diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
430 files changed, 44116 insertions, 15786 deletions
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index ff80f12480e..637c29a3312 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -3,6 +3,7 @@ config DRM_NOUVEAU  	depends on DRM && PCI          select FW_LOADER  	select DRM_KMS_HELPER +	select DRM_KMS_FB_HELPER  	select DRM_TTM  	select FB_CFB_FILLRECT  	select FB_CFB_COPYAREA @@ -10,7 +11,7 @@ config DRM_NOUVEAU  	select FB  	select FRAMEBUFFER_CONSOLE if !EXPERT  	select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT -	select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT +	select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT  	select X86_PLATFORM_DEVICES if ACPI && X86  	select ACPI_WMI if ACPI && X86  	select MXM_WMI if ACPI && X86 @@ -18,7 +19,6 @@ config DRM_NOUVEAU  	# Similar to i915, we need to select ACPI_VIDEO and it's dependencies  	select BACKLIGHT_LCD_SUPPORT if ACPI && X86  	select BACKLIGHT_CLASS_DEVICE if ACPI && X86 -	select VIDEO_OUTPUT_CONTROL if ACPI && X86  	select INPUT if ACPI && X86  	select THERMAL if ACPI && X86  	select ACPI_VIDEO if ACPI && X86 diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index d939a1da320..8b307e14363 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -28,7 +28,9 @@ nouveau-y += core/subdev/bar/nv50.o  nouveau-y += core/subdev/bar/nvc0.o  nouveau-y += core/subdev/bios/base.o  nouveau-y += core/subdev/bios/bit.o +nouveau-y += core/subdev/bios/boost.o  nouveau-y += core/subdev/bios/conn.o +nouveau-y += core/subdev/bios/cstep.o  nouveau-y += core/subdev/bios/dcb.o  nouveau-y += core/subdev/bios/disp.o  nouveau-y += core/subdev/bios/dp.o @@ -39,17 +41,29 @@ nouveau-y += core/subdev/bios/init.o  nouveau-y += core/subdev/bios/mxm.o  nouveau-y += core/subdev/bios/perf.o  nouveau-y += core/subdev/bios/pll.o +nouveau-y += core/subdev/bios/ramcfg.o +nouveau-y += core/subdev/bios/rammap.o +nouveau-y += core/subdev/bios/timing.o  nouveau-y += core/subdev/bios/therm.o +nouveau-y += core/subdev/bios/vmap.o +nouveau-y += core/subdev/bios/volt.o  nouveau-y += core/subdev/bios/xpio.o +nouveau-y += core/subdev/bios/P0260.o +nouveau-y += core/subdev/bus/hwsq.o  nouveau-y += core/subdev/bus/nv04.o  nouveau-y += core/subdev/bus/nv31.o  nouveau-y += core/subdev/bus/nv50.o +nouveau-y += core/subdev/bus/nv94.o  nouveau-y += core/subdev/bus/nvc0.o +nouveau-y += core/subdev/clock/base.o  nouveau-y += core/subdev/clock/nv04.o  nouveau-y += core/subdev/clock/nv40.o  nouveau-y += core/subdev/clock/nv50.o +nouveau-y += core/subdev/clock/nv84.o  nouveau-y += core/subdev/clock/nva3.o +nouveau-y += core/subdev/clock/nvaa.o  nouveau-y += core/subdev/clock/nvc0.o +nouveau-y += core/subdev/clock/nve0.o  nouveau-y += core/subdev/clock/pllnv04.o  nouveau-y += core/subdev/clock/pllnva3.o  nouveau-y += core/subdev/devinit/base.o @@ -59,8 +73,12 @@ nouveau-y += core/subdev/devinit/nv10.o  nouveau-y += core/subdev/devinit/nv1a.o  nouveau-y += core/subdev/devinit/nv20.o  nouveau-y += core/subdev/devinit/nv50.o +nouveau-y += core/subdev/devinit/nv84.o +nouveau-y += core/subdev/devinit/nv98.o  nouveau-y += core/subdev/devinit/nva3.o +nouveau-y += core/subdev/devinit/nvaf.o  nouveau-y += core/subdev/devinit/nvc0.o +nouveau-y += core/subdev/devinit/gm107.o  nouveau-y += core/subdev/fb/base.o  nouveau-y += core/subdev/fb/nv04.o  nouveau-y += core/subdev/fb/nv10.o @@ -78,7 +96,14 @@ nouveau-y += core/subdev/fb/nv47.o  nouveau-y += core/subdev/fb/nv49.o  nouveau-y += core/subdev/fb/nv4e.o  nouveau-y += core/subdev/fb/nv50.o +nouveau-y += core/subdev/fb/nv84.o +nouveau-y += core/subdev/fb/nva3.o +nouveau-y += core/subdev/fb/nvaa.o +nouveau-y += core/subdev/fb/nvaf.o  nouveau-y += core/subdev/fb/nvc0.o +nouveau-y += core/subdev/fb/nve0.o +nouveau-y += core/subdev/fb/gk20a.o +nouveau-y += core/subdev/fb/gm107.o  nouveau-y += core/subdev/fb/ramnv04.o  nouveau-y += core/subdev/fb/ramnv10.o  nouveau-y += core/subdev/fb/ramnv1a.o @@ -89,37 +114,62 @@ nouveau-y += core/subdev/fb/ramnv44.o  nouveau-y += core/subdev/fb/ramnv49.o  nouveau-y += core/subdev/fb/ramnv4e.o  nouveau-y += core/subdev/fb/ramnv50.o +nouveau-y += core/subdev/fb/ramnva3.o +nouveau-y += core/subdev/fb/ramnvaa.o  nouveau-y += core/subdev/fb/ramnvc0.o +nouveau-y += core/subdev/fb/ramnve0.o +nouveau-y += core/subdev/fb/ramgk20a.o +nouveau-y += core/subdev/fb/ramgm107.o +nouveau-y += core/subdev/fb/sddr3.o +nouveau-y += core/subdev/fb/gddr5.o  nouveau-y += core/subdev/gpio/base.o  nouveau-y += core/subdev/gpio/nv10.o  nouveau-y += core/subdev/gpio/nv50.o +nouveau-y += core/subdev/gpio/nv92.o  nouveau-y += core/subdev/gpio/nvd0.o  nouveau-y += core/subdev/gpio/nve0.o  nouveau-y += core/subdev/i2c/base.o  nouveau-y += core/subdev/i2c/anx9805.o  nouveau-y += core/subdev/i2c/aux.o  nouveau-y += core/subdev/i2c/bit.o +nouveau-y += core/subdev/i2c/pad.o +nouveau-y += core/subdev/i2c/padnv04.o +nouveau-y += core/subdev/i2c/padnv94.o  nouveau-y += core/subdev/i2c/nv04.o  nouveau-y += core/subdev/i2c/nv4e.o  nouveau-y += core/subdev/i2c/nv50.o  nouveau-y += core/subdev/i2c/nv94.o  nouveau-y += core/subdev/i2c/nvd0.o +nouveau-y += core/subdev/i2c/gf117.o +nouveau-y += core/subdev/i2c/nve0.o  nouveau-y += core/subdev/ibus/nvc0.o  nouveau-y += core/subdev/ibus/nve0.o +nouveau-y += core/subdev/ibus/gk20a.o  nouveau-y += core/subdev/instmem/base.o  nouveau-y += core/subdev/instmem/nv04.o  nouveau-y += core/subdev/instmem/nv40.o  nouveau-y += core/subdev/instmem/nv50.o -nouveau-y += core/subdev/ltcg/nvc0.o +nouveau-y += core/subdev/ltcg/gf100.o +nouveau-y += core/subdev/ltcg/gm107.o  nouveau-y += core/subdev/mc/base.o  nouveau-y += core/subdev/mc/nv04.o +nouveau-y += core/subdev/mc/nv40.o  nouveau-y += core/subdev/mc/nv44.o +nouveau-y += core/subdev/mc/nv4c.o  nouveau-y += core/subdev/mc/nv50.o +nouveau-y += core/subdev/mc/nv94.o  nouveau-y += core/subdev/mc/nv98.o  nouveau-y += core/subdev/mc/nvc0.o +nouveau-y += core/subdev/mc/nvc3.o  nouveau-y += core/subdev/mxm/base.o  nouveau-y += core/subdev/mxm/mxms.o  nouveau-y += core/subdev/mxm/nv50.o +nouveau-y += core/subdev/pwr/base.o +nouveau-y += core/subdev/pwr/memx.o +nouveau-y += core/subdev/pwr/nva3.o +nouveau-y += core/subdev/pwr/nvc0.o +nouveau-y += core/subdev/pwr/nvd0.o +nouveau-y += core/subdev/pwr/nv108.o  nouveau-y += core/subdev/therm/base.o  nouveau-y += core/subdev/therm/fan.o  nouveau-y += core/subdev/therm/fannil.o @@ -134,12 +184,16 @@ nouveau-y += core/subdev/therm/nva3.o  nouveau-y += core/subdev/therm/nvd0.o  nouveau-y += core/subdev/timer/base.o  nouveau-y += core/subdev/timer/nv04.o +nouveau-y += core/subdev/timer/gk20a.o  nouveau-y += core/subdev/vm/base.o  nouveau-y += core/subdev/vm/nv04.o  nouveau-y += core/subdev/vm/nv41.o  nouveau-y += core/subdev/vm/nv44.o  nouveau-y += core/subdev/vm/nv50.o  nouveau-y += core/subdev/vm/nvc0.o +nouveau-y += core/subdev/volt/base.o +nouveau-y += core/subdev/volt/gpio.o +nouveau-y += core/subdev/volt/nv40.o  nouveau-y += core/engine/falcon.o  nouveau-y += core/engine/xtensa.o @@ -158,6 +212,7 @@ nouveau-y += core/engine/copy/nve0.o  nouveau-y += core/engine/crypt/nv84.o  nouveau-y += core/engine/crypt/nv98.o  nouveau-y += core/engine/device/base.o +nouveau-y += core/engine/device/ctrl.o  nouveau-y += core/engine/device/nv04.o  nouveau-y += core/engine/device/nv10.o  nouveau-y += core/engine/device/nv20.o @@ -166,7 +221,11 @@ nouveau-y += core/engine/device/nv40.o  nouveau-y += core/engine/device/nv50.o  nouveau-y += core/engine/device/nvc0.o  nouveau-y += core/engine/device/nve0.o +nouveau-y += core/engine/device/gm100.o  nouveau-y += core/engine/disp/base.o +nouveau-y += core/engine/disp/conn.o +nouveau-y += core/engine/disp/outp.o +nouveau-y += core/engine/disp/outpdp.o  nouveau-y += core/engine/disp/nv04.o  nouveau-y += core/engine/disp/nv50.o  nouveau-y += core/engine/disp/nv84.o @@ -176,6 +235,7 @@ nouveau-y += core/engine/disp/nva3.o  nouveau-y += core/engine/disp/nvd0.o  nouveau-y += core/engine/disp/nve0.o  nouveau-y += core/engine/disp/nvf0.o +nouveau-y += core/engine/disp/gm107.o  nouveau-y += core/engine/disp/dacnv50.o  nouveau-y += core/engine/disp/dport.o  nouveau-y += core/engine/disp/hdanva3.o @@ -197,16 +257,21 @@ nouveau-y += core/engine/fifo/nv50.o  nouveau-y += core/engine/fifo/nv84.o  nouveau-y += core/engine/fifo/nvc0.o  nouveau-y += core/engine/fifo/nve0.o +nouveau-y += core/engine/fifo/gk20a.o +nouveau-y += core/engine/fifo/nv108.o  nouveau-y += core/engine/graph/ctxnv40.o  nouveau-y += core/engine/graph/ctxnv50.o  nouveau-y += core/engine/graph/ctxnvc0.o  nouveau-y += core/engine/graph/ctxnvc1.o -nouveau-y += core/engine/graph/ctxnvc3.o +nouveau-y += core/engine/graph/ctxnvc4.o  nouveau-y += core/engine/graph/ctxnvc8.o  nouveau-y += core/engine/graph/ctxnvd7.o  nouveau-y += core/engine/graph/ctxnvd9.o  nouveau-y += core/engine/graph/ctxnve4.o +nouveau-y += core/engine/graph/ctxgk20a.o  nouveau-y += core/engine/graph/ctxnvf0.o +nouveau-y += core/engine/graph/ctxnv108.o +nouveau-y += core/engine/graph/ctxgm107.o  nouveau-y += core/engine/graph/nv04.o  nouveau-y += core/engine/graph/nv10.o  nouveau-y += core/engine/graph/nv20.o @@ -219,16 +284,29 @@ nouveau-y += core/engine/graph/nv40.o  nouveau-y += core/engine/graph/nv50.o  nouveau-y += core/engine/graph/nvc0.o  nouveau-y += core/engine/graph/nvc1.o -nouveau-y += core/engine/graph/nvc3.o +nouveau-y += core/engine/graph/nvc4.o  nouveau-y += core/engine/graph/nvc8.o  nouveau-y += core/engine/graph/nvd7.o  nouveau-y += core/engine/graph/nvd9.o  nouveau-y += core/engine/graph/nve4.o +nouveau-y += core/engine/graph/gk20a.o  nouveau-y += core/engine/graph/nvf0.o +nouveau-y += core/engine/graph/nv108.o +nouveau-y += core/engine/graph/gm107.o  nouveau-y += core/engine/mpeg/nv31.o  nouveau-y += core/engine/mpeg/nv40.o +nouveau-y += core/engine/mpeg/nv44.o  nouveau-y += core/engine/mpeg/nv50.o  nouveau-y += core/engine/mpeg/nv84.o +nouveau-y += core/engine/perfmon/base.o +nouveau-y += core/engine/perfmon/daemon.o +nouveau-y += core/engine/perfmon/nv40.o +nouveau-y += core/engine/perfmon/nv50.o +nouveau-y += core/engine/perfmon/nv84.o +nouveau-y += core/engine/perfmon/nva3.o +nouveau-y += core/engine/perfmon/nvc0.o +nouveau-y += core/engine/perfmon/nve0.o +nouveau-y += core/engine/perfmon/nvf0.o  nouveau-y += core/engine/ppp/nv98.o  nouveau-y += core/engine/ppp/nvc0.o  nouveau-y += core/engine/software/nv04.o @@ -260,9 +338,7 @@ include $(src)/dispnv04/Makefile  nouveau-y += nv50_display.o  # drm/pm -nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o -nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o -nouveau-y += nouveau_mem.o +nouveau-y += nouveau_hwmon.o nouveau_sysfs.o  # other random bits  nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o diff --git a/drivers/gpu/drm/nouveau/core/core/engine.c b/drivers/gpu/drm/nouveau/core/core/engine.c index c8bed4a2683..1f6954ae9dd 100644 --- a/drivers/gpu/drm/nouveau/core/core/engine.c +++ b/drivers/gpu/drm/nouveau/core/core/engine.c @@ -42,11 +42,24 @@ nouveau_engine_create_(struct nouveau_object *parent,  	if (ret)  		return ret; -	if ( parent && -	    !nouveau_boolopt(nv_device(parent)->cfgopt, iname, enable)) { -		if (!enable) -			nv_warn(engine, "disabled, %s=1 to enable\n", iname); -		return -ENODEV; +	if (parent) { +		struct nouveau_device *device = nv_device(parent); +		int engidx = nv_engidx(nv_object(engine)); + +		if (device->disable_mask & (1ULL << engidx)) { +			if (!nouveau_boolopt(device->cfgopt, iname, false)) { +				nv_debug(engine, "engine disabled by hw/fw\n"); +				return -ENODEV; +			} + +			nv_warn(engine, "ignoring hw/fw engine disable\n"); +		} + +		if (!nouveau_boolopt(device->cfgopt, iname, enable)) { +			if (!enable) +				nv_warn(engine, "disabled, %s=1 to enable\n", iname); +			return -ENODEV; +		}  	}  	INIT_LIST_HEAD(&engine->contexts); diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c index 7eb81c1b6fa..ae81d3b5d8b 100644 --- a/drivers/gpu/drm/nouveau/core/core/event.c +++ b/drivers/gpu/drm/nouveau/core/core/event.c @@ -23,62 +23,140 @@  #include <core/os.h>  #include <core/event.h> -static void -nouveau_event_put_locked(struct nouveau_event *event, int index, -			 struct nouveau_eventh *handler) +void +nouveau_event_put(struct nouveau_eventh *handler)  { -	if (!--event->index[index].refs) { -		if (event->disable) -			event->disable(event, index); +	struct nouveau_event *event = handler->event; +	unsigned long flags; +	u32 m, t; + +	if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) +		return; + +	spin_lock_irqsave(&event->refs_lock, flags); +	for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) { +		if (!--event->refs[handler->index * event->types_nr + t]) { +			if (event->disable) +				event->disable(event, 1 << t, handler->index); +		} +  	} -	list_del(&handler->head); +	spin_unlock_irqrestore(&event->refs_lock, flags);  }  void -nouveau_event_put(struct nouveau_event *event, int index, -		  struct nouveau_eventh *handler) +nouveau_event_get(struct nouveau_eventh *handler)  { +	struct nouveau_event *event = handler->event;  	unsigned long flags; +	u32 m, t; + +	if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) +		return; + +	spin_lock_irqsave(&event->refs_lock, flags); +	for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) { +		if (!event->refs[handler->index * event->types_nr + t]++) { +			if (event->enable) +				event->enable(event, 1 << t, handler->index); +		} -	spin_lock_irqsave(&event->lock, flags); -	if (index < event->index_nr) -		nouveau_event_put_locked(event, index, handler); -	spin_unlock_irqrestore(&event->lock, flags); +	} +	spin_unlock_irqrestore(&event->refs_lock, flags);  } -void -nouveau_event_get(struct nouveau_event *event, int index, -		  struct nouveau_eventh *handler) +static void +nouveau_event_fini(struct nouveau_eventh *handler) +{ +	struct nouveau_event *event = handler->event; +	unsigned long flags; +	nouveau_event_put(handler); +	spin_lock_irqsave(&event->list_lock, flags); +	list_del(&handler->head); +	spin_unlock_irqrestore(&event->list_lock, flags); +} + +static int +nouveau_event_init(struct nouveau_event *event, u32 types, int index, +		   int (*func)(void *, u32, int), void *priv, +		   struct nouveau_eventh *handler)  {  	unsigned long flags; -	spin_lock_irqsave(&event->lock, flags); -	if (index < event->index_nr) { -		list_add(&handler->head, &event->index[index].list); -		if (!event->index[index].refs++) { -			if (event->enable) -				event->enable(event, index); -		} +	if (types & ~((1 << event->types_nr) - 1)) +		return -EINVAL; +	if (index >= event->index_nr) +		return -EINVAL; + +	handler->event = event; +	handler->flags = 0; +	handler->types = types; +	handler->index = index; +	handler->func = func; +	handler->priv = priv; + +	spin_lock_irqsave(&event->list_lock, flags); +	list_add_tail(&handler->head, &event->list[index]); +	spin_unlock_irqrestore(&event->list_lock, flags); +	return 0; +} + +int +nouveau_event_new(struct nouveau_event *event, u32 types, int index, +		  int (*func)(void *, u32, int), void *priv, +		  struct nouveau_eventh **phandler) +{ +	struct nouveau_eventh *handler; +	int ret = -ENOMEM; + +	if (event->check) { +		ret = event->check(event, types, index); +		if (ret) +			return ret;  	} -	spin_unlock_irqrestore(&event->lock, flags); + +	handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL); +	if (handler) { +		ret = nouveau_event_init(event, types, index, func, priv, handler); +		if (ret) +			kfree(handler); +	} + +	return ret;  }  void -nouveau_event_trigger(struct nouveau_event *event, int index) +nouveau_event_ref(struct nouveau_eventh *handler, struct nouveau_eventh **ref)  { -	struct nouveau_eventh *handler, *temp; +	BUG_ON(handler != NULL); +	if (*ref) { +		nouveau_event_fini(*ref); +		kfree(*ref); +	} +	*ref = handler; +} + +void +nouveau_event_trigger(struct nouveau_event *event, u32 types, int index) +{ +	struct nouveau_eventh *handler;  	unsigned long flags; -	if (index >= event->index_nr) +	if (WARN_ON(index >= event->index_nr))  		return; -	spin_lock_irqsave(&event->lock, flags); -	list_for_each_entry_safe(handler, temp, &event->index[index].list, head) { -		if (handler->func(handler, index) == NVKM_EVENT_DROP) { -			nouveau_event_put_locked(event, index, handler); -		} +	spin_lock_irqsave(&event->list_lock, flags); +	list_for_each_entry(handler, &event->list[index], head) { +		if (!test_bit(NVKM_EVENT_ENABLE, &handler->flags)) +			continue; +		if (!(handler->types & types)) +			continue; +		if (handler->func(handler->priv, handler->types & types, index) +				!= NVKM_EVENT_DROP) +			continue; +		nouveau_event_put(handler);  	} -	spin_unlock_irqrestore(&event->lock, flags); +	spin_unlock_irqrestore(&event->list_lock, flags);  }  void @@ -92,19 +170,27 @@ nouveau_event_destroy(struct nouveau_event **pevent)  }  int -nouveau_event_create(int index_nr, struct nouveau_event **pevent) +nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **pevent)  {  	struct nouveau_event *event;  	int i; -	event = *pevent = kzalloc(sizeof(*event) + index_nr * -				  sizeof(event->index[0]), GFP_KERNEL); +	event = *pevent = kzalloc(sizeof(*event) + (index_nr * types_nr) * +				  sizeof(event->refs[0]), GFP_KERNEL);  	if (!event)  		return -ENOMEM; -	spin_lock_init(&event->lock); +	event->list = kmalloc(sizeof(*event->list) * index_nr, GFP_KERNEL); +	if (!event->list) { +		kfree(event); +		return -ENOMEM; +	} + +	spin_lock_init(&event->list_lock); +	spin_lock_init(&event->refs_lock);  	for (i = 0; i < index_nr; i++) -		INIT_LIST_HEAD(&event->index[i].list); +		INIT_LIST_HEAD(&event->list[i]); +	event->types_nr = types_nr;  	event->index_nr = index_nr;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/core/namedb.c b/drivers/gpu/drm/nouveau/core/core/namedb.c index 1ce95a8709d..0594a599f6f 100644 --- a/drivers/gpu/drm/nouveau/core/core/namedb.c +++ b/drivers/gpu/drm/nouveau/core/core/namedb.c @@ -167,7 +167,7 @@ int  nouveau_namedb_create_(struct nouveau_object *parent,  		       struct nouveau_object *engine,  		       struct nouveau_oclass *oclass, u32 pclass, -		       struct nouveau_oclass *sclass, u32 engcls, +		       struct nouveau_oclass *sclass, u64 engcls,  		       int length, void **pobject)  {  	struct nouveau_namedb *namedb; diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c index 7f48e288215..12453855590 100644 --- a/drivers/gpu/drm/nouveau/core/core/object.c +++ b/drivers/gpu/drm/nouveau/core/core/object.c @@ -156,7 +156,7 @@ nouveau_object_ctor(struct nouveau_object *parent,  	}  	if (ret == 0) { -		nv_debug(object, "created\n"); +		nv_trace(object, "created\n");  		atomic_set(&object->refcount, 1);  	} @@ -166,7 +166,7 @@ nouveau_object_ctor(struct nouveau_object *parent,  static void  nouveau_object_dtor(struct nouveau_object *object)  { -	nv_debug(object, "destroying\n"); +	nv_trace(object, "destroying\n");  	nv_ofuncs(object)->dtor(object);  } @@ -337,7 +337,7 @@ nouveau_object_inc(struct nouveau_object *object)  		goto fail_self;  	} -	nv_debug(object, "initialised\n"); +	nv_trace(object, "initialised\n");  	return 0;  fail_self: @@ -375,7 +375,7 @@ nouveau_object_decf(struct nouveau_object *object)  	if (object->parent)  		nouveau_object_dec(object->parent, false); -	nv_debug(object, "stopped\n"); +	nv_trace(object, "stopped\n");  	return 0;  } @@ -411,7 +411,7 @@ nouveau_object_decs(struct nouveau_object *object)  		}  	} -	nv_debug(object, "suspended\n"); +	nv_trace(object, "suspended\n");  	return 0;  fail_parent: diff --git a/drivers/gpu/drm/nouveau/core/core/option.c b/drivers/gpu/drm/nouveau/core/core/option.c index 62a432ea39e..9f6fcc5f66c 100644 --- a/drivers/gpu/drm/nouveau/core/core/option.c +++ b/drivers/gpu/drm/nouveau/core/core/option.c @@ -25,15 +25,6 @@  #include <core/option.h>  #include <core/debug.h> -/* compares unterminated string 'str' with zero-terminated string 'cmp' */ -static inline int -strncasecmpz(const char *str, const char *cmp, size_t len) -{ -	if (strlen(cmp) != len) -		return len; -	return strncasecmp(str, cmp, len); -} -  const char *  nouveau_stropt(const char *optstr, const char *opt, int *arglen)  { @@ -105,7 +96,7 @@ nouveau_dbgopt(const char *optstr, const char *sub)  				else if (!strncasecmpz(optstr, "warn", len))  					level = NV_DBG_WARN;  				else if (!strncasecmpz(optstr, "info", len)) -					level = NV_DBG_INFO; +					level = NV_DBG_INFO_NORMAL;  				else if (!strncasecmpz(optstr, "debug", len))  					level = NV_DBG_DEBUG;  				else if (!strncasecmpz(optstr, "trace", len)) diff --git a/drivers/gpu/drm/nouveau/core/core/parent.c b/drivers/gpu/drm/nouveau/core/core/parent.c index 313380ce632..dee5d1235e9 100644 --- a/drivers/gpu/drm/nouveau/core/core/parent.c +++ b/drivers/gpu/drm/nouveau/core/core/parent.c @@ -49,7 +49,7 @@ nouveau_parent_sclass(struct nouveau_object *parent, u16 handle,  	mask = nv_parent(parent)->engine;  	while (mask) { -		int i = ffsll(mask) - 1; +		int i = __ffs64(mask);  		if (nv_iclass(parent, NV_CLIENT_CLASS))  			engine = nv_engine(nv_client(parent)->device); diff --git a/drivers/gpu/drm/nouveau/core/core/printk.c b/drivers/gpu/drm/nouveau/core/core/printk.c index 52fb2aa129e..03e0060b13d 100644 --- a/drivers/gpu/drm/nouveau/core/core/printk.c +++ b/drivers/gpu/drm/nouveau/core/core/printk.c @@ -27,16 +27,38 @@  #include <core/subdev.h>  #include <core/printk.h> -int nv_printk_suspend_level = NV_DBG_DEBUG; +int nv_info_debug_level = NV_DBG_INFO_NORMAL;  void -nv_printk_(struct nouveau_object *object, const char *pfx, int level, -	   const char *fmt, ...) +nv_printk_(struct nouveau_object *object, int level, const char *fmt, ...)  {  	static const char name[] = { '!', 'E', 'W', ' ', 'D', 'T', 'P', 'S' }; +	const char *pfx;  	char mfmt[256];  	va_list args; +	switch (level) { +	case NV_DBG_FATAL: +		pfx = KERN_CRIT; +		break; +	case NV_DBG_ERROR: +		pfx = KERN_ERR; +		break; +	case NV_DBG_WARN: +		pfx = KERN_WARNING; +		break; +	case NV_DBG_INFO_NORMAL: +		pfx = KERN_INFO; +		break; +	case NV_DBG_DEBUG: +	case NV_DBG_PARANOIA: +	case NV_DBG_TRACE: +	case NV_DBG_SPAM: +	default: +		pfx = KERN_DEBUG; +		break; +	} +  	if (object && !nv_iclass(object, NV_CLIENT_CLASS)) {  		struct nouveau_object *device = object;  		struct nouveau_object *subdev = object; @@ -74,20 +96,3 @@ nv_printk_(struct nouveau_object *object, const char *pfx, int level,  	vprintk(mfmt, args);  	va_end(args);  } - -#define CONV_LEVEL(x) case NV_DBG_##x: return NV_PRINTK_##x - -const char *nv_printk_level_to_pfx(int level) -{ -	switch (level) { -	CONV_LEVEL(FATAL); -	CONV_LEVEL(ERROR); -	CONV_LEVEL(WARN); -	CONV_LEVEL(INFO); -	CONV_LEVEL(DEBUG); -	CONV_LEVEL(PARANOIA); -	CONV_LEVEL(TRACE); -	CONV_LEVEL(SPAM); -	} -	return NV_PRINTK_DEBUG; -} diff --git a/drivers/gpu/drm/nouveau/core/core/subdev.c b/drivers/gpu/drm/nouveau/core/core/subdev.c index 48f06378d3f..2ea5568b6cf 100644 --- a/drivers/gpu/drm/nouveau/core/core/subdev.c +++ b/drivers/gpu/drm/nouveau/core/core/subdev.c @@ -104,11 +104,8 @@ nouveau_subdev_create_(struct nouveau_object *parent,  	if (parent) {  		struct nouveau_device *device = nv_device(parent); -		int subidx = nv_hclass(subdev) & 0xff; -  		subdev->debug = nouveau_dbgopt(device->dbgopt, subname);  		subdev->mmio  = nv_subdev(device)->mmio; -		device->subdev[subidx] = *pobject;  	}  	return 0; diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c index 993df09ad64..ac3291f781f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nvc0.c @@ -105,9 +105,6 @@ nvc0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nvc0_copy_priv *priv;  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000100) -		return -ENODEV; -  	ret = nouveau_falcon_create(parent, engine, oclass, 0x104000, true,  				    "PCE0", "copy0", &priv);  	*pobject = nv_object(priv); @@ -133,9 +130,6 @@ nvc0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nvc0_copy_priv *priv;  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000200) -		return -ENODEV; -  	ret = nouveau_falcon_create(parent, engine, oclass, 0x105000, true,  				    "PCE1", "copy1", &priv);  	*pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c index 30f1ef1edcc..748a61eb3c6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nve0.c @@ -88,9 +88,6 @@ nve0_copy0_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nve0_copy_priv *priv;  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000100) -		return -ENODEV; -  	ret = nouveau_engine_create(parent, engine, oclass, true,  				    "PCE0", "copy0", &priv);  	*pobject = nv_object(priv); @@ -112,9 +109,6 @@ nve0_copy1_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nve0_copy_priv *priv;  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000200) -		return -ENODEV; -  	ret = nouveau_engine_create(parent, engine, oclass, true,  				    "PCE1", "copy1", &priv);  	*pobject = nv_object(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c index 4c72571655a..18c8c7245b7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c @@ -29,7 +29,7 @@  #include <core/class.h> -#include <engine/device.h> +#include "priv.h"  static DEFINE_MUTEX(nv_devices_mutex);  static LIST_HEAD(nv_devices); @@ -75,7 +75,9 @@ static const u64 disable_map[] = {  	[NVDEV_SUBDEV_BAR]	= NV_DEVICE_DISABLE_CORE,  	[NVDEV_SUBDEV_VOLT]	= NV_DEVICE_DISABLE_CORE,  	[NVDEV_SUBDEV_THERM]	= NV_DEVICE_DISABLE_CORE, +	[NVDEV_SUBDEV_PWR]	= NV_DEVICE_DISABLE_CORE,  	[NVDEV_ENGINE_DMAOBJ]	= NV_DEVICE_DISABLE_CORE, +	[NVDEV_ENGINE_PERFMON]  = NV_DEVICE_DISABLE_CORE,  	[NVDEV_ENGINE_FIFO]	= NV_DEVICE_DISABLE_FIFO,  	[NVDEV_ENGINE_SW]	= NV_DEVICE_DISABLE_FIFO,  	[NVDEV_ENGINE_GR]	= NV_DEVICE_DISABLE_GRAPH, @@ -87,7 +89,7 @@ static const u64 disable_map[] = {  	[NVDEV_ENGINE_PPP]	= NV_DEVICE_DISABLE_PPP,  	[NVDEV_ENGINE_COPY0]	= NV_DEVICE_DISABLE_COPY0,  	[NVDEV_ENGINE_COPY1]	= NV_DEVICE_DISABLE_COPY1, -	[NVDEV_ENGINE_UNK1C1]	= NV_DEVICE_DISABLE_UNK1C1, +	[NVDEV_ENGINE_VIC]	= NV_DEVICE_DISABLE_VIC,  	[NVDEV_ENGINE_VENC]	= NV_DEVICE_DISABLE_VENC,  	[NVDEV_ENGINE_DISP]	= NV_DEVICE_DISABLE_DISP,  	[NVDEV_SUBDEV_NR]	= 0, @@ -119,16 +121,18 @@ nouveau_devobj_ctor(struct nouveau_object *parent,  			return -ENODEV;  	} -	ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, NULL, +	ret = nouveau_parent_create(parent, nv_object(device), oclass, 0, +				    nouveau_control_oclass,  				    (1ULL << NVDEV_ENGINE_DMAOBJ) |  				    (1ULL << NVDEV_ENGINE_FIFO) | -				    (1ULL << NVDEV_ENGINE_DISP), &devobj); +				    (1ULL << NVDEV_ENGINE_DISP) | +				    (1ULL << NVDEV_ENGINE_PERFMON), &devobj);  	*pobject = nv_object(devobj);  	if (ret)  		return ret; -	mmio_base = pci_resource_start(device->pdev, 0); -	mmio_size = pci_resource_len(device->pdev, 0); +	mmio_base = nv_device_resource_start(device, 0); +	mmio_size = nv_device_resource_len(device, 0);  	/* translate api disable mask into internal mapping */  	disable = args->debug0; @@ -158,22 +162,30 @@ nouveau_devobj_ctor(struct nouveau_object *parent,  		iounmap(map);  		/* determine chipset and derive architecture from it */ -		if ((boot0 & 0x0f000000) > 0) { -			device->chipset = (boot0 & 0xff00000) >> 20; -			switch (device->chipset & 0xf0) { -			case 0x10: device->card_type = NV_10; break; -			case 0x20: device->card_type = NV_20; break; -			case 0x30: device->card_type = NV_30; break; -			case 0x40: -			case 0x60: device->card_type = NV_40; break; -			case 0x50: -			case 0x80: -			case 0x90: -			case 0xa0: device->card_type = NV_50; break; -			case 0xc0: device->card_type = NV_C0; break; -			case 0xd0: device->card_type = NV_D0; break; -			case 0xe0: -			case 0xf0: device->card_type = NV_E0; break; +		if ((boot0 & 0x1f000000) > 0) { +			device->chipset = (boot0 & 0x1ff00000) >> 20; +			switch (device->chipset & 0x1f0) { +			case 0x010: { +				if (0x461 & (1 << (device->chipset & 0xf))) +					device->card_type = NV_10; +				else +					device->card_type = NV_11; +				break; +			} +			case 0x020: device->card_type = NV_20; break; +			case 0x030: device->card_type = NV_30; break; +			case 0x040: +			case 0x060: device->card_type = NV_40; break; +			case 0x050: +			case 0x080: +			case 0x090: +			case 0x0a0: device->card_type = NV_50; break; +			case 0x0c0: device->card_type = NV_C0; break; +			case 0x0d0: device->card_type = NV_D0; break; +			case 0x0e0: +			case 0x0f0: +			case 0x100: device->card_type = NV_E0; break; +			case 0x110: device->card_type = GM100; break;  			default:  				break;  			} @@ -188,7 +200,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,  		switch (device->card_type) {  		case NV_04: ret = nv04_identify(device); break; -		case NV_10: ret = nv10_identify(device); break; +		case NV_10: +		case NV_11: ret = nv10_identify(device); break;  		case NV_20: ret = nv20_identify(device); break;  		case NV_30: ret = nv30_identify(device); break;  		case NV_40: ret = nv40_identify(device); break; @@ -196,6 +209,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,  		case NV_C0:  		case NV_D0: ret = nvc0_identify(device); break;  		case NV_E0: ret = nve0_identify(device); break; +		case GM100: ret = gm100_identify(device); break;  		default:  			ret = -EINVAL;  			break; @@ -212,7 +226,7 @@ nouveau_devobj_ctor(struct nouveau_object *parent,  		nv_info(device, "Family : NV%02X\n", device->card_type);  		/* determine frequency of timing crystal */ -		if ( device->chipset < 0x17 || +		if ( device->card_type <= NV_10 || device->chipset < 0x17 ||  		    (device->chipset >= 0x20 && device->chipset < 0x25))  			strap &= 0x00000040;  		else @@ -256,6 +270,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent,  		if (ret)  			return ret; +		device->subdev[i] = devobj->subdev[i]; +  		/* note: can't init *any* subdevs until devinit has been run  		 * due to not knowing exactly what the vbios init tables will  		 * mess with.  devinit also can't be run until all of its @@ -432,6 +448,72 @@ nouveau_device_dtor(struct nouveau_object *object)  	nouveau_engine_destroy(&device->base);  } +resource_size_t +nv_device_resource_start(struct nouveau_device *device, unsigned int bar) +{ +	if (nv_device_is_pci(device)) { +		return pci_resource_start(device->pdev, bar); +	} else { +		struct resource *res; +		res = platform_get_resource(device->platformdev, +					    IORESOURCE_MEM, bar); +		if (!res) +			return 0; +		return res->start; +	} +} + +resource_size_t +nv_device_resource_len(struct nouveau_device *device, unsigned int bar) +{ +	if (nv_device_is_pci(device)) { +		return pci_resource_len(device->pdev, bar); +	} else { +		struct resource *res; +		res = platform_get_resource(device->platformdev, +					    IORESOURCE_MEM, bar); +		if (!res) +			return 0; +		return resource_size(res); +	} +} + +dma_addr_t +nv_device_map_page(struct nouveau_device *device, struct page *page) +{ +	dma_addr_t ret; + +	if (nv_device_is_pci(device)) { +		ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE, +				   PCI_DMA_BIDIRECTIONAL); +		if (pci_dma_mapping_error(device->pdev, ret)) +			ret = 0; +	} else { +		ret = page_to_phys(page); +	} + +	return ret; +} + +void +nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr) +{ +	if (nv_device_is_pci(device)) +		pci_unmap_page(device->pdev, addr, PAGE_SIZE, +			       PCI_DMA_BIDIRECTIONAL); +} + +int +nv_device_get_irq(struct nouveau_device *device, bool stall) +{ +	if (nv_device_is_pci(device)) { +		return device->pdev->irq; +	} else { +		return platform_get_irq_byname(device->platformdev, +					       stall ? "stall" : "nonstall"); +	} +} +  static struct nouveau_oclass  nouveau_device_oclass = {  	.handle = NV_ENGINE(DEVICE, 0x00), @@ -443,8 +525,8 @@ nouveau_device_oclass = {  };  int -nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname, -		       const char *cfg, const char *dbg, +nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name, +		       const char *sname, const char *cfg, const char *dbg,  		       int length, void **pobject)  {  	struct nouveau_device *device; @@ -462,7 +544,14 @@ nouveau_device_create_(struct pci_dev *pdev, u64 name, const char *sname,  	if (ret)  		goto done; -	device->pdev = pdev; +	switch (type) { +	case NOUVEAU_BUS_PCI: +		device->pdev = dev; +		break; +	case NOUVEAU_BUS_PLATFORM: +		device->platformdev = dev; +		break; +	}  	device->handle = name;  	device->cfgopt = cfg;  	device->dbgopt = dbg; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c new file mode 100644 index 00000000000..4b69bf56ed0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c @@ -0,0 +1,144 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include <core/object.h> +#include <core/class.h> + +#include <subdev/clock.h> + +#include "priv.h" + +static int +nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd, +				void *data, u32 size) +{ +	struct nouveau_clock *clk = nouveau_clock(object); +	struct nv_control_pstate_info *args = data; + +	if (size < sizeof(*args)) +		return -EINVAL; + +	if (clk) { +		args->count  = clk->state_nr; +		args->ustate = clk->ustate; +		args->pstate = clk->pstate; +	} else { +		args->count  = 0; +		args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE; +		args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN; +	} + +	return 0; +} + +static int +nouveau_control_mthd_pstate_attr(struct nouveau_object *object, u32 mthd, +				void *data, u32 size) +{ +	struct nouveau_clock *clk = nouveau_clock(object); +	struct nv_control_pstate_attr *args = data; +	struct nouveau_clocks *domain; +	struct nouveau_pstate *pstate; +	struct nouveau_cstate *cstate; +	int i = 0, j = -1; +	u32 lo, hi; + +	if ((size < sizeof(*args)) || !clk || +	    (args->state >= 0 && args->state >= clk->state_nr)) +		return -EINVAL; +	domain = clk->domains; + +	while (domain->name != nv_clk_src_max) { +		if (domain->mname && ++j == args->index) +			break; +		domain++; +	} + +	if (domain->name == nv_clk_src_max) +		return -EINVAL; + +	if (args->state != NV_CONTROL_PSTATE_ATTR_STATE_CURRENT) { +		list_for_each_entry(pstate, &clk->states, head) { +			if (i++ == args->state) +				break; +		} + +		lo = pstate->base.domain[domain->name]; +		hi = lo; +		list_for_each_entry(cstate, &pstate->list, head) { +			lo = min(lo, cstate->domain[domain->name]); +			hi = max(hi, cstate->domain[domain->name]); +		} + +		args->state = pstate->pstate; +	} else { +		lo = max(clk->read(clk, domain->name), 0); +		hi = lo; +	} + +	snprintf(args->name, sizeof(args->name), "%s", domain->mname); +	snprintf(args->unit, sizeof(args->unit), "MHz"); +	args->min = lo / domain->mdiv; +	args->max = hi / domain->mdiv; + +	args->index = 0; +	while ((++domain)->name != nv_clk_src_max) { +		if (domain->mname) { +			args->index = ++j; +			break; +		} +	} + +	return 0; +} + +static int +nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd, +				void *data, u32 size) +{ +	struct nouveau_clock *clk = nouveau_clock(object); +	struct nv_control_pstate_user *args = data; + +	if (size < sizeof(*args) || !clk) +		return -EINVAL; + +	return nouveau_clock_ustate(clk, args->state); +} + +struct nouveau_oclass +nouveau_control_oclass[] = { +	{ .handle = NV_CONTROL_CLASS, +	  .ofuncs = &nouveau_object_ofuncs, +	  .omthds = (struct nouveau_omthds[]) { +		  { NV_CONTROL_PSTATE_INFO, +		    NV_CONTROL_PSTATE_INFO, nouveau_control_mthd_pstate_info }, +		  { NV_CONTROL_PSTATE_ATTR, +		    NV_CONTROL_PSTATE_ATTR, nouveau_control_mthd_pstate_attr }, +		  { NV_CONTROL_PSTATE_USER, +		    NV_CONTROL_PSTATE_USER, nouveau_control_mthd_pstate_user }, +		  {}, +	  }, +	}, +	{} +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/device/gm100.c b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c new file mode 100644 index 00000000000..a520029e25d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/device/gm100.c @@ -0,0 +1,106 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bus.h> +#include <subdev/gpio.h> +#include <subdev/i2c.h> +#include <subdev/clock.h> +#include <subdev/therm.h> +#include <subdev/mxm.h> +#include <subdev/devinit.h> +#include <subdev/mc.h> +#include <subdev/timer.h> +#include <subdev/fb.h> +#include <subdev/ltcg.h> +#include <subdev/ibus.h> +#include <subdev/instmem.h> +#include <subdev/vm.h> +#include <subdev/bar.h> +#include <subdev/pwr.h> +#include <subdev/volt.h> + +#include <engine/device.h> +#include <engine/dmaobj.h> +#include <engine/fifo.h> +#include <engine/software.h> +#include <engine/graph.h> +#include <engine/disp.h> +#include <engine/copy.h> +#include <engine/bsp.h> +#include <engine/vp.h> +#include <engine/ppp.h> +#include <engine/perfmon.h> + +int +gm100_identify(struct nouveau_device *device) +{ +	switch (device->chipset) { +	case 0x117: +		device->cname = "GM107"; +		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nvd0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass; +#if 0 +		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass; +#endif +		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  gm107_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  gm107_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gm107_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +#if 0 +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass; +#endif +		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  gm107_graph_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  gm107_disp_oclass; +		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass; +#if 0 +		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass; +#endif +		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass; +#if 0 +		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass; +		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass; +		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; +#endif +		break; +	default: +		nv_fatal(device, "unknown Maxwell chipset\n"); +		return -EINVAL; +	} + +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c index a0284cf09c0..40b29d0214c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv04.c @@ -47,38 +47,38 @@ nv04_identify(struct nouveau_device *device)  	case 0x04:  		device->cname = "NV04";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv04_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv04_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv04_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv04_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv04_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv04_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x05:  		device->cname = "NV05";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv05_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv04_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv04_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv04_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv04_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv04_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv04_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv04_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	default:  		nv_fatal(device, "unknown RIVA chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c index 1b7809a095c..5f7c25ff523 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv10.c @@ -48,152 +48,152 @@ nv10_identify(struct nouveau_device *device)  	case 0x10:  		device->cname = "NV10";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x15:  		device->cname = "NV15";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv10_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x16:  		device->cname = "NV16";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv10_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x1a:  		device->cname = "nForce";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv1a_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv10_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x11:  		device->cname = "NV11";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv10_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv10_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x17:  		device->cname = "NV17";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x1f:  		device->cname = "nForce2";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv1a_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv1a_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x18:  		device->cname = "NV18";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv10_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	default:  		nv_fatal(device, "unknown Celsius chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c index 12a4005fa61..75fed11bba0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv20.c @@ -49,78 +49,78 @@ nv20_identify(struct nouveau_device *device)  	case 0x20:  		device->cname = "NV20";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv20_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv20_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv20_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x25:  		device->cname = "NV25";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv25_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv25_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x28:  		device->cname = "NV28";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv25_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv25_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x2a:  		device->cname = "NV2A";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv25_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv25_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv2a_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	default:  		nv_fatal(device, "unknown Kelvin chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c index cef0f1ea4c2..36919d7db7c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv30.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv30.c @@ -49,100 +49,100 @@ nv30_identify(struct nouveau_device *device)  	case 0x30:  		device->cname = "NV30";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv30_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv30_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x35:  		device->cname = "NV35";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv04_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv04_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv35_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv35_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv35_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x31:  		device->cname = "NV31";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv30_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv30_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv30_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x36:  		device->cname = "NV36";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv20_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv36_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv36_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv35_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	case 0x34:  		device->cname = "NV34";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv04_clock_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv10_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv04_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv10_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv10_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv04_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv17_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv17_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv34_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv31_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass;  		break;  	default:  		nv_fatal(device, "unknown Rankine chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c index 1719cb0ee59..1130a62be2c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv40.c @@ -35,6 +35,7 @@  #include <subdev/fb.h>  #include <subdev/instmem.h>  #include <subdev/vm.h> +#include <subdev/volt.h>  #include <engine/device.h>  #include <engine/dmaobj.h> @@ -43,6 +44,7 @@  #include <engine/graph.h>  #include <engine/mpeg.h>  #include <engine/disp.h> +#include <engine/perfmon.h>  int  nv40_identify(struct nouveau_device *device) @@ -51,338 +53,370 @@ nv40_identify(struct nouveau_device *device)  	case 0x40:  		device->cname = "NV40";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x41:  		device->cname = "NV41";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv41_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x42:  		device->cname = "NV42";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv41_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x43:  		device->cname = "NV43";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv41_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv41_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x45:  		device->cname = "NV45";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv40_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv40_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv04_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x47:  		device->cname = "G70";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv47_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv47_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x49:  		device->cname = "G71";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv49_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x4b:  		device->cname = "G73";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv04_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv40_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv49_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv49_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv41_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x44:  		device->cname = "NV44";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv44_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x46:  		device->cname = "G72";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv46_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x4a:  		device->cname = "NV44A";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv44_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv44_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv44_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x4c:  		device->cname = "C61";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv46_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x4e:  		device->cname = "C51";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv4e_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv4e_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv4e_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv4e_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x63:  		device->cname = "C73";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv46_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x67:  		device->cname = "C67";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv46_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	case 0x68:  		device->cname = "C68";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv10_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv04_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv10_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv04_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv40_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv40_therm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv44_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv31_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv1a_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv4c_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv31_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv46_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv46_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv40_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv44_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv04_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv40_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv10_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv40_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv10_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv40_graph_oclass; -		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv40_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv44_mpeg_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv04_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv40_perfmon_oclass;  		break;  	default:  		nv_fatal(device, "unknown Curie chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c index ffc18b80c5d..ef0b0bde1a9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nv50.c @@ -36,6 +36,8 @@  #include <subdev/instmem.h>  #include <subdev/vm.h>  #include <subdev/bar.h> +#include <subdev/pwr.h> +#include <subdev/volt.h>  #include <engine/device.h>  #include <engine/dmaobj.h> @@ -49,6 +51,7 @@  #include <engine/ppp.h>  #include <engine/copy.h>  #include <engine/disp.h> +#include <engine/perfmon.h>  int  nv50_identify(struct nouveau_device *device) @@ -57,364 +60,396 @@ nv50_identify(struct nouveau_device *device)  	case 0x50:  		device->cname = "G80";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv50_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv50_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv50_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv50_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv50_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv50_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv50_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv50_mpeg_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv50_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv50_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv50_perfmon_oclass;  		break;  	case 0x84:  		device->cname = "G84";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv50_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv84_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv84_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0x86:  		device->cname = "G86";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv50_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv50_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv84_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv84_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0x92:  		device->cname = "G92";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv50_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv50_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv50_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv84_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv84_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0x94:  		device->cname = "G94";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv50_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0x96:  		device->cname = "G96";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv50_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv94_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0x98:  		device->cname = "G98";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0xa0:  		device->cname = "G200";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv50_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv50_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nv84_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv84_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nv84_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv84_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv84_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv84_bsp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva0_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0xaa:  		device->cname = "MCP77/MCP78";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0xac:  		device->cname = "MCP79/MCP7A";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nv50_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] =  nvaa_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nv84_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nv98_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvaa_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_CRYPT  ] = &nv98_crypt_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nv94_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nv84_perfmon_oclass;  		break;  	case 0xa3:  		device->cname = "GT215";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_MPEG   ] = &nv84_mpeg_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;  		break;  	case 0xa5:  		device->cname = "GT216";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;  		break;  	case 0xa8:  		device->cname = "GT218";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nva3_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nva3_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;  		break;  	case 0xaf:  		device->cname = "MCP89";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nva3_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nva3_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nv98_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nv50_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvaf_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nv98_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nv94_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nv50_fb_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvaf_fb_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nv50_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nv50_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nva3_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nv50_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nv84_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nv50_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv84_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nv50_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] = &nv50_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nv98_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nv98_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nv98_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nva3_copy_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] =  nva3_perfmon_oclass;  		break;  	default:  		nv_fatal(device, "unknown Tesla chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c index 418f51f50d7..8d55ed633b1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nvc0.c @@ -38,6 +38,8 @@  #include <subdev/instmem.h>  #include <subdev/vm.h>  #include <subdev/bar.h> +#include <subdev/pwr.h> +#include <subdev/volt.h>  #include <engine/device.h>  #include <engine/dmaobj.h> @@ -49,6 +51,7 @@  #include <engine/ppp.h>  #include <engine/copy.h>  #include <engine/disp.h> +#include <engine/perfmon.h>  int  nvc0_identify(struct nouveau_device *device) @@ -57,259 +60,284 @@ nvc0_identify(struct nouveau_device *device)  	case 0xc0:  		device->cname = "GF100";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nvc0_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xc4:  		device->cname = "GF104";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; -		device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xc3:  		device->cname = "GF106";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; -		device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xce:  		device->cname = "GF114";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; -		device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xcf:  		device->cname = "GF116";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; -		device->oclass[NVDEV_ENGINE_GR     ] =  nvc3_graph_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  nvc4_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xc1:  		device->cname = "GF108";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nvc1_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xc8:  		device->cname = "GF110";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nv50_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nv94_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nv92_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nv94_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nva3_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc0_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvc0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvc0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nvc8_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nvc0_copy1_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nva3_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xd9:  		device->cname = "GF119";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nvd0_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nvd0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nvd0_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nvd9_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nvd0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nvd0_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	case 0xd7:  		device->cname = "GF117";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nvd0_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nvd0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  gf117_i2c_oclass;  		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nvc0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nvc0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nvc0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nvc0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nvd7_graph_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nvc0_vp_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nvc0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nvc0_copy0_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nvd0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nvd0_disp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvc0_perfmon_oclass;  		break;  	default:  		nv_fatal(device, "unknown Fermi chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index 7aca1877add..2d1e97d4264 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c @@ -38,6 +38,8 @@  #include <subdev/instmem.h>  #include <subdev/vm.h>  #include <subdev/bar.h> +#include <subdev/pwr.h> +#include <subdev/volt.h>  #include <engine/device.h>  #include <engine/dmaobj.h> @@ -49,6 +51,7 @@  #include <engine/bsp.h>  #include <engine/vp.h>  #include <engine/ppp.h> +#include <engine/perfmon.h>  int  nve0_identify(struct nouveau_device *device) @@ -57,124 +60,216 @@ nve0_identify(struct nouveau_device *device)  	case 0xe4:  		device->cname = "GK104";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nve0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nve0_disp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;  		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;  		break;  	case 0xe7:  		device->cname = "GK107";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nve0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nve0_disp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;  		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;  		break;  	case 0xe6:  		device->cname = "GK106";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nve0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nve4_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nve0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nve0_disp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;  		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass;  		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass; +		break; +	case 0xea: +		device->cname = "GK20A"; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_TIMER  ] = &gk20a_timer_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  gk20a_fb_oclass; +		device->oclass[NVDEV_SUBDEV_IBUS   ] = &gk20a_ibus_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  gk20a_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  gk20a_graph_oclass; +		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nve0_perfmon_oclass;  		break;  	case 0xf0:  		device->cname = "GK110";  		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; -		device->oclass[NVDEV_SUBDEV_GPIO   ] = &nve0_gpio_oclass; -		device->oclass[NVDEV_SUBDEV_I2C    ] = &nvd0_i2c_oclass; -		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nvc0_clock_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass; +		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass; +		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass; +		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass; +		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass; +		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass; +		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass; +		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass; +		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass; +		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass; +		break; +	case 0xf1: +		device->cname = "GK110B"; +		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nvd0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass;  		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass;  		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; -		device->oclass[NVDEV_SUBDEV_DEVINIT] = &nvc0_devinit_oclass; -		device->oclass[NVDEV_SUBDEV_MC     ] = &nvc0_mc_oclass; -		device->oclass[NVDEV_SUBDEV_BUS    ] = &nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass;  		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; -		device->oclass[NVDEV_SUBDEV_FB     ] = &nvc0_fb_oclass; -		device->oclass[NVDEV_SUBDEV_LTCG   ] = &nvc0_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass;  		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; -		device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass;  		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass;  		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nvd0_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass;  		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; -		device->oclass[NVDEV_ENGINE_FIFO   ] = &nve0_fifo_oclass; -		device->oclass[NVDEV_ENGINE_SW     ] = &nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nve0_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass;  		device->oclass[NVDEV_ENGINE_GR     ] =  nvf0_graph_oclass; -		device->oclass[NVDEV_ENGINE_DISP   ] = &nvf0_disp_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass; +		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass; +		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass; +		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass; +		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass; +		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass; +		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; +		device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass; +		break; +	case 0x108: +		device->cname = "GK208"; +		device->oclass[NVDEV_SUBDEV_VBIOS  ] = &nouveau_bios_oclass; +		device->oclass[NVDEV_SUBDEV_GPIO   ] =  nve0_gpio_oclass; +		device->oclass[NVDEV_SUBDEV_I2C    ] =  nve0_i2c_oclass; +		device->oclass[NVDEV_SUBDEV_CLOCK  ] = &nve0_clock_oclass; +		device->oclass[NVDEV_SUBDEV_THERM  ] = &nvd0_therm_oclass; +		device->oclass[NVDEV_SUBDEV_MXM    ] = &nv50_mxm_oclass; +		device->oclass[NVDEV_SUBDEV_DEVINIT] =  nvc0_devinit_oclass; +		device->oclass[NVDEV_SUBDEV_MC     ] =  nvc3_mc_oclass; +		device->oclass[NVDEV_SUBDEV_BUS    ] =  nvc0_bus_oclass; +		device->oclass[NVDEV_SUBDEV_TIMER  ] = &nv04_timer_oclass; +		device->oclass[NVDEV_SUBDEV_FB     ] =  nve0_fb_oclass; +		device->oclass[NVDEV_SUBDEV_LTCG   ] =  gf100_ltcg_oclass; +		device->oclass[NVDEV_SUBDEV_IBUS   ] = &nve0_ibus_oclass; +		device->oclass[NVDEV_SUBDEV_INSTMEM] =  nv50_instmem_oclass; +		device->oclass[NVDEV_SUBDEV_VM     ] = &nvc0_vmmgr_oclass; +		device->oclass[NVDEV_SUBDEV_BAR    ] = &nvc0_bar_oclass; +		device->oclass[NVDEV_SUBDEV_PWR    ] = &nv108_pwr_oclass; +		device->oclass[NVDEV_SUBDEV_VOLT   ] = &nv40_volt_oclass; +		device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass; +		device->oclass[NVDEV_ENGINE_FIFO   ] =  nv108_fifo_oclass; +		device->oclass[NVDEV_ENGINE_SW     ] =  nvc0_software_oclass; +		device->oclass[NVDEV_ENGINE_GR     ] =  nv108_graph_oclass; +		device->oclass[NVDEV_ENGINE_DISP   ] =  nvf0_disp_oclass;  		device->oclass[NVDEV_ENGINE_COPY0  ] = &nve0_copy0_oclass;  		device->oclass[NVDEV_ENGINE_COPY1  ] = &nve0_copy1_oclass;  		device->oclass[NVDEV_ENGINE_COPY2  ] = &nve0_copy2_oclass; -#if 0  		device->oclass[NVDEV_ENGINE_BSP    ] = &nve0_bsp_oclass;  		device->oclass[NVDEV_ENGINE_VP     ] = &nve0_vp_oclass;  		device->oclass[NVDEV_ENGINE_PPP    ] = &nvc0_ppp_oclass; -#endif  		break;  	default:  		nv_fatal(device, "unknown Kepler chipset\n"); diff --git a/drivers/gpu/drm/nouveau/core/engine/device/priv.h b/drivers/gpu/drm/nouveau/core/engine/device/priv.h new file mode 100644 index 00000000000..035fd5b9cfc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/device/priv.h @@ -0,0 +1,8 @@ +#ifndef __NVKM_DEVICE_PRIV_H__ +#define __NVKM_DEVICE_PRIV_H__ + +#include <engine/device.h> + +extern struct nouveau_oclass nouveau_control_oclass[]; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/base.c b/drivers/gpu/drm/nouveau/core/engine/disp/base.c index 7a5cae42834..9c38c5e4050 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/base.c @@ -22,13 +22,89 @@   * Authors: Ben Skeggs   */ -#include <engine/disp.h> +#include "priv.h" +#include "outp.h" +#include "conn.h" + +static int +nouveau_disp_hpd_check(struct nouveau_event *event, u32 types, int index) +{ +	struct nouveau_disp *disp = event->priv; +	struct nvkm_output *outp; +	list_for_each_entry(outp, &disp->outp, head) { +		if (outp->conn->index == index) { +			if (outp->conn->hpd.event) +				return 0; +			break; +		} +	} +	return -ENOSYS; +} + +int +_nouveau_disp_fini(struct nouveau_object *object, bool suspend) +{ +	struct nouveau_disp *disp = (void *)object; +	struct nvkm_output *outp; +	int ret; + +	list_for_each_entry(outp, &disp->outp, head) { +		ret = nv_ofuncs(outp)->fini(nv_object(outp), suspend); +		if (ret && suspend) +			goto fail_outp; +	} + +	return nouveau_engine_fini(&disp->base, suspend); + +fail_outp: +	list_for_each_entry_continue_reverse(outp, &disp->outp, head) { +		nv_ofuncs(outp)->init(nv_object(outp)); +	} + +	return ret; +} + +int +_nouveau_disp_init(struct nouveau_object *object) +{ +	struct nouveau_disp *disp = (void *)object; +	struct nvkm_output *outp; +	int ret; + +	ret = nouveau_engine_init(&disp->base); +	if (ret) +		return ret; + +	list_for_each_entry(outp, &disp->outp, head) { +		ret = nv_ofuncs(outp)->init(nv_object(outp)); +		if (ret) +			goto fail_outp; +	} + +	return ret; + +fail_outp: +	list_for_each_entry_continue_reverse(outp, &disp->outp, head) { +		nv_ofuncs(outp)->fini(nv_object(outp), false); +	} + +	return ret; +}  void  _nouveau_disp_dtor(struct nouveau_object *object)  {  	struct nouveau_disp *disp = (void *)object; +	struct nvkm_output *outp, *outt; +  	nouveau_event_destroy(&disp->vblank); + +	if (disp->outp.next) { +		list_for_each_entry_safe(outp, outt, &disp->outp, head) { +			nouveau_object_ref(NULL, (struct nouveau_object **)&outp); +		} +	} +  	nouveau_engine_destroy(&disp->base);  } @@ -39,8 +115,15 @@ nouveau_disp_create_(struct nouveau_object *parent,  		     const char *intname, const char *extname,  		     int length, void **pobject)  { +	struct nouveau_disp_impl *impl = (void *)oclass; +	struct nouveau_bios *bios = nouveau_bios(parent);  	struct nouveau_disp *disp; -	int ret; +	struct nouveau_oclass **sclass; +	struct nouveau_object *object; +	struct dcb_output dcbE; +	u8  hpd = 0, ver, hdr; +	u32 data; +	int ret, i;  	ret = nouveau_engine_create_(parent, engine, oclass, true,  				     intname, extname, length, pobject); @@ -48,5 +131,42 @@ nouveau_disp_create_(struct nouveau_object *parent,  	if (ret)  		return ret; -	return nouveau_event_create(heads, &disp->vblank); +	INIT_LIST_HEAD(&disp->outp); + +	/* create output objects for each display path in the vbios */ +	i = -1; +	while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) { +		if (dcbE.type == DCB_OUTPUT_UNUSED) +			continue; +		if (dcbE.type == DCB_OUTPUT_EOL) +			break; +		data = dcbE.location << 4 | dcbE.type; + +		oclass = nvkm_output_oclass; +		sclass = impl->outp; +		while (sclass && sclass[0]) { +			if (sclass[0]->handle == data) { +				oclass = sclass[0]; +				break; +			} +			sclass++; +		} + +		nouveau_object_ctor(*pobject, *pobject, oclass, +				    &dcbE, i, &object); +		hpd = max(hpd, (u8)(dcbE.connector + 1)); +	} + +	ret = nouveau_event_create(3, hpd, &disp->hpd); +	if (ret) +		return ret; + +	disp->hpd->priv = disp; +	disp->hpd->check = nouveau_disp_hpd_check; + +	ret = nouveau_event_create(1, heads, &disp->vblank); +	if (ret) +		return ret; + +	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/conn.c b/drivers/gpu/drm/nouveau/core/engine/disp/conn.c new file mode 100644 index 00000000000..4ffbc70ecf5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/conn.c @@ -0,0 +1,172 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/gpio.h> + +#include "conn.h" +#include "outp.h" + +static void +nvkm_connector_hpd_work(struct work_struct *w) +{ +	struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work); +	struct nouveau_disp *disp = nouveau_disp(conn); +	struct nouveau_gpio *gpio = nouveau_gpio(conn); +	u32 send = NVKM_HPD_UNPLUG; +	if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index)) +		send = NVKM_HPD_PLUG; +	nouveau_event_trigger(disp->hpd, send, conn->index); +	nouveau_event_get(conn->hpd.event); +} + +static int +nvkm_connector_hpd(void *data, u32 type, int index) +{ +	struct nvkm_connector *conn = data; +	DBG("HPD: %d\n", type); +	schedule_work(&conn->hpd.work); +	return NVKM_EVENT_DROP; +} + +int +_nvkm_connector_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvkm_connector *conn = (void *)object; +	if (conn->hpd.event) +		nouveau_event_put(conn->hpd.event); +	return nouveau_object_fini(&conn->base, suspend); +} + +int +_nvkm_connector_init(struct nouveau_object *object) +{ +	struct nvkm_connector *conn = (void *)object; +	int ret = nouveau_object_init(&conn->base); +	if (ret == 0) { +		if (conn->hpd.event) +			nouveau_event_get(conn->hpd.event); +	} +	return ret; +} + +void +_nvkm_connector_dtor(struct nouveau_object *object) +{ +	struct nvkm_connector *conn = (void *)object; +	nouveau_event_ref(NULL, &conn->hpd.event); +	nouveau_object_destroy(&conn->base); +} + +int +nvkm_connector_create_(struct nouveau_object *parent, +		       struct nouveau_object *engine, +		       struct nouveau_oclass *oclass, +		       struct nvbios_connE *info, int index, +		       int length, void **pobject) +{ +	static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 }; +	struct nouveau_gpio *gpio = nouveau_gpio(parent); +	struct nouveau_disp *disp = (void *)engine; +	struct nvkm_connector *conn; +	struct nvkm_output *outp; +	struct dcb_gpio_func func; +	int ret; + +	list_for_each_entry(outp, &disp->outp, head) { +		if (outp->conn && outp->conn->index == index) { +			atomic_inc(&nv_object(outp->conn)->refcount); +			*pobject = outp->conn; +			return 1; +		} +	} + +	ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject); +	conn = *pobject; +	if (ret) +		return ret; + +	conn->info = *info; +	conn->index = index; + +	DBG("type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x\n", +	    info->type, info->location, info->hpd, info->dp, +	    info->di, info->sr, info->lcdid); + +	if ((info->hpd = ffs(info->hpd))) { +		if (--info->hpd >= ARRAY_SIZE(hpd)) { +			ERR("hpd %02x unknown\n", info->hpd); +			goto done; +		} +		info->hpd = hpd[info->hpd]; + +		ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); +		if (ret) { +			ERR("func %02x lookup failed, %d\n", info->hpd, ret); +			goto done; +		} + +		ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED, +					func.line, nvkm_connector_hpd, +					conn, &conn->hpd.event); +		if (ret) { +			ERR("func %02x failed, %d\n", info->hpd, ret); +		} else { +			DBG("func %02x (HPD)\n", info->hpd); +		} +	} + +done: +	INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work); +	return 0; +} + +int +_nvkm_connector_ctor(struct nouveau_object *parent, +		     struct nouveau_object *engine, +		     struct nouveau_oclass *oclass, void *info, u32 index, +		     struct nouveau_object **pobject) +{ +	struct nvkm_connector *conn; +	int ret; + +	ret = nvkm_connector_create(parent, engine, oclass, info, index, &conn); +	*pobject = nv_object(conn); +	if (ret) +		return ret; + +	return 0; +} + +struct nouveau_oclass * +nvkm_connector_oclass = &(struct nvkm_connector_impl) { +	.base = { +		.handle = 0, +		.ofuncs = &(struct nouveau_ofuncs) { +			.ctor = _nvkm_connector_ctor, +			.dtor = _nvkm_connector_dtor, +			.init = _nvkm_connector_init, +			.fini = _nvkm_connector_fini, +		}, +	}, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/conn.h b/drivers/gpu/drm/nouveau/core/engine/disp/conn.h new file mode 100644 index 00000000000..035ebeacbb1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/conn.h @@ -0,0 +1,59 @@ +#ifndef __NVKM_DISP_CONN_H__ +#define __NVKM_DISP_CONN_H__ + +#include "priv.h" + +struct nvkm_connector { +	struct nouveau_object base; +	struct list_head head; + +	struct nvbios_connE info; +	int index; + +	struct { +		struct nouveau_eventh *event; +		struct work_struct work; +	} hpd; +}; + +#define nvkm_connector_create(p,e,c,b,i,d)                                     \ +	nvkm_connector_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) +#define nvkm_connector_destroy(d) ({                                           \ +	struct nvkm_connector *disp = (d);                                     \ +	_nvkm_connector_dtor(nv_object(disp));                                 \ +}) +#define nvkm_connector_init(d) ({                                              \ +	struct nvkm_connector *disp = (d);                                     \ +	_nvkm_connector_init(nv_object(disp));                                 \ +}) +#define nvkm_connector_fini(d,s) ({                                            \ +	struct nvkm_connector *disp = (d);                                     \ +	_nvkm_connector_fini(nv_object(disp), (s));                            \ +}) + +int nvkm_connector_create_(struct nouveau_object *, struct nouveau_object *, +			   struct nouveau_oclass *, struct nvbios_connE *, +			   int, int, void **); + +int  _nvkm_connector_ctor(struct nouveau_object *, struct nouveau_object *, +			  struct nouveau_oclass *, void *, u32, +			  struct nouveau_object **); +void _nvkm_connector_dtor(struct nouveau_object *); +int  _nvkm_connector_init(struct nouveau_object *); +int  _nvkm_connector_fini(struct nouveau_object *, bool); + +struct nvkm_connector_impl { +	struct nouveau_oclass base; +}; + +#ifndef MSG +#define MSG(l,f,a...) do {                                                     \ +	struct nvkm_connector *_conn = (void *)conn;                           \ +	nv_##l(nv_object(conn)->engine, "%02x:%02x%02x: "f, _conn->index,      \ +	       _conn->info.location, _conn->info.type, ##a);                   \ +} while(0) +#define DBG(f,a...) MSG(debug, f, ##a) +#define ERR(f,a...) MSG(error, f, ##a) +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c index 054d9cff4f5..5a5b59b2113 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.c @@ -30,60 +30,49 @@  #include <engine/disp.h> -#include "dport.h" +#include <core/class.h> -#define DBG(fmt, args...) nv_debug(dp->disp, "DP:%04x:%04x: " fmt,             \ -				   dp->outp->hasht, dp->outp->hashm, ##args) -#define ERR(fmt, args...) nv_error(dp->disp, "DP:%04x:%04x: " fmt,             \ -				   dp->outp->hasht, dp->outp->hashm, ##args) +#include "dport.h" +#include "outpdp.h"  /******************************************************************************   * link training   *****************************************************************************/  struct dp_state { -	const struct nouveau_dp_func *func; -	struct nouveau_disp *disp; -	struct dcb_output *outp; -	struct nvbios_dpout info; -	u8 version; -	struct nouveau_i2c_port *aux; -	int head; -	u8  dpcd[4]; +	struct nvkm_output_dp *outp;  	int link_nr;  	u32 link_bw;  	u8  stat[6];  	u8  conf[4]; +	bool pc2; +	u8  pc2stat; +	u8  pc2conf[2];  };  static int  dp_set_link_config(struct dp_state *dp)  { -	struct nouveau_disp *disp = dp->disp; +	struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); +	struct nvkm_output_dp *outp = dp->outp; +	struct nouveau_disp *disp = nouveau_disp(outp);  	struct nouveau_bios *bios = nouveau_bios(disp);  	struct nvbios_init init = { -		.subdev = nv_subdev(dp->disp), +		.subdev = nv_subdev(disp),  		.bios = bios,  		.offset = 0x0000, -		.outp = dp->outp, -		.crtc = dp->head, +		.outp = &outp->base.info, +		.crtc = -1,  		.execute = 1,  	};  	u32 lnkcmp;  	u8 sink[2]; +	int ret;  	DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); -	/* set desired link configuration on the sink */ -	sink[0] = dp->link_bw / 27000; -	sink[1] = dp->link_nr; -	if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) -		sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; - -	nv_wraux(dp->aux, DPCD_LC00, sink, 2); -  	/* set desired link configuration on the source */ -	if ((lnkcmp = dp->info.lnkcmp)) { -		if (dp->version < 0x30) { +	if ((lnkcmp = dp->outp->info.lnkcmp)) { +		if (outp->version < 0x30) {  			while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp))  				lnkcmp += 4;  			init.offset = nv_ro16(bios, lnkcmp + 2); @@ -96,61 +85,112 @@ dp_set_link_config(struct dp_state *dp)  		nvbios_exec(&init);  	} -	return dp->func->lnk_ctl(dp->disp, dp->outp, dp->head, -				 dp->link_nr, dp->link_bw / 27000, -				 dp->dpcd[DPCD_RC02] & -					  DPCD_RC02_ENHANCED_FRAME_CAP); +	ret = impl->lnk_ctl(outp, dp->link_nr, dp->link_bw / 27000, +			    outp->dpcd[DPCD_RC02] & +				       DPCD_RC02_ENHANCED_FRAME_CAP); +	if (ret) { +		if (ret < 0) +			ERR("lnk_ctl failed with %d\n", ret); +		return ret; +	} + +	impl->lnk_pwr(outp, dp->link_nr); + +	/* set desired link configuration on the sink */ +	sink[0] = dp->link_bw / 27000; +	sink[1] = dp->link_nr; +	if (outp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) +		sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; + +	return nv_wraux(outp->base.edid, DPCD_LC00_LINK_BW_SET, sink, 2);  }  static void  dp_set_training_pattern(struct dp_state *dp, u8 pattern)  { +	struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); +	struct nvkm_output_dp *outp = dp->outp;  	u8 sink_tp;  	DBG("training pattern %d\n", pattern); -	dp->func->pattern(dp->disp, dp->outp, dp->head, pattern); +	impl->pattern(outp, pattern); -	nv_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1); +	nv_rdaux(outp->base.edid, DPCD_LC02, &sink_tp, 1);  	sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET;  	sink_tp |= pattern; -	nv_wraux(dp->aux, DPCD_LC02, &sink_tp, 1); +	nv_wraux(outp->base.edid, DPCD_LC02, &sink_tp, 1);  }  static int -dp_link_train_commit(struct dp_state *dp) +dp_link_train_commit(struct dp_state *dp, bool pc)  { -	int i; +	struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); +	struct nvkm_output_dp *outp = dp->outp; +	int ret, i;  	for (i = 0; i < dp->link_nr; i++) {  		u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; +		u8 lpc2 = (dp->pc2stat >> (i * 2)) & 0x3;  		u8 lpre = (lane & 0x0c) >> 2;  		u8 lvsw = (lane & 0x03) >> 0; +		u8 hivs = 3 - lpre; +		u8 hipe = 3; +		u8 hipc = 3; + +		if (lpc2 >= hipc) +			lpc2 = hipc | DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED; +		if (lpre >= hipe) { +			lpre = hipe | DPCD_LC03_MAX_SWING_REACHED; /* yes. */ +			lvsw = hivs = 3 - (lpre & 3); +		} else +		if (lvsw >= hivs) { +			lvsw = hivs | DPCD_LC03_MAX_SWING_REACHED; +		}  		dp->conf[i] = (lpre << 3) | lvsw; -		if (lvsw == 3) -			dp->conf[i] |= DPCD_LC03_MAX_SWING_REACHED; -		if (lpre == 3) -			dp->conf[i] |= DPCD_LC03_MAX_PRE_EMPHASIS_REACHED; +		dp->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4); + +		DBG("config lane %d %02x %02x\n", i, dp->conf[i], lpc2); +		impl->drv_ctl(outp, i, lvsw & 3, lpre & 3, lpc2 & 3); +	} + +	ret = nv_wraux(outp->base.edid, DPCD_LC03(0), dp->conf, 4); +	if (ret) +		return ret; -		DBG("config lane %d %02x\n", i, dp->conf[i]); -		dp->func->drv_ctl(dp->disp, dp->outp, dp->head, i, lvsw, lpre); +	if (pc) { +		ret = nv_wraux(outp->base.edid, DPCD_LC0F, dp->pc2conf, 2); +		if (ret) +			return ret;  	} -	return nv_wraux(dp->aux, DPCD_LC03(0), dp->conf, 4); +	return 0;  }  static int -dp_link_train_update(struct dp_state *dp, u32 delay) +dp_link_train_update(struct dp_state *dp, bool pc, u32 delay)  { +	struct nvkm_output_dp *outp = dp->outp;  	int ret; -	udelay(delay); +	if (outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL]) +		mdelay(outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4); +	else +		udelay(delay); -	ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6); +	ret = nv_rdaux(outp->base.edid, DPCD_LS02, dp->stat, 6);  	if (ret)  		return ret; -	DBG("status %6ph\n", dp->stat); +	if (pc) { +		ret = nv_rdaux(outp->base.edid, DPCD_LS0C, &dp->pc2stat, 1); +		if (ret) +			dp->pc2stat = 0x00; +		DBG("status %6ph pc2 %02x\n", dp->stat, dp->pc2stat); +	} else { +		DBG("status %6ph\n", dp->stat); +	} +  	return 0;  } @@ -164,8 +204,8 @@ dp_link_train_cr(struct dp_state *dp)  	dp_set_training_pattern(dp, 1);  	do { -		if (dp_link_train_commit(dp) || -		    dp_link_train_update(dp, 100)) +		if (dp_link_train_commit(dp, false) || +		    dp_link_train_update(dp, false, 100))  			break;  		cr_done = true; @@ -191,13 +231,19 @@ dp_link_train_cr(struct dp_state *dp)  static int  dp_link_train_eq(struct dp_state *dp)  { +	struct nvkm_output_dp *outp = dp->outp;  	bool eq_done = false, cr_done = true;  	int tries = 0, i; -	dp_set_training_pattern(dp, 2); +	if (outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED) +		dp_set_training_pattern(dp, 3); +	else +		dp_set_training_pattern(dp, 2);  	do { -		if (dp_link_train_update(dp, 400)) +		if ((tries && +		    dp_link_train_commit(dp, dp->pc2)) || +		    dp_link_train_update(dp, dp->pc2, 400))  			break;  		eq_done = !!(dp->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); @@ -209,9 +255,6 @@ dp_link_train_eq(struct dp_state *dp)  			    !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED))  				eq_done = false;  		} - -		if (dp_link_train_commit(dp)) -			break;  	} while (!eq_done && cr_done && ++tries <= 5);  	return eq_done ? 0 : -1; @@ -220,104 +263,109 @@ dp_link_train_eq(struct dp_state *dp)  static void  dp_link_train_init(struct dp_state *dp, bool spread)  { +	struct nvkm_output_dp *outp = dp->outp; +	struct nouveau_disp *disp = nouveau_disp(outp); +	struct nouveau_bios *bios = nouveau_bios(disp);  	struct nvbios_init init = { -		.subdev = nv_subdev(dp->disp), -		.bios = nouveau_bios(dp->disp), -		.outp = dp->outp, -		.crtc = dp->head, +		.subdev = nv_subdev(disp), +		.bios = bios, +		.outp = &outp->base.info, +		.crtc = -1,  		.execute = 1,  	};  	/* set desired spread */  	if (spread) -		init.offset = dp->info.script[2]; +		init.offset = outp->info.script[2];  	else -		init.offset = dp->info.script[3]; +		init.offset = outp->info.script[3];  	nvbios_exec(&init);  	/* pre-train script */ -	init.offset = dp->info.script[0]; +	init.offset = outp->info.script[0];  	nvbios_exec(&init);  }  static void  dp_link_train_fini(struct dp_state *dp)  { +	struct nvkm_output_dp *outp = dp->outp; +	struct nouveau_disp *disp = nouveau_disp(outp); +	struct nouveau_bios *bios = nouveau_bios(disp);  	struct nvbios_init init = { -		.subdev = nv_subdev(dp->disp), -		.bios = nouveau_bios(dp->disp), -		.outp = dp->outp, -		.crtc = dp->head, +		.subdev = nv_subdev(disp), +		.bios = bios, +		.outp = &outp->base.info, +		.crtc = -1,  		.execute = 1,  	};  	/* post-train script */ -	init.offset = dp->info.script[1], +	init.offset = outp->info.script[1],  	nvbios_exec(&init);  } -int -nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func, -		 struct dcb_output *outp, int head, u32 datarate) +static const struct dp_rates { +	u32 rate; +	u8  bw; +	u8  nr; +} nouveau_dp_rates[] = { +	{ 2160000, 0x14, 4 }, +	{ 1080000, 0x0a, 4 }, +	{ 1080000, 0x14, 2 }, +	{  648000, 0x06, 4 }, +	{  540000, 0x0a, 2 }, +	{  540000, 0x14, 1 }, +	{  324000, 0x06, 2 }, +	{  270000, 0x0a, 1 }, +	{  162000, 0x06, 1 }, +	{} +}; + +void +nouveau_dp_train(struct work_struct *w)  { -	struct nouveau_bios *bios = nouveau_bios(disp); -	struct nouveau_i2c *i2c = nouveau_i2c(disp); +	struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work); +	struct nouveau_disp *disp = nouveau_disp(outp); +	const struct dp_rates *cfg = nouveau_dp_rates;  	struct dp_state _dp = { -		.disp = disp, -		.func = func,  		.outp = outp, -		.head = head,  	}, *dp = &_dp; -	const u32 bw_list[] = { 270000, 162000, 0 }; -	const u32 *link_bw = bw_list; -	u8  hdr, cnt, len; -	u32 data; +	u32 datarate = 0;  	int ret; -	/* find the bios displayport data relevant to this output */ -	data = nvbios_dpout_match(bios, outp->hasht, outp->hashm, &dp->version, -				 &hdr, &cnt, &len, &dp->info); -	if (!data) { -		ERR("bios data not found\n"); -		return -EINVAL; -	} - -	/* acquire the aux channel and fetch some info about the display */ -	if (outp->location) -		dp->aux = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); -	else -		dp->aux = i2c->find(i2c, NV_I2C_TYPE_DCBI2C(outp->i2c_index)); -	if (!dp->aux) { -		ERR("no aux channel?!\n"); -		return -ENODEV; +	/* bring capabilities within encoder limits */ +	if (nv_mclass(disp) < NVD0_DISP_CLASS) +		outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED; +	if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) { +		outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT; +		outp->dpcd[2] |= outp->base.info.dpconf.link_nr;  	} - -	ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd)); -	if (ret) { -		ERR("failed to read DPCD\n"); -		return ret; +	if (outp->dpcd[1] > outp->base.info.dpconf.link_bw) +		outp->dpcd[1] = outp->base.info.dpconf.link_bw; +	dp->pc2 = outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED; + +	/* restrict link config to the lowest required rate, if requested */ +	if (datarate) { +		datarate = (datarate / 8) * 10; /* 8B/10B coding overhead */ +		while (cfg[1].rate >= datarate) +			cfg++;  	} +	cfg--; -	/* adjust required bandwidth for 8B/10B coding overhead */ -	datarate = (datarate / 8) * 10; +	/* disable link interrupt handling during link training */ +	nouveau_event_put(outp->irq);  	/* enable down-spreading and execute pre-train script from vbios */ -	dp_link_train_init(dp, dp->dpcd[3] & 0x01); - -	/* start off at highest link rate supported by encoder and display */ -	while (*link_bw > (dp->dpcd[1] * 27000)) -		link_bw++; +	dp_link_train_init(dp, outp->dpcd[3] & 0x01); -	while (link_bw[0]) { -		/* find minimum required lane count at this link rate */ -		dp->link_nr = dp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT; -		while ((dp->link_nr >> 1) * link_bw[0] > datarate) -			dp->link_nr >>= 1; - -		/* drop link rate to minimum with this lane count */ -		while ((link_bw[1] * dp->link_nr) > datarate) -			link_bw++; -		dp->link_bw = link_bw[0]; +	while (ret = -EIO, (++cfg)->rate) { +		/* select next configuration supported by encoder and sink */ +		while (cfg->nr > (outp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT) || +		       cfg->bw > (outp->dpcd[DPCD_RC01_MAX_LINK_RATE])) +			cfg++; +		dp->link_bw = cfg->bw * 27000; +		dp->link_nr = cfg->nr;  		/* program selected link configuration */  		ret = dp_set_link_config(dp); @@ -328,19 +376,24 @@ nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func,  			    !dp_link_train_eq(dp))  				break;  		} else -		if (ret >= 1) { -			/* dp_set_link_config() handled training */ +		if (ret) { +			/* dp_set_link_config() handled training, or +			 * we failed to communicate with the sink. +			 */  			break;  		} - -		/* retry at lower rate */ -		link_bw++;  	} -	/* finish link training */ +	/* finish link training and execute post-train script from vbios */  	dp_set_training_pattern(dp, 0); +	if (ret < 0) +		ERR("link training failed\n"); -	/* execute post-train script from vbios */  	dp_link_train_fini(dp); -	return true; + +	/* signal completion and enable link interrupt handling */ +	DBG("training complete\n"); +	atomic_set(&outp->lt.done, 1); +	wake_up(&outp->lt.wait); +	nouveau_event_get(outp->irq);  } diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dport.h b/drivers/gpu/drm/nouveau/core/engine/disp/dport.h index 0e1bbd18ff6..5628d2d5ec7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/dport.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/dport.h @@ -2,19 +2,18 @@  #define __NVKM_DISP_DPORT_H__  /* DPCD Receiver Capabilities */ -#define DPCD_RC00                                                       0x00000 -#define DPCD_RC00_DPCD_REV                                                 0xff -#define DPCD_RC01                                                       0x00001 -#define DPCD_RC01_MAX_LINK_RATE                                            0xff +#define DPCD_RC00_DPCD_REV                                              0x00000 +#define DPCD_RC01_MAX_LINK_RATE                                         0x00001  #define DPCD_RC02                                                       0x00002  #define DPCD_RC02_ENHANCED_FRAME_CAP                                       0x80 +#define DPCD_RC02_TPS3_SUPPORTED                                           0x40  #define DPCD_RC02_MAX_LANE_COUNT                                           0x1f  #define DPCD_RC03                                                       0x00003  #define DPCD_RC03_MAX_DOWNSPREAD                                           0x01 +#define DPCD_RC0E_AUX_RD_INTERVAL                                       0x0000e  /* DPCD Link Configuration */ -#define DPCD_LC00                                                       0x00100 -#define DPCD_LC00_LINK_BW_SET                                              0xff +#define DPCD_LC00_LINK_BW_SET                                           0x00100  #define DPCD_LC01                                                       0x00101  #define DPCD_LC01_ENHANCED_FRAME_EN                                        0x80  #define DPCD_LC01_LANE_COUNT_SET                                           0x1f @@ -25,6 +24,16 @@  #define DPCD_LC03_PRE_EMPHASIS_SET                                         0x18  #define DPCD_LC03_MAX_SWING_REACHED                                        0x04  #define DPCD_LC03_VOLTAGE_SWING_SET                                        0x03 +#define DPCD_LC0F                                                       0x0010f +#define DPCD_LC0F_LANE1_MAX_POST_CURSOR2_REACHED                           0x40 +#define DPCD_LC0F_LANE1_POST_CURSOR2_SET                                   0x30 +#define DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED                           0x04 +#define DPCD_LC0F_LANE0_POST_CURSOR2_SET                                   0x03 +#define DPCD_LC10                                                       0x00110 +#define DPCD_LC10_LANE3_MAX_POST_CURSOR2_REACHED                           0x40 +#define DPCD_LC10_LANE3_POST_CURSOR2_SET                                   0x30 +#define DPCD_LC10_LANE2_MAX_POST_CURSOR2_REACHED                           0x04 +#define DPCD_LC10_LANE2_POST_CURSOR2_SET                                   0x03  /* DPCD Link/Sink Status */  #define DPCD_LS02                                                       0x00202 @@ -55,24 +64,12 @@  #define DPCD_LS07_LANE3_VOLTAGE_SWING                                      0x30  #define DPCD_LS07_LANE2_PRE_EMPHASIS                                       0x0c  #define DPCD_LS07_LANE2_VOLTAGE_SWING                                      0x03 +#define DPCD_LS0C                                                       0x0020c +#define DPCD_LS0C_LANE3_POST_CURSOR2                                       0xc0 +#define DPCD_LS0C_LANE2_POST_CURSOR2                                       0x30 +#define DPCD_LS0C_LANE1_POST_CURSOR2                                       0x0c +#define DPCD_LS0C_LANE0_POST_CURSOR2                                       0x03 -struct nouveau_disp; -struct dcb_output; - -struct nouveau_dp_func { -	int (*pattern)(struct nouveau_disp *, struct dcb_output *, -		       int head, int pattern); -	int (*lnk_ctl)(struct nouveau_disp *, struct dcb_output *, int head, -		       int link_nr, int link_bw, bool enh_frame); -	int (*drv_ctl)(struct nouveau_disp *, struct dcb_output *, int head, -		       int lane, int swing, int preem); -}; - -extern const struct nouveau_dp_func nv94_sor_dp_func; -extern const struct nouveau_dp_func nvd0_sor_dp_func; -extern const struct nouveau_dp_func nv50_pior_dp_func; - -int nouveau_dp_train(struct nouveau_disp *, const struct nouveau_dp_func *, -		     struct dcb_output *, int, u32); +void nouveau_dp_train(struct work_struct *);  #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c new file mode 100644 index 00000000000..9fc7447fec9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/gm107.c @@ -0,0 +1,101 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <engine/software.h> +#include <engine/disp.h> + +#include <core/class.h> + +#include "nv50.h" + +/******************************************************************************* + * Base display object + ******************************************************************************/ + +static struct nouveau_oclass +gm107_disp_sclass[] = { +	{ GM107_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs }, +	{ GM107_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs }, +	{ GM107_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs }, +	{ GM107_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs }, +	{ GM107_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs }, +	{} +}; + +static struct nouveau_oclass +gm107_disp_base_oclass[] = { +	{ GM107_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds }, +	{} +}; + +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ + +static int +gm107_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct nv50_disp_priv *priv; +	int heads = nv_rd32(parent, 0x022448); +	int ret; + +	ret = nouveau_disp_create(parent, engine, oclass, heads, +				  "PDISP", "display", &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	nv_engine(priv)->sclass = gm107_disp_base_oclass; +	nv_engine(priv)->cclass = &nv50_disp_cclass; +	nv_subdev(priv)->intr = nvd0_disp_intr; +	INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); +	priv->sclass = gm107_disp_sclass; +	priv->head.nr = heads; +	priv->dac.nr = 3; +	priv->sor.nr = 4; +	priv->dac.power = nv50_dac_power; +	priv->dac.sense = nv50_dac_sense; +	priv->sor.power = nv50_sor_power; +	priv->sor.hda_eld = nvd0_hda_eld; +	priv->sor.hdmi = nvd0_hdmi_ctrl; +	return 0; +} + +struct nouveau_oclass * +gm107_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x07), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = gm107_disp_ctor, +		.dtor = _nouveau_disp_dtor, +		.init = _nouveau_disp_init, +		.fini = _nouveau_disp_fini, +	}, +	.base.outp =  nvd0_disp_outp_sclass, +	.mthd.core = &nve0_disp_mast_mthd_chan, +	.mthd.base = &nvd0_disp_sync_mthd_chan, +	.mthd.ovly = &nve0_disp_ovly_mthd_chan, +	.mthd.prev = -0x020000, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c index 05e903f08a3..a32666ed0c4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c @@ -22,7 +22,7 @@   * Authors: Ben Skeggs   */ -#include <engine/disp.h> +#include "priv.h"  #include <core/event.h>  #include <core/class.h> @@ -31,9 +31,53 @@ struct nv04_disp_priv {  	struct nouveau_disp base;  }; +static int +nv04_disp_scanoutpos(struct nouveau_object *object, u32 mthd, +		     void *data, u32 size) +{ +	struct nv04_disp_priv *priv = (void *)object->engine; +	struct nv04_display_scanoutpos *args = data; +	const int head = (mthd & NV04_DISP_MTHD_HEAD); +	u32 line; + +	if (size < sizeof(*args)) +		return -EINVAL; + +	args->vblanks = nv_rd32(priv, 0x680800 + (head * 0x2000)) & 0xffff; +	args->vtotal  = nv_rd32(priv, 0x680804 + (head * 0x2000)) & 0xffff; +	args->vblanke = args->vtotal - 1; + +	args->hblanks = nv_rd32(priv, 0x680820 + (head * 0x2000)) & 0xffff; +	args->htotal  = nv_rd32(priv, 0x680824 + (head * 0x2000)) & 0xffff; +	args->hblanke = args->htotal - 1; + +	/* +	 * If output is vga instead of digital then vtotal/htotal is invalid +	 * so we have to give up and trigger the timestamping fallback in the +	 * drm core. +	 */ +	if (!args->vtotal || !args->htotal) +		return -ENOTSUPP; + +	args->time[0] = ktime_to_ns(ktime_get()); +	line = nv_rd32(priv, 0x600868 + (head * 0x2000)); +	args->time[1] = ktime_to_ns(ktime_get()); +	args->hline = (line & 0xffff0000) >> 16; +	args->vline = (line & 0x0000ffff); +	return 0; +} + +#define HEAD_MTHD(n) (n), (n) + 0x01 + +static struct nouveau_omthds +nv04_disp_omthds[] = { +	{ HEAD_MTHD(NV04_DISP_SCANOUTPOS), nv04_disp_scanoutpos }, +	{} +}; +  static struct nouveau_oclass  nv04_disp_sclass[] = { -	{ NV04_DISP_CLASS, &nouveau_object_ofuncs }, +	{ NV04_DISP_CLASS, &nouveau_object_ofuncs, nv04_disp_omthds },  	{},  }; @@ -42,13 +86,13 @@ nv04_disp_sclass[] = {   ******************************************************************************/  static void -nv04_disp_vblank_enable(struct nouveau_event *event, int head) +nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head)  {  	nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001);  }  static void -nv04_disp_vblank_disable(struct nouveau_event *event, int head) +nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head)  {  	nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000);  } @@ -59,16 +103,25 @@ nv04_disp_intr(struct nouveau_subdev *subdev)  	struct nv04_disp_priv *priv = (void *)subdev;  	u32 crtc0 = nv_rd32(priv, 0x600100);  	u32 crtc1 = nv_rd32(priv, 0x602100); +	u32 pvideo;  	if (crtc0 & 0x00000001) { -		nouveau_event_trigger(priv->base.vblank, 0); +		nouveau_event_trigger(priv->base.vblank, 1, 0);  		nv_wr32(priv, 0x600100, 0x00000001);  	}  	if (crtc1 & 0x00000001) { -		nouveau_event_trigger(priv->base.vblank, 1); +		nouveau_event_trigger(priv->base.vblank, 1, 1);  		nv_wr32(priv, 0x602100, 0x00000001);  	} + +	if (nv_device(priv)->chipset >= 0x10 && +	    nv_device(priv)->chipset <= 0x40) { +		pvideo = nv_rd32(priv, 0x8100); +		if (pvideo & ~0x11) +			nv_info(priv, "PVIDEO intr: %08x\n", pvideo); +		nv_wr32(priv, 0x8100, pvideo); +	}  }  static int @@ -93,13 +146,13 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -struct nouveau_oclass -nv04_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_disp_oclass = &(struct nouveau_disp_impl) { +	.base.handle = NV_ENGINE(DISP, 0x04), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index c168ae3eaa9..2283c442a10 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -26,8 +26,7 @@  #include <core/parent.h>  #include <core/handle.h>  #include <core/class.h> - -#include <engine/disp.h> +#include <core/enum.h>  #include <subdev/bios.h>  #include <subdev/bios/dcb.h> @@ -227,6 +226,177 @@ nv50_disp_dmac_fini(struct nouveau_object *object, bool suspend)   * EVO master channel object   ******************************************************************************/ +static void +nv50_disp_mthd_list(struct nv50_disp_priv *priv, int debug, u32 base, int c, +		    const struct nv50_disp_mthd_list *list, int inst) +{ +	struct nouveau_object *disp = nv_object(priv); +	int i; + +	for (i = 0; list->data[i].mthd; i++) { +		if (list->data[i].addr) { +			u32 next = nv_rd32(priv, list->data[i].addr + base + 0); +			u32 prev = nv_rd32(priv, list->data[i].addr + base + c); +			u32 mthd = list->data[i].mthd + (list->mthd * inst); +			const char *name = list->data[i].name; +			char mods[16]; + +			if (prev != next) +				snprintf(mods, sizeof(mods), "-> 0x%08x", next); +			else +				snprintf(mods, sizeof(mods), "%13c", ' '); + +			nv_printk_(disp, debug, "\t0x%04x: 0x%08x %s%s%s\n", +				   mthd, prev, mods, name ? " // " : "", +				   name ? name : ""); +		} +	} +} + +void +nv50_disp_mthd_chan(struct nv50_disp_priv *priv, int debug, int head, +		    const struct nv50_disp_mthd_chan *chan) +{ +	struct nouveau_object *disp = nv_object(priv); +	const struct nv50_disp_impl *impl = (void *)disp->oclass; +	const struct nv50_disp_mthd_list *list; +	int i, j; + +	if (debug > nv_subdev(priv)->debug) +		return; + +	for (i = 0; (list = chan->data[i].mthd) != NULL; i++) { +		u32 base = head * chan->addr; +		for (j = 0; j < chan->data[i].nr; j++, base += list->addr) { +			const char *cname = chan->name; +			const char *sname = ""; +			char cname_[16], sname_[16]; + +			if (chan->addr) { +				snprintf(cname_, sizeof(cname_), "%s %d", +					 chan->name, head); +				cname = cname_; +			} + +			if (chan->data[i].nr > 1) { +				snprintf(sname_, sizeof(sname_), " - %s %d", +					 chan->data[i].name, j); +				sname = sname_; +			} + +			nv_printk_(disp, debug, "%s%s:\n", cname, sname); +			nv50_disp_mthd_list(priv, debug, base, impl->mthd.prev, +					    list, j); +		} +	} +} + +const struct nv50_disp_mthd_list +nv50_disp_mast_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x000000 }, +		{ 0x0084, 0x610bb8 }, +		{ 0x0088, 0x610b9c }, +		{ 0x008c, 0x000000 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_list +nv50_disp_mast_mthd_dac = { +	.mthd = 0x0080, +	.addr = 0x000008, +	.data = { +		{ 0x0400, 0x610b58 }, +		{ 0x0404, 0x610bdc }, +		{ 0x0420, 0x610828 }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nv50_disp_mast_mthd_sor = { +	.mthd = 0x0040, +	.addr = 0x000008, +	.data = { +		{ 0x0600, 0x610b70 }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nv50_disp_mast_mthd_pior = { +	.mthd = 0x0040, +	.addr = 0x000008, +	.data = { +		{ 0x0700, 0x610b80 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_list +nv50_disp_mast_mthd_head = { +	.mthd = 0x0400, +	.addr = 0x000540, +	.data = { +		{ 0x0800, 0x610ad8 }, +		{ 0x0804, 0x610ad0 }, +		{ 0x0808, 0x610a48 }, +		{ 0x080c, 0x610a78 }, +		{ 0x0810, 0x610ac0 }, +		{ 0x0814, 0x610af8 }, +		{ 0x0818, 0x610b00 }, +		{ 0x081c, 0x610ae8 }, +		{ 0x0820, 0x610af0 }, +		{ 0x0824, 0x610b08 }, +		{ 0x0828, 0x610b10 }, +		{ 0x082c, 0x610a68 }, +		{ 0x0830, 0x610a60 }, +		{ 0x0834, 0x000000 }, +		{ 0x0838, 0x610a40 }, +		{ 0x0840, 0x610a24 }, +		{ 0x0844, 0x610a2c }, +		{ 0x0848, 0x610aa8 }, +		{ 0x084c, 0x610ab0 }, +		{ 0x0860, 0x610a84 }, +		{ 0x0864, 0x610a90 }, +		{ 0x0868, 0x610b18 }, +		{ 0x086c, 0x610b20 }, +		{ 0x0870, 0x610ac8 }, +		{ 0x0874, 0x610a38 }, +		{ 0x0880, 0x610a58 }, +		{ 0x0884, 0x610a9c }, +		{ 0x08a0, 0x610a70 }, +		{ 0x08a4, 0x610a50 }, +		{ 0x08a8, 0x610ae0 }, +		{ 0x08c0, 0x610b28 }, +		{ 0x08c4, 0x610b30 }, +		{ 0x08c8, 0x610b40 }, +		{ 0x08d4, 0x610b38 }, +		{ 0x08d8, 0x610b48 }, +		{ 0x08dc, 0x610b50 }, +		{ 0x0900, 0x610a18 }, +		{ 0x0904, 0x610ab8 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_chan +nv50_disp_mast_mthd_chan = { +	.name = "Core", +	.addr = 0x000000, +	.data = { +		{ "Global", 1, &nv50_disp_mast_mthd_base }, +		{    "DAC", 3, &nv50_disp_mast_mthd_dac  }, +		{    "SOR", 2, &nv50_disp_mast_mthd_sor  }, +		{   "PIOR", 3, &nv50_disp_mast_mthd_pior }, +		{   "HEAD", 2, &nv50_disp_mast_mthd_head }, +		{} +	} +}; +  static int  nv50_disp_mast_ctor(struct nouveau_object *parent,  		    struct nouveau_object *engine, @@ -323,6 +493,56 @@ nv50_disp_mast_ofuncs = {   * EVO sync channel objects   ******************************************************************************/ +static const struct nv50_disp_mthd_list +nv50_disp_sync_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x000000 }, +		{ 0x0084, 0x0008c4 }, +		{ 0x0088, 0x0008d0 }, +		{ 0x008c, 0x0008dc }, +		{ 0x0090, 0x0008e4 }, +		{ 0x0094, 0x610884 }, +		{ 0x00a0, 0x6108a0 }, +		{ 0x00a4, 0x610878 }, +		{ 0x00c0, 0x61086c }, +		{ 0x00e0, 0x610858 }, +		{ 0x00e4, 0x610860 }, +		{ 0x00e8, 0x6108ac }, +		{ 0x00ec, 0x6108b4 }, +		{ 0x0100, 0x610894 }, +		{ 0x0110, 0x6108bc }, +		{ 0x0114, 0x61088c }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nv50_disp_sync_mthd_image = { +	.mthd = 0x0400, +	.addr = 0x000000, +	.data = { +		{ 0x0800, 0x6108f0 }, +		{ 0x0804, 0x6108fc }, +		{ 0x0808, 0x61090c }, +		{ 0x080c, 0x610914 }, +		{ 0x0810, 0x610904 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_chan +nv50_disp_sync_mthd_chan = { +	.name = "Base", +	.addr = 0x000540, +	.data = { +		{ "Global", 1, &nv50_disp_sync_mthd_base }, +		{  "Image", 2, &nv50_disp_sync_mthd_image }, +		{} +	} +}; +  static int  nv50_disp_sync_ctor(struct nouveau_object *parent,  		    struct nouveau_object *engine, @@ -362,6 +582,44 @@ nv50_disp_sync_ofuncs = {   * EVO overlay channel objects   ******************************************************************************/ +const struct nv50_disp_mthd_list +nv50_disp_ovly_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x000000 }, +		{ 0x0084, 0x0009a0 }, +		{ 0x0088, 0x0009c0 }, +		{ 0x008c, 0x0009c8 }, +		{ 0x0090, 0x6109b4 }, +		{ 0x0094, 0x610970 }, +		{ 0x00a0, 0x610998 }, +		{ 0x00a4, 0x610964 }, +		{ 0x00c0, 0x610958 }, +		{ 0x00e0, 0x6109a8 }, +		{ 0x00e4, 0x6109d0 }, +		{ 0x00e8, 0x6109d8 }, +		{ 0x0100, 0x61094c }, +		{ 0x0104, 0x610984 }, +		{ 0x0108, 0x61098c }, +		{ 0x0800, 0x6109f8 }, +		{ 0x0808, 0x610a08 }, +		{ 0x080c, 0x610a10 }, +		{ 0x0810, 0x610a00 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_chan +nv50_disp_ovly_mthd_chan = { +	.name = "Overlay", +	.addr = 0x000540, +	.data = { +		{ "Global", 1, &nv50_disp_ovly_mthd_base }, +		{} +	} +}; +  static int  nv50_disp_ovly_ctor(struct nouveau_object *parent,  		    struct nouveau_object *engine, @@ -541,14 +799,43 @@ nv50_disp_curs_ofuncs = {   * Base display object   ******************************************************************************/ +int +nv50_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd, +			  void *data, u32 size) +{ +	struct nv50_disp_priv *priv = (void *)object->engine; +	struct nv04_display_scanoutpos *args = data; +	const int head = (mthd & NV50_DISP_MTHD_HEAD); +	u32 blanke, blanks, total; + +	if (size < sizeof(*args) || head >= priv->head.nr) +		return -EINVAL; +	blanke = nv_rd32(priv, 0x610aec + (head * 0x540)); +	blanks = nv_rd32(priv, 0x610af4 + (head * 0x540)); +	total  = nv_rd32(priv, 0x610afc + (head * 0x540)); + +	args->vblanke = (blanke & 0xffff0000) >> 16; +	args->hblanke = (blanke & 0x0000ffff); +	args->vblanks = (blanks & 0xffff0000) >> 16; +	args->hblanks = (blanks & 0x0000ffff); +	args->vtotal  = ( total & 0xffff0000) >> 16; +	args->htotal  = ( total & 0x0000ffff); + +	args->time[0] = ktime_to_ns(ktime_get()); +	args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff; +	args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */ +	args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff; +	return 0; +} +  static void -nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) +nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)  {  	nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));  }  static void -nv50_disp_base_vblank_disable(struct nouveau_event *event, int head) +nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)  {  	nv_mask(event->priv, 0x61002c, (4 << head), 0);  } @@ -675,6 +962,7 @@ nv50_disp_base_ofuncs = {  static struct nouveau_omthds  nv50_disp_base_omthds[] = { +	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },  	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },  	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },  	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd }, @@ -752,40 +1040,94 @@ nv50_disp_cclass = {   * Display engine implementation   ******************************************************************************/ -static void -nv50_disp_intr_error(struct nv50_disp_priv *priv) -{ -	u32 channels = (nv_rd32(priv, 0x610020) & 0x001f0000) >> 16; -	u32 addr, data; -	int chid; - -	for (chid = 0; chid < 5; chid++) { -		if (!(channels & (1 << chid))) -			continue; +static const struct nouveau_enum +nv50_disp_intr_error_type[] = { +	{ 3, "ILLEGAL_MTHD" }, +	{ 4, "INVALID_VALUE" }, +	{ 5, "INVALID_STATE" }, +	{ 7, "INVALID_HANDLE" }, +	{} +}; -		nv_wr32(priv, 0x610020, 0x00010000 << chid); -		addr = nv_rd32(priv, 0x610080 + (chid * 0x08)); -		data = nv_rd32(priv, 0x610084 + (chid * 0x08)); -		nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000); +static const struct nouveau_enum +nv50_disp_intr_error_code[] = { +	{ 0x00, "" }, +	{} +}; -		nv_error(priv, "chid %d mthd 0x%04x data 0x%08x 0x%08x\n", -			 chid, addr & 0xffc, data, addr); +static void +nv50_disp_intr_error(struct nv50_disp_priv *priv, int chid) +{ +	struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass; +	u32 data = nv_rd32(priv, 0x610084 + (chid * 0x08)); +	u32 addr = nv_rd32(priv, 0x610080 + (chid * 0x08)); +	u32 code = (addr & 0x00ff0000) >> 16; +	u32 type = (addr & 0x00007000) >> 12; +	u32 mthd = (addr & 0x00000ffc); +	const struct nouveau_enum *ec, *et; +	char ecunk[6], etunk[6]; + +	et = nouveau_enum_find(nv50_disp_intr_error_type, type); +	if (!et) +		snprintf(etunk, sizeof(etunk), "UNK%02X", type); + +	ec = nouveau_enum_find(nv50_disp_intr_error_code, code); +	if (!ec) +		snprintf(ecunk, sizeof(ecunk), "UNK%02X", code); + +	nv_error(priv, "%s [%s] chid %d mthd 0x%04x data 0x%08x\n", +		 et ? et->name : etunk, ec ? ec->name : ecunk, +		 chid, mthd, data); + +	if (chid == 0) { +		switch (mthd) { +		case 0x0080: +			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0, +					    impl->mthd.core); +			break; +		default: +			break; +		} +	} else +	if (chid <= 2) { +		switch (mthd) { +		case 0x0080: +			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1, +					    impl->mthd.base); +			break; +		default: +			break; +		} +	} else +	if (chid <= 4) { +		switch (mthd) { +		case 0x0080: +			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 3, +					    impl->mthd.ovly); +			break; +		default: +			break; +		}  	} + +	nv_wr32(priv, 0x610020, 0x00010000 << chid); +	nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000);  } -static u16 -exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, -	    struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +static struct nvkm_output * +exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, +	    u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,  	    struct nvbios_outp *info)  {  	struct nouveau_bios *bios = nouveau_bios(priv); -	u16 mask, type, data; +	struct nvkm_output *outp; +	u16 mask, type; -	if (outp < 4) { +	if (or < 4) {  		type = DCB_OUTPUT_ANALOG;  		mask = 0;  	} else -	if (outp < 8) { +	if (or < 8) {  		switch (ctrl & 0x00000f00) {  		case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;  		case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; @@ -795,45 +1137,48 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,  		case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;  		default:  			nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); -			return 0x0000; +			return NULL;  		} -		outp -= 4; +		or  -= 4;  	} else { -		outp = outp - 8; +		or   = or - 8;  		type = 0x0010;  		mask = 0;  		switch (ctrl & 0x00000f00) { -		case 0x00000000: type |= priv->pior.type[outp]; break; +		case 0x00000000: type |= priv->pior.type[or]; break;  		default:  			nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl); -			return 0x0000; +			return NULL;  		}  	}  	mask  = 0x00c0 & (mask << 6); -	mask |= 0x0001 << outp; +	mask |= 0x0001 << or;  	mask |= 0x0100 << head; -	data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); -	if (!data) -		return 0x0000; - -	/* off-chip encoders require matching the exact encoder type */ -	if (dcb->location != 0) -		type |= dcb->extdev << 8; +	list_for_each_entry(outp, &priv->base.outp, head) { +		if ((outp->info.hasht & 0xff) == type && +		    (outp->info.hashm & mask) == mask) { +			*data = nvbios_outp_match(bios, outp->info.hasht, +							outp->info.hashm, +						  ver, hdr, cnt, len, info); +			if (!*data) +				return NULL; +			return outp; +		} +	} -	return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); +	return NULL;  } -static bool +static struct nvkm_output *  exec_script(struct nv50_disp_priv *priv, int head, int id)  {  	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvkm_output *outp;  	struct nvbios_outp info; -	struct dcb_output dcb;  	u8  ver, hdr, cnt, len; -	u16 data; -	u32 ctrl = 0x00000000; +	u32 data, ctrl = 0;  	u32 reg;  	int i; @@ -863,36 +1208,35 @@ exec_script(struct nv50_disp_priv *priv, int head, int id)  	}  	if (!(ctrl & (1 << head))) -		return false; +		return NULL;  	i--; -	data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); -	if (data) { +	outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info); +	if (outp) {  		struct nvbios_init init = {  			.subdev = nv_subdev(priv),  			.bios = bios,  			.offset = info.script[id], -			.outp = &dcb, +			.outp = &outp->info,  			.crtc = head,  			.execute = 1,  		}; -		return nvbios_exec(&init) == 0; +		nvbios_exec(&init);  	} -	return false; +	return outp;  } -static u32 -exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, -	    struct dcb_output *outp) +static struct nvkm_output * +exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)  {  	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvkm_output *outp;  	struct nvbios_outp info1;  	struct nvbios_ocfg info2;  	u8  ver, hdr, cnt, len; -	u32 ctrl = 0x00000000; -	u32 data, conf = ~0; +	u32 data, ctrl = 0;  	u32 reg;  	int i; @@ -922,37 +1266,37 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,  	}  	if (!(ctrl & (1 << head))) -		return conf; +		return NULL;  	i--; -	data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); -	if (!data) -		return conf; +	outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); +	if (!outp) +		return NULL; -	if (outp->location == 0) { -		switch (outp->type) { +	if (outp->info.location == 0) { +		switch (outp->info.type) {  		case DCB_OUTPUT_TMDS: -			conf = (ctrl & 0x00000f00) >> 8; +			*conf = (ctrl & 0x00000f00) >> 8;  			if (pclk >= 165000) -				conf |= 0x0100; +				*conf |= 0x0100;  			break;  		case DCB_OUTPUT_LVDS: -			conf = priv->sor.lvdsconf; +			*conf = priv->sor.lvdsconf;  			break;  		case DCB_OUTPUT_DP: -			conf = (ctrl & 0x00000f00) >> 8; +			*conf = (ctrl & 0x00000f00) >> 8;  			break;  		case DCB_OUTPUT_ANALOG:  		default: -			conf = 0x00ff; +			*conf = 0x00ff;  			break;  		}  	} else { -		conf = (ctrl & 0x00000f00) >> 8; +		*conf = (ctrl & 0x00000f00) >> 8;  		pclk = pclk / 2;  	} -	data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); +	data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);  	if (data && id < 0xff) {  		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);  		if (data) { @@ -960,7 +1304,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,  				.subdev = nv_subdev(priv),  				.bios = bios,  				.offset = data, -				.outp = outp, +				.outp = &outp->info,  				.crtc = head,  				.execute = 1,  			}; @@ -969,7 +1313,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk,  		}  	} -	return conf; +	return outp;  }  static void @@ -981,7 +1325,35 @@ nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head)  static void  nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head)  { -	exec_script(priv, head, 2); +	struct nvkm_output *outp = exec_script(priv, head, 2); + +	/* the binary driver does this outside of the supervisor handling +	 * (after the third supervisor from a detach).  we (currently?) +	 * allow both detach/attach to happen in the same set of +	 * supervisor interrupts, so it would make sense to execute this +	 * (full power down?) script after all the detach phases of the +	 * supervisor handling.  like with training if needed from the +	 * second supervisor, nvidia doesn't do this, so who knows if it's +	 * entirely safe, but it does appear to work.. +	 * +	 * without this script being run, on some configurations i've +	 * seen, switching from DP to TMDS on a DP connector may result +	 * in a blank screen (SOR_PWR off/on can restore it) +	 */ +	if (outp && outp->info.type == DCB_OUTPUT_DP) { +		struct nvkm_output_dp *outpdp = (void *)outp; +		struct nvbios_init init = { +			.subdev = nv_subdev(priv), +			.bios = nouveau_bios(priv), +			.outp = &outp->info, +			.crtc = head, +			.offset = outpdp->info.script[4], +			.execute = 1, +		}; + +		nvbios_exec(&init); +		atomic_set(&outpdp->lt.done, 0); +	}  }  static void @@ -1103,56 +1475,83 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv,  static void  nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head)  { -	struct dcb_output outp; +	struct nvkm_output *outp;  	u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;  	u32 hval, hreg = 0x614200 + (head * 0x800);  	u32 oval, oreg; -	u32 mask; -	u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); -	if (conf != ~0) { -		if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { -			u32 soff = (ffs(outp.or) - 1) * 0x08; -			u32 ctrl = nv_rd32(priv, 0x610798 + soff); -			u32 datarate; - -			switch ((ctrl & 0x000f0000) >> 16) { -			case 6: datarate = pclk * 30 / 8; break; -			case 5: datarate = pclk * 24 / 8; break; -			case 2: -			default: -				datarate = pclk * 18 / 8; -				break; -			} +	u32 mask, conf; -			nouveau_dp_train(&priv->base, priv->sor.dp, -					 &outp, head, datarate); -		} +	outp = exec_clkcmp(priv, head, 0xff, pclk, &conf); +	if (!outp) +		return; -		exec_clkcmp(priv, head, 0, pclk, &outp); - -		if (!outp.location && outp.type == DCB_OUTPUT_ANALOG) { -			oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800; -			oval = 0x00000000; -			hval = 0x00000000; -			mask = 0xffffffff; -		} else -		if (!outp.location) { -			if (outp.type == DCB_OUTPUT_DP) -				nv50_disp_intr_unk20_2_dp(priv, &outp, pclk); -			oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800; -			oval = (conf & 0x0100) ? 0x00000101 : 0x00000000; -			hval = 0x00000000; -			mask = 0x00000707; +	/* we allow both encoder attach and detach operations to occur +	 * within a single supervisor (ie. modeset) sequence.  the +	 * encoder detach scripts quite often switch off power to the +	 * lanes, which requires the link to be re-trained. +	 * +	 * this is not generally an issue as the sink "must" (heh) +	 * signal an irq when it's lost sync so the driver can +	 * re-train. +	 * +	 * however, on some boards, if one does not configure at least +	 * the gpu side of the link *before* attaching, then various +	 * things can go horribly wrong (PDISP disappearing from mmio, +	 * third supervisor never happens, etc). +	 * +	 * the solution is simply to retrain here, if necessary.  last +	 * i checked, the binary driver userspace does not appear to +	 * trigger this situation (it forces an UPDATE between steps). +	 */ +	if (outp->info.type == DCB_OUTPUT_DP) { +		u32 soff = (ffs(outp->info.or) - 1) * 0x08; +		u32 ctrl, datarate; + +		if (outp->info.location == 0) { +			ctrl = nv_rd32(priv, 0x610794 + soff); +			soff = 1;  		} else { -			oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800; -			oval = 0x00000001; -			hval = 0x00000001; -			mask = 0x00000707; +			ctrl = nv_rd32(priv, 0x610b80 + soff); +			soff = 2; +		} + +		switch ((ctrl & 0x000f0000) >> 16) { +		case 6: datarate = pclk * 30; break; +		case 5: datarate = pclk * 24; break; +		case 2: +		default: +			datarate = pclk * 18; +			break;  		} -		nv_mask(priv, hreg, 0x0000000f, hval); -		nv_mask(priv, oreg, mask, oval); +		if (nvkm_output_dp_train(outp, datarate / soff, true)) +			ERR("link not trained before attach\n");  	} + +	exec_clkcmp(priv, head, 0, pclk, &conf); + +	if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) { +		oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800; +		oval = 0x00000000; +		hval = 0x00000000; +		mask = 0xffffffff; +	} else +	if (!outp->info.location) { +		if (outp->info.type == DCB_OUTPUT_DP) +			nv50_disp_intr_unk20_2_dp(priv, &outp->info, pclk); +		oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800; +		oval = (conf & 0x0100) ? 0x00000101 : 0x00000000; +		hval = 0x00000000; +		mask = 0x00000707; +	} else { +		oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800; +		oval = 0x00000001; +		hval = 0x00000001; +		mask = 0x00000707; +	} + +	nv_mask(priv, hreg, 0x0000000f, hval); +	nv_mask(priv, oreg, mask, oval);  }  /* If programming a TMDS output on a SOR that can also be configured for @@ -1180,30 +1579,16 @@ nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp  static void  nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head)  { -	struct dcb_output outp; +	struct nvkm_output *outp;  	u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; -	if (exec_clkcmp(priv, head, 1, pclk, &outp) != ~0) { -		if (outp.location == 0 && outp.type == DCB_OUTPUT_TMDS) -			nv50_disp_intr_unk40_0_tmds(priv, &outp); -		else -		if (outp.location == 1 && outp.type == DCB_OUTPUT_DP) { -			u32 soff = (ffs(outp.or) - 1) * 0x08; -			u32 ctrl = nv_rd32(priv, 0x610b84 + soff); -			u32 datarate; - -			switch ((ctrl & 0x000f0000) >> 16) { -			case 6: datarate = pclk * 30 / 8; break; -			case 5: datarate = pclk * 24 / 8; break; -			case 2: -			default: -				datarate = pclk * 18 / 8; -				break; -			} +	u32 conf; -			nouveau_dp_train(&priv->base, priv->pior.dp, -					 &outp, head, datarate); -		} -	} +	outp = exec_clkcmp(priv, head, 1, pclk, &conf); +	if (!outp) +		return; + +	if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS) +		nv50_disp_intr_unk40_0_tmds(priv, &outp->info);  }  void @@ -1211,12 +1596,14 @@ nv50_disp_intr_supervisor(struct work_struct *work)  {  	struct nv50_disp_priv *priv =  		container_of(work, struct nv50_disp_priv, supervisor); +	struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;  	u32 super = nv_rd32(priv, 0x610030);  	int head;  	nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super);  	if (priv->super & 0x00000010) { +		nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);  		for (head = 0; head < priv->head.nr; head++) {  			if (!(super & (0x00000020 << head)))  				continue; @@ -1260,19 +1647,20 @@ nv50_disp_intr(struct nouveau_subdev *subdev)  	u32 intr0 = nv_rd32(priv, 0x610020);  	u32 intr1 = nv_rd32(priv, 0x610024); -	if (intr0 & 0x001f0000) { -		nv50_disp_intr_error(priv); -		intr0 &= ~0x001f0000; +	while (intr0 & 0x001f0000) { +		u32 chid = __ffs(intr0 & 0x001f0000) - 16; +		nv50_disp_intr_error(priv, chid); +		intr0 &= ~(0x00010000 << chid);  	}  	if (intr1 & 0x00000004) { -		nouveau_event_trigger(priv->base.vblank, 0); +		nouveau_event_trigger(priv->base.vblank, 1, 0);  		nv_wr32(priv, 0x610024, 0x00000004);  		intr1 &= ~0x00000004;  	}  	if (intr1 & 0x00000008) { -		nouveau_event_trigger(priv->base.vblank, 1); +		nouveau_event_trigger(priv->base.vblank, 1, 1);  		nv_wr32(priv, 0x610024, 0x00000008);  		intr1 &= ~0x00000008;  	} @@ -1312,17 +1700,27 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->dac.sense = nv50_dac_sense;  	priv->sor.power = nv50_sor_power;  	priv->pior.power = nv50_pior_power; -	priv->pior.dp = &nv50_pior_dp_func;  	return 0;  } -struct nouveau_oclass -nv50_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_disp_outp_sclass[] = { +	&nv50_pior_dp_impl.base.base, +	NULL +}; + +struct nouveau_oclass * +nv50_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x50), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nv50_disp_outp_sclass, +	.mthd.core = &nv50_disp_mast_mthd_chan, +	.mthd.base = &nv50_disp_sync_mthd_chan, +	.mthd.ovly = &nv50_disp_ovly_mthd_chan, +	.mthd.prev = 0x000004, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index 1ae6ceb5670..1a886472b6f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -8,9 +8,21 @@  #include <core/event.h>  #include <engine/dmaobj.h> -#include <engine/disp.h>  #include "dport.h" +#include "priv.h" +#include "outp.h" +#include "outpdp.h" + +struct nv50_disp_impl { +	struct nouveau_disp_impl base; +	struct { +		const struct nv50_disp_mthd_chan *core; +		const struct nv50_disp_mthd_chan *base; +		const struct nv50_disp_mthd_chan *ovly; +		int prev; +	} mthd; +};  struct nv50_disp_priv {  	struct nouveau_disp base; @@ -33,16 +45,18 @@ struct nv50_disp_priv {  		int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32);  		int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32);  		u32 lvdsconf; -		const struct nouveau_dp_func *dp;  	} sor;  	struct {  		int nr;  		int (*power)(struct nv50_disp_priv *, int ext, u32 data);  		u8 type[3]; -		const struct nouveau_dp_func *dp;  	} pior;  }; +#define HEAD_MTHD(n) (n), (n) + 0x03 + +int nv50_disp_base_scanoutpos(struct nouveau_object *, u32, void *, u32); +  #define DAC_MTHD(n) (n), (n) + 0x03  int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32); @@ -120,28 +134,79 @@ struct nv50_disp_pioc {  	struct nv50_disp_chan base;  }; +struct nv50_disp_mthd_list { +	u32 mthd; +	u32 addr; +	struct { +		u32 mthd; +		u32 addr; +		const char *name; +	} data[]; +}; + +struct nv50_disp_mthd_chan { +	const char *name; +	u32 addr; +	struct { +		const char *name; +		int nr; +		const struct nv50_disp_mthd_list *mthd; +	} data[]; +}; +  extern struct nouveau_ofuncs nv50_disp_mast_ofuncs; +extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_base; +extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_sor; +extern const struct nv50_disp_mthd_list nv50_disp_mast_mthd_pior;  extern struct nouveau_ofuncs nv50_disp_sync_ofuncs; +extern const struct nv50_disp_mthd_list nv50_disp_sync_mthd_image;  extern struct nouveau_ofuncs nv50_disp_ovly_ofuncs; +extern const struct nv50_disp_mthd_list nv50_disp_ovly_mthd_base;  extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs;  extern struct nouveau_ofuncs nv50_disp_curs_ofuncs;  extern struct nouveau_ofuncs nv50_disp_base_ofuncs;  extern struct nouveau_oclass nv50_disp_cclass; +void nv50_disp_mthd_chan(struct nv50_disp_priv *, int debug, int head, +			 const struct nv50_disp_mthd_chan *);  void nv50_disp_intr_supervisor(struct work_struct *);  void nv50_disp_intr(struct nouveau_subdev *); +extern const struct nv50_disp_mthd_chan nv84_disp_mast_mthd_chan; +extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_dac; +extern const struct nv50_disp_mthd_list nv84_disp_mast_mthd_head; +extern const struct nv50_disp_mthd_chan nv84_disp_sync_mthd_chan; +extern const struct nv50_disp_mthd_chan nv84_disp_ovly_mthd_chan;  extern struct nouveau_omthds nv84_disp_base_omthds[]; -extern struct nouveau_omthds nva3_disp_base_omthds[]; +extern const struct nv50_disp_mthd_chan nv94_disp_mast_mthd_chan;  extern struct nouveau_ofuncs nvd0_disp_mast_ofuncs; +extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_base; +extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_dac; +extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_sor; +extern const struct nv50_disp_mthd_list nvd0_disp_mast_mthd_pior;  extern struct nouveau_ofuncs nvd0_disp_sync_ofuncs;  extern struct nouveau_ofuncs nvd0_disp_ovly_ofuncs; +extern const struct nv50_disp_mthd_chan nvd0_disp_sync_mthd_chan;  extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs;  extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; +extern struct nouveau_omthds nvd0_disp_base_omthds[];  extern struct nouveau_ofuncs nvd0_disp_base_ofuncs;  extern struct nouveau_oclass nvd0_disp_cclass;  void nvd0_disp_intr_supervisor(struct work_struct *);  void nvd0_disp_intr(struct nouveau_subdev *); +extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan; +extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan; + +extern struct nvkm_output_dp_impl nv50_pior_dp_impl; +extern struct nouveau_oclass *nv50_disp_outp_sclass[]; + +extern struct nvkm_output_dp_impl nv94_sor_dp_impl; +int nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); +extern struct nouveau_oclass *nv94_disp_outp_sclass[]; + +extern struct nvkm_output_dp_impl nvd0_sor_dp_impl; +extern struct nouveau_oclass *nvd0_disp_outp_sclass[]; +  #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index d8c74c0883a..1cc62e43468 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c @@ -29,6 +29,179 @@  #include "nv50.h" +/******************************************************************************* + * EVO master channel object + ******************************************************************************/ + +const struct nv50_disp_mthd_list +nv84_disp_mast_mthd_dac = { +	.mthd = 0x0080, +	.addr = 0x000008, +	.data = { +		{ 0x0400, 0x610b58 }, +		{ 0x0404, 0x610bdc }, +		{ 0x0420, 0x610bc4 }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nv84_disp_mast_mthd_head = { +	.mthd = 0x0400, +	.addr = 0x000540, +	.data = { +		{ 0x0800, 0x610ad8 }, +		{ 0x0804, 0x610ad0 }, +		{ 0x0808, 0x610a48 }, +		{ 0x080c, 0x610a78 }, +		{ 0x0810, 0x610ac0 }, +		{ 0x0814, 0x610af8 }, +		{ 0x0818, 0x610b00 }, +		{ 0x081c, 0x610ae8 }, +		{ 0x0820, 0x610af0 }, +		{ 0x0824, 0x610b08 }, +		{ 0x0828, 0x610b10 }, +		{ 0x082c, 0x610a68 }, +		{ 0x0830, 0x610a60 }, +		{ 0x0834, 0x000000 }, +		{ 0x0838, 0x610a40 }, +		{ 0x0840, 0x610a24 }, +		{ 0x0844, 0x610a2c }, +		{ 0x0848, 0x610aa8 }, +		{ 0x084c, 0x610ab0 }, +		{ 0x085c, 0x610c5c }, +		{ 0x0860, 0x610a84 }, +		{ 0x0864, 0x610a90 }, +		{ 0x0868, 0x610b18 }, +		{ 0x086c, 0x610b20 }, +		{ 0x0870, 0x610ac8 }, +		{ 0x0874, 0x610a38 }, +		{ 0x0878, 0x610c50 }, +		{ 0x0880, 0x610a58 }, +		{ 0x0884, 0x610a9c }, +		{ 0x089c, 0x610c68 }, +		{ 0x08a0, 0x610a70 }, +		{ 0x08a4, 0x610a50 }, +		{ 0x08a8, 0x610ae0 }, +		{ 0x08c0, 0x610b28 }, +		{ 0x08c4, 0x610b30 }, +		{ 0x08c8, 0x610b40 }, +		{ 0x08d4, 0x610b38 }, +		{ 0x08d8, 0x610b48 }, +		{ 0x08dc, 0x610b50 }, +		{ 0x0900, 0x610a18 }, +		{ 0x0904, 0x610ab8 }, +		{ 0x0910, 0x610c70 }, +		{ 0x0914, 0x610c78 }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nv84_disp_mast_mthd_chan = { +	.name = "Core", +	.addr = 0x000000, +	.data = { +		{ "Global", 1, &nv50_disp_mast_mthd_base }, +		{    "DAC", 3, &nv84_disp_mast_mthd_dac  }, +		{    "SOR", 2, &nv50_disp_mast_mthd_sor  }, +		{   "PIOR", 3, &nv50_disp_mast_mthd_pior }, +		{   "HEAD", 2, &nv84_disp_mast_mthd_head }, +		{} +	} +}; + +/******************************************************************************* + * EVO sync channel objects + ******************************************************************************/ + +static const struct nv50_disp_mthd_list +nv84_disp_sync_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x000000 }, +		{ 0x0084, 0x0008c4 }, +		{ 0x0088, 0x0008d0 }, +		{ 0x008c, 0x0008dc }, +		{ 0x0090, 0x0008e4 }, +		{ 0x0094, 0x610884 }, +		{ 0x00a0, 0x6108a0 }, +		{ 0x00a4, 0x610878 }, +		{ 0x00c0, 0x61086c }, +		{ 0x00c4, 0x610800 }, +		{ 0x00c8, 0x61080c }, +		{ 0x00cc, 0x610818 }, +		{ 0x00e0, 0x610858 }, +		{ 0x00e4, 0x610860 }, +		{ 0x00e8, 0x6108ac }, +		{ 0x00ec, 0x6108b4 }, +		{ 0x00fc, 0x610824 }, +		{ 0x0100, 0x610894 }, +		{ 0x0104, 0x61082c }, +		{ 0x0110, 0x6108bc }, +		{ 0x0114, 0x61088c }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nv84_disp_sync_mthd_chan = { +	.name = "Base", +	.addr = 0x000540, +	.data = { +		{ "Global", 1, &nv84_disp_sync_mthd_base }, +		{  "Image", 2, &nv50_disp_sync_mthd_image }, +		{} +	} +}; + +/******************************************************************************* + * EVO overlay channel objects + ******************************************************************************/ + +static const struct nv50_disp_mthd_list +nv84_disp_ovly_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x000000 }, +		{ 0x0084, 0x6109a0 }, +		{ 0x0088, 0x6109c0 }, +		{ 0x008c, 0x6109c8 }, +		{ 0x0090, 0x6109b4 }, +		{ 0x0094, 0x610970 }, +		{ 0x00a0, 0x610998 }, +		{ 0x00a4, 0x610964 }, +		{ 0x00c0, 0x610958 }, +		{ 0x00e0, 0x6109a8 }, +		{ 0x00e4, 0x6109d0 }, +		{ 0x00e8, 0x6109d8 }, +		{ 0x0100, 0x61094c }, +		{ 0x0104, 0x610984 }, +		{ 0x0108, 0x61098c }, +		{ 0x0800, 0x6109f8 }, +		{ 0x0808, 0x610a08 }, +		{ 0x080c, 0x610a10 }, +		{ 0x0810, 0x610a00 }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nv84_disp_ovly_mthd_chan = { +	.name = "Overlay", +	.addr = 0x000540, +	.data = { +		{ "Global", 1, &nv84_disp_ovly_mthd_base }, +		{} +	} +}; + +/******************************************************************************* + * Base display object + ******************************************************************************/ +  static struct nouveau_oclass  nv84_disp_sclass[] = {  	{ NV84_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, @@ -41,6 +214,7 @@ nv84_disp_sclass[] = {  struct nouveau_omthds  nv84_disp_base_omthds[] = { +	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },  	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },  	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },  	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, @@ -58,6 +232,10 @@ nv84_disp_base_oclass[] = {  	{}  }; +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ +  static int  nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size, @@ -86,17 +264,21 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->sor.power = nv50_sor_power;  	priv->sor.hdmi = nv84_hdmi_ctrl;  	priv->pior.power = nv50_pior_power; -	priv->pior.dp = &nv50_pior_dp_func;  	return 0;  } -struct nouveau_oclass -nv84_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x82), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv84_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x82), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv84_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nv50_disp_outp_sclass, +	.mthd.core = &nv84_disp_mast_mthd_chan, +	.mthd.base = &nv84_disp_sync_mthd_chan, +	.mthd.ovly = &nv84_disp_ovly_mthd_chan, +	.mthd.prev = 0x000004, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index a66f949c1f8..4f718a9f5ae 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c @@ -29,6 +29,38 @@  #include "nv50.h" +/******************************************************************************* + * EVO master channel object + ******************************************************************************/ + +const struct nv50_disp_mthd_list +nv94_disp_mast_mthd_sor = { +	.mthd = 0x0040, +	.addr = 0x000008, +	.data = { +		{ 0x0600, 0x610794 }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nv94_disp_mast_mthd_chan = { +	.name = "Core", +	.addr = 0x000000, +	.data = { +		{ "Global", 1, &nv50_disp_mast_mthd_base }, +		{    "DAC", 3, &nv84_disp_mast_mthd_dac  }, +		{    "SOR", 4, &nv94_disp_mast_mthd_sor  }, +		{   "PIOR", 3, &nv50_disp_mast_mthd_pior }, +		{   "HEAD", 2, &nv84_disp_mast_mthd_head }, +		{} +	} +}; + +/******************************************************************************* + * Base display object + ******************************************************************************/ +  static struct nouveau_oclass  nv94_disp_sclass[] = {  	{ NV94_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, @@ -41,9 +73,11 @@ nv94_disp_sclass[] = {  static struct nouveau_omthds  nv94_disp_base_omthds[] = { +	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },  	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },  	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },  	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, +	{ SOR_MTHD(NV94_DISP_SOR_DP_PWR)      , nv50_sor_mthd },  	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },  	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },  	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd }, @@ -58,6 +92,10 @@ nv94_disp_base_oclass[] = {  	{}  }; +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ +  static int  nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size, @@ -85,19 +123,29 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->dac.sense = nv50_dac_sense;  	priv->sor.power = nv50_sor_power;  	priv->sor.hdmi = nv84_hdmi_ctrl; -	priv->sor.dp = &nv94_sor_dp_func;  	priv->pior.power = nv50_pior_power; -	priv->pior.dp = &nv50_pior_dp_func;  	return 0;  } -struct nouveau_oclass -nv94_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x88), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv94_disp_outp_sclass[] = { +	&nv50_pior_dp_impl.base.base, +	&nv94_sor_dp_impl.base.base, +	NULL +}; + +struct nouveau_oclass * +nv94_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x88), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv94_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nv94_disp_outp_sclass, +	.mthd.core = &nv94_disp_mast_mthd_chan, +	.mthd.base = &nv84_disp_sync_mthd_chan, +	.mthd.ovly = &nv84_disp_ovly_mthd_chan, +	.mthd.prev = 0x000004, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c index 6cf8eefac36..6237a9a36f7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c @@ -29,6 +29,55 @@  #include "nv50.h" +/******************************************************************************* + * EVO overlay channel objects + ******************************************************************************/ + +static const struct nv50_disp_mthd_list +nva0_disp_ovly_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x000000 }, +		{ 0x0084, 0x6109a0 }, +		{ 0x0088, 0x6109c0 }, +		{ 0x008c, 0x6109c8 }, +		{ 0x0090, 0x6109b4 }, +		{ 0x0094, 0x610970 }, +		{ 0x00a0, 0x610998 }, +		{ 0x00a4, 0x610964 }, +		{ 0x00b0, 0x610c98 }, +		{ 0x00b4, 0x610ca4 }, +		{ 0x00b8, 0x610cac }, +		{ 0x00c0, 0x610958 }, +		{ 0x00e0, 0x6109a8 }, +		{ 0x00e4, 0x6109d0 }, +		{ 0x00e8, 0x6109d8 }, +		{ 0x0100, 0x61094c }, +		{ 0x0104, 0x610984 }, +		{ 0x0108, 0x61098c }, +		{ 0x0800, 0x6109f8 }, +		{ 0x0808, 0x610a08 }, +		{ 0x080c, 0x610a10 }, +		{ 0x0810, 0x610a00 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_chan +nva0_disp_ovly_mthd_chan = { +	.name = "Overlay", +	.addr = 0x000540, +	.data = { +		{ "Global", 1, &nva0_disp_ovly_mthd_base }, +		{} +	} +}; + +/******************************************************************************* + * Base display object + ******************************************************************************/ +  static struct nouveau_oclass  nva0_disp_sclass[] = {  	{ NVA0_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, @@ -45,6 +94,10 @@ nva0_disp_base_oclass[] = {  	{}  }; +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ +  static int  nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size, @@ -73,17 +126,21 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->sor.power = nv50_sor_power;  	priv->sor.hdmi = nv84_hdmi_ctrl;  	priv->pior.power = nv50_pior_power; -	priv->pior.dp = &nv50_pior_dp_func;  	return 0;  } -struct nouveau_oclass -nva0_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x83), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nva0_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x83), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nva0_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nv50_disp_outp_sclass, +	.mthd.core = &nv84_disp_mast_mthd_chan, +	.mthd.base = &nv84_disp_sync_mthd_chan, +	.mthd.ovly = &nva0_disp_ovly_mthd_chan, +	.mthd.prev = 0x000004, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index b75413169ea..019124d4782 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c @@ -29,6 +29,10 @@  #include "nv50.h" +/******************************************************************************* + * Base display object + ******************************************************************************/ +  static struct nouveau_oclass  nva3_disp_sclass[] = {  	{ NVA3_DISP_MAST_CLASS, &nv50_disp_mast_ofuncs }, @@ -39,12 +43,14 @@ nva3_disp_sclass[] = {  	{}  }; -struct nouveau_omthds +static struct nouveau_omthds  nva3_disp_base_omthds[] = { +	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nv50_disp_base_scanoutpos },  	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd },  	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd },  	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd },  	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, +	{ SOR_MTHD(NV94_DISP_SOR_DP_PWR)      , nv50_sor_mthd },  	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd },  	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd },  	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd }, @@ -59,6 +65,10 @@ nva3_disp_base_oclass[] = {  	{}  }; +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ +  static int  nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size, @@ -87,19 +97,22 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->sor.power = nv50_sor_power;  	priv->sor.hda_eld = nva3_hda_eld;  	priv->sor.hdmi = nva3_hdmi_ctrl; -	priv->sor.dp = &nv94_sor_dp_func;  	priv->pior.power = nv50_pior_power; -	priv->pior.dp = &nv50_pior_dp_func;  	return 0;  } -struct nouveau_oclass -nva3_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x85), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nva3_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x85), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nva3_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nv94_disp_outp_sclass, +	.mthd.core = &nv94_disp_mast_mthd_chan, +	.mthd.base = &nv84_disp_sync_mthd_chan, +	.mthd.ovly = &nv84_disp_ovly_mthd_chan, +	.mthd.prev = 0x000004, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 52dd7a1db72..fa30d8196f3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -124,6 +124,146 @@ nvd0_disp_dmac_fini(struct nouveau_object *object, bool suspend)   * EVO master channel object   ******************************************************************************/ +const struct nv50_disp_mthd_list +nvd0_disp_mast_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x660080 }, +		{ 0x0084, 0x660084 }, +		{ 0x0088, 0x660088 }, +		{ 0x008c, 0x000000 }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nvd0_disp_mast_mthd_dac = { +	.mthd = 0x0020, +	.addr = 0x000020, +	.data = { +		{ 0x0180, 0x660180 }, +		{ 0x0184, 0x660184 }, +		{ 0x0188, 0x660188 }, +		{ 0x0190, 0x660190 }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nvd0_disp_mast_mthd_sor = { +	.mthd = 0x0020, +	.addr = 0x000020, +	.data = { +		{ 0x0200, 0x660200 }, +		{ 0x0204, 0x660204 }, +		{ 0x0208, 0x660208 }, +		{ 0x0210, 0x660210 }, +		{} +	} +}; + +const struct nv50_disp_mthd_list +nvd0_disp_mast_mthd_pior = { +	.mthd = 0x0020, +	.addr = 0x000020, +	.data = { +		{ 0x0300, 0x660300 }, +		{ 0x0304, 0x660304 }, +		{ 0x0308, 0x660308 }, +		{ 0x0310, 0x660310 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_list +nvd0_disp_mast_mthd_head = { +	.mthd = 0x0300, +	.addr = 0x000300, +	.data = { +		{ 0x0400, 0x660400 }, +		{ 0x0404, 0x660404 }, +		{ 0x0408, 0x660408 }, +		{ 0x040c, 0x66040c }, +		{ 0x0410, 0x660410 }, +		{ 0x0414, 0x660414 }, +		{ 0x0418, 0x660418 }, +		{ 0x041c, 0x66041c }, +		{ 0x0420, 0x660420 }, +		{ 0x0424, 0x660424 }, +		{ 0x0428, 0x660428 }, +		{ 0x042c, 0x66042c }, +		{ 0x0430, 0x660430 }, +		{ 0x0434, 0x660434 }, +		{ 0x0438, 0x660438 }, +		{ 0x0440, 0x660440 }, +		{ 0x0444, 0x660444 }, +		{ 0x0448, 0x660448 }, +		{ 0x044c, 0x66044c }, +		{ 0x0450, 0x660450 }, +		{ 0x0454, 0x660454 }, +		{ 0x0458, 0x660458 }, +		{ 0x045c, 0x66045c }, +		{ 0x0460, 0x660460 }, +		{ 0x0468, 0x660468 }, +		{ 0x046c, 0x66046c }, +		{ 0x0470, 0x660470 }, +		{ 0x0474, 0x660474 }, +		{ 0x0480, 0x660480 }, +		{ 0x0484, 0x660484 }, +		{ 0x048c, 0x66048c }, +		{ 0x0490, 0x660490 }, +		{ 0x0494, 0x660494 }, +		{ 0x0498, 0x660498 }, +		{ 0x04b0, 0x6604b0 }, +		{ 0x04b8, 0x6604b8 }, +		{ 0x04bc, 0x6604bc }, +		{ 0x04c0, 0x6604c0 }, +		{ 0x04c4, 0x6604c4 }, +		{ 0x04c8, 0x6604c8 }, +		{ 0x04d0, 0x6604d0 }, +		{ 0x04d4, 0x6604d4 }, +		{ 0x04e0, 0x6604e0 }, +		{ 0x04e4, 0x6604e4 }, +		{ 0x04e8, 0x6604e8 }, +		{ 0x04ec, 0x6604ec }, +		{ 0x04f0, 0x6604f0 }, +		{ 0x04f4, 0x6604f4 }, +		{ 0x04f8, 0x6604f8 }, +		{ 0x04fc, 0x6604fc }, +		{ 0x0500, 0x660500 }, +		{ 0x0504, 0x660504 }, +		{ 0x0508, 0x660508 }, +		{ 0x050c, 0x66050c }, +		{ 0x0510, 0x660510 }, +		{ 0x0514, 0x660514 }, +		{ 0x0518, 0x660518 }, +		{ 0x051c, 0x66051c }, +		{ 0x052c, 0x66052c }, +		{ 0x0530, 0x660530 }, +		{ 0x054c, 0x66054c }, +		{ 0x0550, 0x660550 }, +		{ 0x0554, 0x660554 }, +		{ 0x0558, 0x660558 }, +		{ 0x055c, 0x66055c }, +		{} +	} +}; + +static const struct nv50_disp_mthd_chan +nvd0_disp_mast_mthd_chan = { +	.name = "Core", +	.addr = 0x000000, +	.data = { +		{ "Global", 1, &nvd0_disp_mast_mthd_base }, +		{    "DAC", 3, &nvd0_disp_mast_mthd_dac  }, +		{    "SOR", 8, &nvd0_disp_mast_mthd_sor  }, +		{   "PIOR", 4, &nvd0_disp_mast_mthd_pior }, +		{   "HEAD", 4, &nvd0_disp_mast_mthd_head }, +		{} +	} +}; +  static int  nvd0_disp_mast_ctor(struct nouveau_object *parent,  		    struct nouveau_object *engine, @@ -216,6 +356,81 @@ nvd0_disp_mast_ofuncs = {   * EVO sync channel objects   ******************************************************************************/ +static const struct nv50_disp_mthd_list +nvd0_disp_sync_mthd_base = { +	.mthd = 0x0000, +	.addr = 0x000000, +	.data = { +		{ 0x0080, 0x661080 }, +		{ 0x0084, 0x661084 }, +		{ 0x0088, 0x661088 }, +		{ 0x008c, 0x66108c }, +		{ 0x0090, 0x661090 }, +		{ 0x0094, 0x661094 }, +		{ 0x00a0, 0x6610a0 }, +		{ 0x00a4, 0x6610a4 }, +		{ 0x00c0, 0x6610c0 }, +		{ 0x00c4, 0x6610c4 }, +		{ 0x00c8, 0x6610c8 }, +		{ 0x00cc, 0x6610cc }, +		{ 0x00e0, 0x6610e0 }, +		{ 0x00e4, 0x6610e4 }, +		{ 0x00e8, 0x6610e8 }, +		{ 0x00ec, 0x6610ec }, +		{ 0x00fc, 0x6610fc }, +		{ 0x0100, 0x661100 }, +		{ 0x0104, 0x661104 }, +		{ 0x0108, 0x661108 }, +		{ 0x010c, 0x66110c }, +		{ 0x0110, 0x661110 }, +		{ 0x0114, 0x661114 }, +		{ 0x0118, 0x661118 }, +		{ 0x011c, 0x66111c }, +		{ 0x0130, 0x661130 }, +		{ 0x0134, 0x661134 }, +		{ 0x0138, 0x661138 }, +		{ 0x013c, 0x66113c }, +		{ 0x0140, 0x661140 }, +		{ 0x0144, 0x661144 }, +		{ 0x0148, 0x661148 }, +		{ 0x014c, 0x66114c }, +		{ 0x0150, 0x661150 }, +		{ 0x0154, 0x661154 }, +		{ 0x0158, 0x661158 }, +		{ 0x015c, 0x66115c }, +		{ 0x0160, 0x661160 }, +		{ 0x0164, 0x661164 }, +		{ 0x0168, 0x661168 }, +		{ 0x016c, 0x66116c }, +		{} +	} +}; + +static const struct nv50_disp_mthd_list +nvd0_disp_sync_mthd_image = { +	.mthd = 0x0400, +	.addr = 0x000400, +	.data = { +		{ 0x0400, 0x661400 }, +		{ 0x0404, 0x661404 }, +		{ 0x0408, 0x661408 }, +		{ 0x040c, 0x66140c }, +		{ 0x0410, 0x661410 }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nvd0_disp_sync_mthd_chan = { +	.name = "Base", +	.addr = 0x001000, +	.data = { +		{ "Global", 1, &nvd0_disp_sync_mthd_base }, +		{  "Image", 2, &nvd0_disp_sync_mthd_image }, +		{} +	} +}; +  static int  nvd0_disp_sync_ctor(struct nouveau_object *parent,  		    struct nouveau_object *engine, @@ -256,6 +471,68 @@ nvd0_disp_sync_ofuncs = {   * EVO overlay channel objects   ******************************************************************************/ +static const struct nv50_disp_mthd_list +nvd0_disp_ovly_mthd_base = { +	.mthd = 0x0000, +	.data = { +		{ 0x0080, 0x665080 }, +		{ 0x0084, 0x665084 }, +		{ 0x0088, 0x665088 }, +		{ 0x008c, 0x66508c }, +		{ 0x0090, 0x665090 }, +		{ 0x0094, 0x665094 }, +		{ 0x00a0, 0x6650a0 }, +		{ 0x00a4, 0x6650a4 }, +		{ 0x00b0, 0x6650b0 }, +		{ 0x00b4, 0x6650b4 }, +		{ 0x00b8, 0x6650b8 }, +		{ 0x00c0, 0x6650c0 }, +		{ 0x00e0, 0x6650e0 }, +		{ 0x00e4, 0x6650e4 }, +		{ 0x00e8, 0x6650e8 }, +		{ 0x0100, 0x665100 }, +		{ 0x0104, 0x665104 }, +		{ 0x0108, 0x665108 }, +		{ 0x010c, 0x66510c }, +		{ 0x0110, 0x665110 }, +		{ 0x0118, 0x665118 }, +		{ 0x011c, 0x66511c }, +		{ 0x0120, 0x665120 }, +		{ 0x0124, 0x665124 }, +		{ 0x0130, 0x665130 }, +		{ 0x0134, 0x665134 }, +		{ 0x0138, 0x665138 }, +		{ 0x013c, 0x66513c }, +		{ 0x0140, 0x665140 }, +		{ 0x0144, 0x665144 }, +		{ 0x0148, 0x665148 }, +		{ 0x014c, 0x66514c }, +		{ 0x0150, 0x665150 }, +		{ 0x0154, 0x665154 }, +		{ 0x0158, 0x665158 }, +		{ 0x015c, 0x66515c }, +		{ 0x0160, 0x665160 }, +		{ 0x0164, 0x665164 }, +		{ 0x0168, 0x665168 }, +		{ 0x016c, 0x66516c }, +		{ 0x0400, 0x665400 }, +		{ 0x0408, 0x665408 }, +		{ 0x040c, 0x66540c }, +		{ 0x0410, 0x665410 }, +		{} +	} +}; + +static const struct nv50_disp_mthd_chan +nvd0_disp_ovly_mthd_chan = { +	.name = "Overlay", +	.addr = 0x001000, +	.data = { +		{ "Global", 1, &nvd0_disp_ovly_mthd_base }, +		{} +	} +}; +  static int  nvd0_disp_ovly_ctor(struct nouveau_object *parent,  		    struct nouveau_object *engine, @@ -440,14 +717,44 @@ nvd0_disp_curs_ofuncs = {   * Base display object   ******************************************************************************/ +static int +nvd0_disp_base_scanoutpos(struct nouveau_object *object, u32 mthd, +			  void *data, u32 size) +{ +	struct nv50_disp_priv *priv = (void *)object->engine; +	struct nv04_display_scanoutpos *args = data; +	const int head = (mthd & NV50_DISP_MTHD_HEAD); +	u32 blanke, blanks, total; + +	if (size < sizeof(*args) || head >= priv->head.nr) +		return -EINVAL; + +	total  = nv_rd32(priv, 0x640414 + (head * 0x300)); +	blanke = nv_rd32(priv, 0x64041c + (head * 0x300)); +	blanks = nv_rd32(priv, 0x640420 + (head * 0x300)); + +	args->vblanke = (blanke & 0xffff0000) >> 16; +	args->hblanke = (blanke & 0x0000ffff); +	args->vblanks = (blanks & 0xffff0000) >> 16; +	args->hblanks = (blanks & 0x0000ffff); +	args->vtotal  = ( total & 0xffff0000) >> 16; +	args->htotal  = ( total & 0x0000ffff); + +	args->time[0] = ktime_to_ns(ktime_get()); +	args->vline   = nv_rd32(priv, 0x616340 + (head * 0x800)) & 0xffff; +	args->time[1] = ktime_to_ns(ktime_get()); /* vline read locks hline */ +	args->hline   = nv_rd32(priv, 0x616344 + (head * 0x800)) & 0xffff; +	return 0; +} +  static void -nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head) +nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head)  {  	nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001);  }  static void -nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head) +nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head)  {  	nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000);  } @@ -541,6 +848,15 @@ nvd0_disp_base_init(struct nouveau_object *object)  	nv_wr32(priv, 0x6100a0, 0x00000000);  	nv_wr32(priv, 0x6100b0, 0x00000307); +	/* disable underflow reporting, preventing an intermittent issue +	 * on some nve4 boards where the production vbios left this +	 * setting enabled by default. +	 * +	 * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt +	 */ +	for (i = 0; i < priv->head.nr; i++) +		nv_mask(priv, 0x616308 + (i * 0x800), 0x00000111, 0x00000010); +  	return 0;  } @@ -564,9 +880,25 @@ nvd0_disp_base_ofuncs = {  	.fini = nvd0_disp_base_fini,  }; +struct nouveau_omthds +nvd0_disp_base_omthds[] = { +	{ HEAD_MTHD(NV50_DISP_SCANOUTPOS)     , nvd0_disp_base_scanoutpos }, +	{ SOR_MTHD(NV50_DISP_SOR_PWR)         , nv50_sor_mthd }, +	{ SOR_MTHD(NVA3_DISP_SOR_HDA_ELD)     , nv50_sor_mthd }, +	{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR)    , nv50_sor_mthd }, +	{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, +	{ SOR_MTHD(NV94_DISP_SOR_DP_PWR)      , nv50_sor_mthd }, +	{ DAC_MTHD(NV50_DISP_DAC_PWR)         , nv50_dac_mthd }, +	{ DAC_MTHD(NV50_DISP_DAC_LOAD)        , nv50_dac_mthd }, +	{ PIOR_MTHD(NV50_DISP_PIOR_PWR)       , nv50_pior_mthd }, +	{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR)  , nv50_pior_mthd }, +	{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR)    , nv50_pior_mthd }, +	{}, +}; +  static struct nouveau_oclass  nvd0_disp_base_oclass[] = { -	{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, +	{ NVD0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },  	{}  }; @@ -584,19 +916,20 @@ nvd0_disp_sclass[] = {   * Display engine implementation   ******************************************************************************/ -static u16 -exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, -	    struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +static struct nvkm_output * +exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, +	    u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,  	    struct nvbios_outp *info)  {  	struct nouveau_bios *bios = nouveau_bios(priv); -	u16 mask, type, data; +	struct nvkm_output *outp; +	u16 mask, type; -	if (outp < 4) { +	if (or < 4) {  		type = DCB_OUTPUT_ANALOG;  		mask = 0;  	} else { -		outp -= 4; +		or -= 4;  		switch (ctrl & 0x00000f00) {  		case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break;  		case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; @@ -608,101 +941,106 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl,  			nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);  			return 0x0000;  		} -		dcb->sorconf.link = mask;  	}  	mask  = 0x00c0 & (mask << 6); -	mask |= 0x0001 << outp; +	mask |= 0x0001 << or;  	mask |= 0x0100 << head; -	data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); -	if (!data) -		return 0x0000; +	list_for_each_entry(outp, &priv->base.outp, head) { +		if ((outp->info.hasht & 0xff) == type && +		    (outp->info.hashm & mask) == mask) { +			*data = nvbios_outp_match(bios, outp->info.hasht, +							outp->info.hashm, +						  ver, hdr, cnt, len, info); +			if (!*data) +				return NULL; +			return outp; +		} +	} -	return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); +	return NULL;  } -static bool +static struct nvkm_output *  exec_script(struct nv50_disp_priv *priv, int head, int id)  {  	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvkm_output *outp;  	struct nvbios_outp info; -	struct dcb_output dcb;  	u8  ver, hdr, cnt, len; -	u32 ctrl = 0x00000000; -	u16 data; -	int outp; +	u32 data, ctrl = 0; +	int or; -	for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { -		ctrl = nv_rd32(priv, 0x640180 + (outp * 0x20)); +	for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { +		ctrl = nv_rd32(priv, 0x640180 + (or * 0x20));  		if (ctrl & (1 << head))  			break;  	} -	if (outp == 8) -		return false; +	if (or == 8) +		return NULL; -	data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); -	if (data) { +	outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info); +	if (outp) {  		struct nvbios_init init = {  			.subdev = nv_subdev(priv),  			.bios = bios,  			.offset = info.script[id], -			.outp = &dcb, +			.outp = &outp->info,  			.crtc = head,  			.execute = 1,  		}; -		return nvbios_exec(&init) == 0; +		nvbios_exec(&init);  	} -	return false; +	return outp;  } -static u32 -exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, -	    u32 pclk, struct dcb_output *dcb) +static struct nvkm_output * +exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf)  {  	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvkm_output *outp;  	struct nvbios_outp info1;  	struct nvbios_ocfg info2;  	u8  ver, hdr, cnt, len; -	u32 ctrl = 0x00000000; -	u32 data, conf = ~0; -	int outp; +	u32 data, ctrl = 0; +	int or; -	for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { -		ctrl = nv_rd32(priv, 0x660180 + (outp * 0x20)); +	for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { +		ctrl = nv_rd32(priv, 0x660180 + (or * 0x20));  		if (ctrl & (1 << head))  			break;  	} -	if (outp == 8) -		return false; +	if (or == 8) +		return NULL; -	data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); -	if (data == 0x0000) -		return conf; +	outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); +	if (!outp) +		return NULL; -	switch (dcb->type) { +	switch (outp->info.type) {  	case DCB_OUTPUT_TMDS: -		conf = (ctrl & 0x00000f00) >> 8; +		*conf = (ctrl & 0x00000f00) >> 8;  		if (pclk >= 165000) -			conf |= 0x0100; +			*conf |= 0x0100;  		break;  	case DCB_OUTPUT_LVDS: -		conf = priv->sor.lvdsconf; +		*conf = priv->sor.lvdsconf;  		break;  	case DCB_OUTPUT_DP: -		conf = (ctrl & 0x00000f00) >> 8; +		*conf = (ctrl & 0x00000f00) >> 8;  		break;  	case DCB_OUTPUT_ANALOG:  	default: -		conf = 0x00ff; +		*conf = 0x00ff;  		break;  	} -	data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); +	data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);  	if (data && id < 0xff) {  		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);  		if (data) { @@ -710,7 +1048,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,  				.subdev = nv_subdev(priv),  				.bios = bios,  				.offset = data, -				.outp = dcb, +				.outp = &outp->info,  				.crtc = head,  				.execute = 1,  			}; @@ -719,7 +1057,7 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id,  		}  	} -	return conf; +	return outp;  }  static void @@ -731,7 +1069,23 @@ nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head)  static void  nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head)  { -	exec_script(priv, head, 2); +	struct nvkm_output *outp = exec_script(priv, head, 2); + +	/* see note in nv50_disp_intr_unk20_0() */ +	if (outp && outp->info.type == DCB_OUTPUT_DP) { +		struct nvkm_output_dp *outpdp = (void *)outp; +		struct nvbios_init init = { +			.subdev = nv_subdev(priv), +			.bios = nouveau_bios(priv), +			.outp = &outp->info, +			.crtc = head, +			.offset = outpdp->info.script[4], +			.execute = 1, +		}; + +		nvbios_exec(&init); +		atomic_set(&outpdp->lt.done, 0); +	}  }  static void @@ -793,49 +1147,52 @@ nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head,  static void  nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head)  { -	struct dcb_output outp; +	struct nvkm_output *outp;  	u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; -	u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); -	if (conf != ~0) { -		u32 addr, data; - -		if (outp.type == DCB_OUTPUT_DP) { -			u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); -			switch ((sync & 0x000003c0) >> 6) { -			case 6: pclk = pclk * 30 / 8; break; -			case 5: pclk = pclk * 24 / 8; break; -			case 2: -			default: -				pclk = pclk * 18 / 8; -				break; -			} - -			nouveau_dp_train(&priv->base, priv->sor.dp, -					 &outp, head, pclk); +	u32 conf, addr, data; + +	outp = exec_clkcmp(priv, head, 0xff, pclk, &conf); +	if (!outp) +		return; + +	/* see note in nv50_disp_intr_unk20_2() */ +	if (outp->info.type == DCB_OUTPUT_DP) { +		u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); +		switch ((sync & 0x000003c0) >> 6) { +		case 6: pclk = pclk * 30; break; +		case 5: pclk = pclk * 24; break; +		case 2: +		default: +			pclk = pclk * 18; +			break;  		} -		exec_clkcmp(priv, head, 0, pclk, &outp); +		if (nvkm_output_dp_train(outp, pclk, true)) +			ERR("link not trained before attach\n"); +	} -		if (outp.type == DCB_OUTPUT_ANALOG) { -			addr = 0x612280 + (ffs(outp.or) - 1) * 0x800; -			data = 0x00000000; -		} else { -			if (outp.type == DCB_OUTPUT_DP) -				nvd0_disp_intr_unk2_2_tu(priv, head, &outp); -			addr = 0x612300 + (ffs(outp.or) - 1) * 0x800; -			data = (conf & 0x0100) ? 0x00000101 : 0x00000000; -		} +	exec_clkcmp(priv, head, 0, pclk, &conf); -		nv_mask(priv, addr, 0x00000707, data); +	if (outp->info.type == DCB_OUTPUT_ANALOG) { +		addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800; +		data = 0x00000000; +	} else { +		if (outp->info.type == DCB_OUTPUT_DP) +			nvd0_disp_intr_unk2_2_tu(priv, head, &outp->info); +		addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800; +		data = (conf & 0x0100) ? 0x00000101 : 0x00000000;  	} + +	nv_mask(priv, addr, 0x00000707, data);  }  static void  nvd0_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head)  { -	struct dcb_output outp;  	u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; -	exec_clkcmp(priv, head, 1, pclk, &outp); +	u32 conf; + +	exec_clkcmp(priv, head, 1, pclk, &conf);  }  void @@ -843,19 +1200,22 @@ nvd0_disp_intr_supervisor(struct work_struct *work)  {  	struct nv50_disp_priv *priv =  		container_of(work, struct nv50_disp_priv, supervisor); +	struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass;  	u32 mask[4];  	int head; -	nv_debug(priv, "supervisor %08x\n", priv->super); +	nv_debug(priv, "supervisor %d\n", ffs(priv->super));  	for (head = 0; head < priv->head.nr; head++) {  		mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800));  		nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]);  	}  	if (priv->super & 0x00000001) { +		nv50_disp_mthd_chan(priv, NV_DBG_DEBUG, 0, impl->mthd.core);  		for (head = 0; head < priv->head.nr; head++) {  			if (!(mask[head] & 0x00001000))  				continue; +			nv_debug(priv, "supervisor 1.0 - head %d\n", head);  			nvd0_disp_intr_unk1_0(priv, head);  		}  	} else @@ -863,16 +1223,19 @@ nvd0_disp_intr_supervisor(struct work_struct *work)  		for (head = 0; head < priv->head.nr; head++) {  			if (!(mask[head] & 0x00001000))  				continue; +			nv_debug(priv, "supervisor 2.0 - head %d\n", head);  			nvd0_disp_intr_unk2_0(priv, head);  		}  		for (head = 0; head < priv->head.nr; head++) {  			if (!(mask[head] & 0x00010000))  				continue; +			nv_debug(priv, "supervisor 2.1 - head %d\n", head);  			nvd0_disp_intr_unk2_1(priv, head);  		}  		for (head = 0; head < priv->head.nr; head++) {  			if (!(mask[head] & 0x00001000))  				continue; +			nv_debug(priv, "supervisor 2.2 - head %d\n", head);  			nvd0_disp_intr_unk2_2(priv, head);  		}  	} else @@ -880,6 +1243,7 @@ nvd0_disp_intr_supervisor(struct work_struct *work)  		for (head = 0; head < priv->head.nr; head++) {  			if (!(mask[head] & 0x00001000))  				continue; +			nv_debug(priv, "supervisor 3.0 - head %d\n", head);  			nvd0_disp_intr_unk4_0(priv, head);  		}  	} @@ -889,6 +1253,53 @@ nvd0_disp_intr_supervisor(struct work_struct *work)  	nv_wr32(priv, 0x6101d0, 0x80000000);  } +static void +nvd0_disp_intr_error(struct nv50_disp_priv *priv, int chid) +{ +	const struct nv50_disp_impl *impl = (void *)nv_object(priv)->oclass; +	u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12)); +	u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12)); +	u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12)); + +	nv_error(priv, "chid %d mthd 0x%04x data 0x%08x " +		       "0x%08x 0x%08x\n", +		 chid, (mthd & 0x0000ffc), data, mthd, unkn); + +	if (chid == 0) { +		switch (mthd & 0xffc) { +		case 0x0080: +			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0, +					    impl->mthd.core); +			break; +		default: +			break; +		} +	} else +	if (chid <= 4) { +		switch (mthd & 0xffc) { +		case 0x0080: +			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1, +					    impl->mthd.base); +			break; +		default: +			break; +		} +	} else +	if (chid <= 8) { +		switch (mthd & 0xffc) { +		case 0x0080: +			nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5, +					    impl->mthd.ovly); +			break; +		default: +			break; +		} +	} + +	nv_wr32(priv, 0x61009c, (1 << chid)); +	nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000); +} +  void  nvd0_disp_intr(struct nouveau_subdev *subdev)  { @@ -905,18 +1316,8 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)  	if (intr & 0x00000002) {  		u32 stat = nv_rd32(priv, 0x61009c);  		int chid = ffs(stat) - 1; -		if (chid >= 0) { -			u32 mthd = nv_rd32(priv, 0x6101f0 + (chid * 12)); -			u32 data = nv_rd32(priv, 0x6101f4 + (chid * 12)); -			u32 unkn = nv_rd32(priv, 0x6101f8 + (chid * 12)); - -			nv_error(priv, "chid %d mthd 0x%04x data 0x%08x " -				       "0x%08x 0x%08x\n", -				 chid, (mthd & 0x0000ffc), data, mthd, unkn); -			nv_wr32(priv, 0x61009c, (1 << chid)); -			nv_wr32(priv, 0x6101f0 + (chid * 12), 0x90000000); -		} - +		if (chid >= 0) +			nvd0_disp_intr_error(priv, chid);  		intr &= ~0x00000002;  	} @@ -942,7 +1343,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev)  		if (mask & intr) {  			u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800));  			if (stat & 0x00000001) -				nouveau_event_trigger(priv->base.vblank, i); +				nouveau_event_trigger(priv->base.vblank, 1, i);  			nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0);  			nv_rd32(priv, 0x6100c0 + (i * 0x800));  		} @@ -958,9 +1359,6 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	int heads = nv_rd32(parent, 0x022448);  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000001) -		return -ENODEV; -  	ret = nouveau_disp_create(parent, engine, oclass, heads,  				  "PDISP", "display", &priv);  	*pobject = nv_object(priv); @@ -980,17 +1378,27 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->sor.power = nv50_sor_power;  	priv->sor.hda_eld = nvd0_hda_eld;  	priv->sor.hdmi = nvd0_hdmi_ctrl; -	priv->sor.dp = &nvd0_sor_dp_func;  	return 0;  } -struct nouveau_oclass -nvd0_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x90), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nvd0_disp_outp_sclass[] = { +	&nvd0_sor_dp_impl.base.base, +	NULL +}; + +struct nouveau_oclass * +nvd0_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x90), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvd0_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nvd0_disp_outp_sclass, +	.mthd.core = &nvd0_disp_mast_mthd_chan, +	.mthd.base = &nvd0_disp_sync_mthd_chan, +	.mthd.ovly = &nvd0_disp_ovly_mthd_chan, +	.mthd.prev = -0x020000, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index fb1fe6ae5e7..11328e3f5df 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c @@ -29,6 +29,175 @@  #include "nv50.h" +/******************************************************************************* + * EVO master channel object + ******************************************************************************/ + +static const struct nv50_disp_mthd_list +nve0_disp_mast_mthd_head = { +	.mthd = 0x0300, +	.addr = 0x000300, +	.data = { +		{ 0x0400, 0x660400 }, +		{ 0x0404, 0x660404 }, +		{ 0x0408, 0x660408 }, +		{ 0x040c, 0x66040c }, +		{ 0x0410, 0x660410 }, +		{ 0x0414, 0x660414 }, +		{ 0x0418, 0x660418 }, +		{ 0x041c, 0x66041c }, +		{ 0x0420, 0x660420 }, +		{ 0x0424, 0x660424 }, +		{ 0x0428, 0x660428 }, +		{ 0x042c, 0x66042c }, +		{ 0x0430, 0x660430 }, +		{ 0x0434, 0x660434 }, +		{ 0x0438, 0x660438 }, +		{ 0x0440, 0x660440 }, +		{ 0x0444, 0x660444 }, +		{ 0x0448, 0x660448 }, +		{ 0x044c, 0x66044c }, +		{ 0x0450, 0x660450 }, +		{ 0x0454, 0x660454 }, +		{ 0x0458, 0x660458 }, +		{ 0x045c, 0x66045c }, +		{ 0x0460, 0x660460 }, +		{ 0x0468, 0x660468 }, +		{ 0x046c, 0x66046c }, +		{ 0x0470, 0x660470 }, +		{ 0x0474, 0x660474 }, +		{ 0x047c, 0x66047c }, +		{ 0x0480, 0x660480 }, +		{ 0x0484, 0x660484 }, +		{ 0x0488, 0x660488 }, +		{ 0x048c, 0x66048c }, +		{ 0x0490, 0x660490 }, +		{ 0x0494, 0x660494 }, +		{ 0x0498, 0x660498 }, +		{ 0x04a0, 0x6604a0 }, +		{ 0x04b0, 0x6604b0 }, +		{ 0x04b8, 0x6604b8 }, +		{ 0x04bc, 0x6604bc }, +		{ 0x04c0, 0x6604c0 }, +		{ 0x04c4, 0x6604c4 }, +		{ 0x04c8, 0x6604c8 }, +		{ 0x04d0, 0x6604d0 }, +		{ 0x04d4, 0x6604d4 }, +		{ 0x04e0, 0x6604e0 }, +		{ 0x04e4, 0x6604e4 }, +		{ 0x04e8, 0x6604e8 }, +		{ 0x04ec, 0x6604ec }, +		{ 0x04f0, 0x6604f0 }, +		{ 0x04f4, 0x6604f4 }, +		{ 0x04f8, 0x6604f8 }, +		{ 0x04fc, 0x6604fc }, +		{ 0x0500, 0x660500 }, +		{ 0x0504, 0x660504 }, +		{ 0x0508, 0x660508 }, +		{ 0x050c, 0x66050c }, +		{ 0x0510, 0x660510 }, +		{ 0x0514, 0x660514 }, +		{ 0x0518, 0x660518 }, +		{ 0x051c, 0x66051c }, +		{ 0x0520, 0x660520 }, +		{ 0x0524, 0x660524 }, +		{ 0x052c, 0x66052c }, +		{ 0x0530, 0x660530 }, +		{ 0x054c, 0x66054c }, +		{ 0x0550, 0x660550 }, +		{ 0x0554, 0x660554 }, +		{ 0x0558, 0x660558 }, +		{ 0x055c, 0x66055c }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nve0_disp_mast_mthd_chan = { +	.name = "Core", +	.addr = 0x000000, +	.data = { +		{ "Global", 1, &nvd0_disp_mast_mthd_base }, +		{    "DAC", 3, &nvd0_disp_mast_mthd_dac  }, +		{    "SOR", 8, &nvd0_disp_mast_mthd_sor  }, +		{   "PIOR", 4, &nvd0_disp_mast_mthd_pior }, +		{   "HEAD", 4, &nve0_disp_mast_mthd_head }, +		{} +	} +}; + +/******************************************************************************* + * EVO overlay channel objects + ******************************************************************************/ + +static const struct nv50_disp_mthd_list +nve0_disp_ovly_mthd_base = { +	.mthd = 0x0000, +	.data = { +		{ 0x0080, 0x665080 }, +		{ 0x0084, 0x665084 }, +		{ 0x0088, 0x665088 }, +		{ 0x008c, 0x66508c }, +		{ 0x0090, 0x665090 }, +		{ 0x0094, 0x665094 }, +		{ 0x00a0, 0x6650a0 }, +		{ 0x00a4, 0x6650a4 }, +		{ 0x00b0, 0x6650b0 }, +		{ 0x00b4, 0x6650b4 }, +		{ 0x00b8, 0x6650b8 }, +		{ 0x00c0, 0x6650c0 }, +		{ 0x00c4, 0x6650c4 }, +		{ 0x00e0, 0x6650e0 }, +		{ 0x00e4, 0x6650e4 }, +		{ 0x00e8, 0x6650e8 }, +		{ 0x0100, 0x665100 }, +		{ 0x0104, 0x665104 }, +		{ 0x0108, 0x665108 }, +		{ 0x010c, 0x66510c }, +		{ 0x0110, 0x665110 }, +		{ 0x0118, 0x665118 }, +		{ 0x011c, 0x66511c }, +		{ 0x0120, 0x665120 }, +		{ 0x0124, 0x665124 }, +		{ 0x0130, 0x665130 }, +		{ 0x0134, 0x665134 }, +		{ 0x0138, 0x665138 }, +		{ 0x013c, 0x66513c }, +		{ 0x0140, 0x665140 }, +		{ 0x0144, 0x665144 }, +		{ 0x0148, 0x665148 }, +		{ 0x014c, 0x66514c }, +		{ 0x0150, 0x665150 }, +		{ 0x0154, 0x665154 }, +		{ 0x0158, 0x665158 }, +		{ 0x015c, 0x66515c }, +		{ 0x0160, 0x665160 }, +		{ 0x0164, 0x665164 }, +		{ 0x0168, 0x665168 }, +		{ 0x016c, 0x66516c }, +		{ 0x0400, 0x665400 }, +		{ 0x0404, 0x665404 }, +		{ 0x0408, 0x665408 }, +		{ 0x040c, 0x66540c }, +		{ 0x0410, 0x665410 }, +		{} +	} +}; + +const struct nv50_disp_mthd_chan +nve0_disp_ovly_mthd_chan = { +	.name = "Overlay", +	.addr = 0x001000, +	.data = { +		{ "Global", 1, &nve0_disp_ovly_mthd_base }, +		{} +	} +}; + +/******************************************************************************* + * Base display object + ******************************************************************************/ +  static struct nouveau_oclass  nve0_disp_sclass[] = {  	{ NVE0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs }, @@ -41,10 +210,14 @@ nve0_disp_sclass[] = {  static struct nouveau_oclass  nve0_disp_base_oclass[] = { -	{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, +	{ NVE0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },  	{}  }; +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ +  static int  nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size, @@ -54,9 +227,6 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	int heads = nv_rd32(parent, 0x022448);  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000001) -		return -ENODEV; -  	ret = nouveau_disp_create(parent, engine, oclass, heads,  				  "PDISP", "display", &priv);  	*pobject = nv_object(priv); @@ -76,17 +246,21 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->sor.power = nv50_sor_power;  	priv->sor.hda_eld = nvd0_hda_eld;  	priv->sor.hdmi = nvd0_hdmi_ctrl; -	priv->sor.dp = &nvd0_sor_dp_func;  	return 0;  } -struct nouveau_oclass -nve0_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x91), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nve0_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x91), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nve0_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nvd0_disp_outp_sclass, +	.mthd.core = &nve0_disp_mast_mthd_chan, +	.mthd.base = &nvd0_disp_sync_mthd_chan, +	.mthd.ovly = &nve0_disp_ovly_mthd_chan, +	.mthd.prev = -0x020000, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c index 42aa6b97dbe..104388081d7 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c @@ -29,6 +29,10 @@  #include "nv50.h" +/******************************************************************************* + * Base display object + ******************************************************************************/ +  static struct nouveau_oclass  nvf0_disp_sclass[] = {  	{ NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs }, @@ -41,10 +45,14 @@ nvf0_disp_sclass[] = {  static struct nouveau_oclass  nvf0_disp_base_oclass[] = { -	{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds }, +	{ NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nvd0_disp_base_omthds },  	{}  }; +/******************************************************************************* + * Display engine implementation + ******************************************************************************/ +  static int  nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size, @@ -54,9 +62,6 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	int heads = nv_rd32(parent, 0x022448);  	int ret; -	if (nv_rd32(parent, 0x022500) & 0x00000001) -		return -ENODEV; -  	ret = nouveau_disp_create(parent, engine, oclass, heads,  				  "PDISP", "display", &priv);  	*pobject = nv_object(priv); @@ -76,17 +81,21 @@ nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->sor.power = nv50_sor_power;  	priv->sor.hda_eld = nvd0_hda_eld;  	priv->sor.hdmi = nvd0_hdmi_ctrl; -	priv->sor.dp = &nvd0_sor_dp_func;  	return 0;  } -struct nouveau_oclass -nvf0_disp_oclass = { -	.handle = NV_ENGINE(DISP, 0x92), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nvf0_disp_oclass = &(struct nv50_disp_impl) { +	.base.base.handle = NV_ENGINE(DISP, 0x92), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvf0_disp_ctor,  		.dtor = _nouveau_disp_dtor,  		.init = _nouveau_disp_init,  		.fini = _nouveau_disp_fini,  	}, -}; +	.base.outp =  nvd0_disp_outp_sclass, +	.mthd.core = &nve0_disp_mast_mthd_chan, +	.mthd.base = &nvd0_disp_sync_mthd_chan, +	.mthd.ovly = &nve0_disp_ovly_mthd_chan, +	.mthd.prev = -0x020000, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c new file mode 100644 index 00000000000..ad9ba7ccec7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.c @@ -0,0 +1,137 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/i2c.h> +#include <subdev/bios.h> +#include <subdev/bios/conn.h> + +#include "outp.h" + +int +_nvkm_output_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvkm_output *outp = (void *)object; +	nv_ofuncs(outp->conn)->fini(nv_object(outp->conn), suspend); +	return nouveau_object_fini(&outp->base, suspend); +} + +int +_nvkm_output_init(struct nouveau_object *object) +{ +	struct nvkm_output *outp = (void *)object; +	int ret = nouveau_object_init(&outp->base); +	if (ret == 0) +		nv_ofuncs(outp->conn)->init(nv_object(outp->conn)); +	return 0; +} + +void +_nvkm_output_dtor(struct nouveau_object *object) +{ +	struct nvkm_output *outp = (void *)object; +	list_del(&outp->head); +	nouveau_object_ref(NULL, (void *)&outp->conn); +	nouveau_object_destroy(&outp->base); +} + +int +nvkm_output_create_(struct nouveau_object *parent, +		    struct nouveau_object *engine, +		    struct nouveau_oclass *oclass, +		    struct dcb_output *dcbE, int index, +		    int length, void **pobject) +{ +	struct nouveau_bios *bios = nouveau_bios(engine); +	struct nouveau_i2c *i2c = nouveau_i2c(parent); +	struct nouveau_disp *disp = (void *)engine; +	struct nvbios_connE connE; +	struct nvkm_output *outp; +	u8  ver, hdr; +	u32 data; +	int ret; + +	ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject); +	outp = *pobject; +	if (ret) +		return ret; + +	outp->info = *dcbE; +	outp->index = index; + +	DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n", +	    dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ? +	    dcbE->sorconf.link : 0, dcbE->connector, dcbE->i2c_index, +	    dcbE->bus, dcbE->heads); + +	outp->port = i2c->find(i2c, outp->info.i2c_index); +	outp->edid = outp->port; + +	data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE); +	if (!data) { +		DBG("vbios connector data not found\n"); +		memset(&connE, 0x00, sizeof(connE)); +		connE.type = DCB_CONNECTOR_NONE; +	} + +	ret = nouveau_object_ctor(parent, engine, nvkm_connector_oclass, +				 &connE, outp->info.connector, +				 (struct nouveau_object **)&outp->conn); +	if (ret < 0) { +		ERR("error %d creating connector, disabling\n", ret); +		return ret; +	} + +	list_add_tail(&outp->head, &disp->outp); +	return 0; +} + +int +_nvkm_output_ctor(struct nouveau_object *parent, +		  struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *dcbE, u32 index, +		  struct nouveau_object **pobject) +{ +	struct nvkm_output *outp; +	int ret; + +	ret = nvkm_output_create(parent, engine, oclass, dcbE, index, &outp); +	*pobject = nv_object(outp); +	if (ret) +		return ret; + +	return 0; +} + +struct nouveau_oclass * +nvkm_output_oclass = &(struct nvkm_output_impl) { +	.base = { +		.handle = 0, +		.ofuncs = &(struct nouveau_ofuncs) { +			.ctor = _nvkm_output_ctor, +			.dtor = _nvkm_output_dtor, +			.init = _nvkm_output_init, +			.fini = _nvkm_output_fini, +		}, +	}, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h new file mode 100644 index 00000000000..bc76fbf8571 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/outp.h @@ -0,0 +1,59 @@ +#ifndef __NVKM_DISP_OUTP_H__ +#define __NVKM_DISP_OUTP_H__ + +#include "priv.h" + +struct nvkm_output { +	struct nouveau_object base; +	struct list_head head; + +	struct dcb_output info; +	int index; + +	struct nouveau_i2c_port *port; +	struct nouveau_i2c_port *edid; + +	struct nvkm_connector *conn; +}; + +#define nvkm_output_create(p,e,c,b,i,d)                                        \ +	nvkm_output_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) +#define nvkm_output_destroy(d) ({                                              \ +	struct nvkm_output *_outp = (d);                                       \ +	_nvkm_output_dtor(nv_object(_outp));                                   \ +}) +#define nvkm_output_init(d) ({                                                 \ +	struct nvkm_output *_outp = (d);                                       \ +	_nvkm_output_init(nv_object(_outp));                                   \ +}) +#define nvkm_output_fini(d,s) ({                                               \ +	struct nvkm_output *_outp = (d);                                       \ +	_nvkm_output_fini(nv_object(_outp), (s));                              \ +}) + +int nvkm_output_create_(struct nouveau_object *, struct nouveau_object *, +			struct nouveau_oclass *, struct dcb_output *, +			int, int, void **); + +int  _nvkm_output_ctor(struct nouveau_object *, struct nouveau_object *, +		       struct nouveau_oclass *, void *, u32, +		       struct nouveau_object **); +void _nvkm_output_dtor(struct nouveau_object *); +int  _nvkm_output_init(struct nouveau_object *); +int  _nvkm_output_fini(struct nouveau_object *, bool); + +struct nvkm_output_impl { +	struct nouveau_oclass base; +}; + +#ifndef MSG +#define MSG(l,f,a...) do {                                                     \ +	struct nvkm_output *_outp = (void *)outp;                              \ +	nv_##l(nv_object(outp)->engine, "%02x:%04x:%04x: "f, _outp->index,     \ +	       _outp->info.hasht, _outp->info.hashm, ##a);                     \ +} while(0) +#define DBG(f,a...) MSG(debug, f, ##a) +#define ERR(f,a...) MSG(error, f, ##a) +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c new file mode 100644 index 00000000000..eb2d7789555 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c @@ -0,0 +1,278 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/i2c.h> + +#include "outpdp.h" +#include "conn.h" +#include "dport.h" + +int +nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait) +{ +	struct nvkm_output_dp *outp = (void *)base; +	bool retrain = true; +	u8 link[2], stat[3]; +	u32 linkrate; +	int ret, i; + +	/* check that the link is trained at a high enough rate */ +	ret = nv_rdaux(outp->base.edid, DPCD_LC00_LINK_BW_SET, link, 2); +	if (ret) { +		DBG("failed to read link config, assuming no sink\n"); +		goto done; +	} + +	linkrate = link[0] * 27000 * (link[1] & DPCD_LC01_LANE_COUNT_SET); +	linkrate = (linkrate * 8) / 10; /* 8B/10B coding overhead */ +	datarate = (datarate + 9) / 10; /* -> decakilobits */ +	if (linkrate < datarate) { +		DBG("link not trained at sufficient rate\n"); +		goto done; +	} + +	/* check that link is still trained */ +	ret = nv_rdaux(outp->base.edid, DPCD_LS02, stat, 3); +	if (ret) { +		DBG("failed to read link status, assuming no sink\n"); +		goto done; +	} + +	if (stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE) { +		for (i = 0; i < (link[1] & DPCD_LC01_LANE_COUNT_SET); i++) { +			u8 lane = (stat[i >> 1] >> ((i & 1) * 4)) & 0x0f; +			if (!(lane & DPCD_LS02_LANE0_CR_DONE) || +			    !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || +			    !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) { +				DBG("lane %d not equalised\n", lane); +				goto done; +			} +		} +		retrain = false; +	} else { +		DBG("no inter-lane alignment\n"); +	} + +done: +	if (retrain || !atomic_read(&outp->lt.done)) { +		/* no sink, but still need to configure source */ +		if (outp->dpcd[DPCD_RC00_DPCD_REV] == 0x00) { +			outp->dpcd[DPCD_RC01_MAX_LINK_RATE] = +				outp->base.info.dpconf.link_bw; +			outp->dpcd[DPCD_RC02] = +				outp->base.info.dpconf.link_nr; +		} +		atomic_set(&outp->lt.done, 0); +		schedule_work(&outp->lt.work); +	} else { +		nouveau_event_get(outp->irq); +	} + +	if (wait) { +		if (!wait_event_timeout(outp->lt.wait, +					atomic_read(&outp->lt.done), +					msecs_to_jiffies(2000))) +			ret = -ETIMEDOUT; +	} + +	return ret; +} + +static void +nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool present) +{ +	struct nouveau_i2c_port *port = outp->base.edid; +	if (present) { +		if (!outp->present) { +			nouveau_i2c(port)->acquire_pad(port, 0); +			DBG("aux power -> always\n"); +			outp->present = true; +		} +		nvkm_output_dp_train(&outp->base, 0, true); +	} else { +		if (outp->present) { +			nouveau_i2c(port)->release_pad(port); +			DBG("aux power -> demand\n"); +			outp->present = false; +		} +		atomic_set(&outp->lt.done, 0); +	} +} + +static void +nvkm_output_dp_detect(struct nvkm_output_dp *outp) +{ +	struct nouveau_i2c_port *port = outp->base.edid; +	int ret = nouveau_i2c(port)->acquire_pad(port, 0); +	if (ret == 0) { +		ret = nv_rdaux(outp->base.edid, DPCD_RC00_DPCD_REV, +			       outp->dpcd, sizeof(outp->dpcd)); +		nvkm_output_dp_enable(outp, ret == 0); +		nouveau_i2c(port)->release_pad(port); +	} +} + +static void +nvkm_output_dp_service_work(struct work_struct *work) +{ +	struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work); +	struct nouveau_disp *disp = nouveau_disp(outp); +	int type = atomic_xchg(&outp->pending, 0); +	u32 send = 0; + +	if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) { +		nvkm_output_dp_detect(outp); +		if (type & NVKM_I2C_UNPLUG) +			send |= NVKM_HPD_UNPLUG; +		if (type & NVKM_I2C_PLUG) +			send |= NVKM_HPD_PLUG; +		nouveau_event_get(outp->base.conn->hpd.event); +	} + +	if (type & NVKM_I2C_IRQ) { +		nvkm_output_dp_train(&outp->base, 0, true); +		send |= NVKM_HPD_IRQ; +	} + +	nouveau_event_trigger(disp->hpd, send, outp->base.info.connector); +} + +static int +nvkm_output_dp_service(void *data, u32 type, int index) +{ +	struct nvkm_output_dp *outp = data; +	DBG("HPD: %d\n", type); +	atomic_or(type, &outp->pending); +	schedule_work(&outp->work); +	return NVKM_EVENT_DROP; +} + +int +_nvkm_output_dp_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvkm_output_dp *outp = (void *)object; +	nouveau_event_put(outp->irq); +	nvkm_output_dp_enable(outp, false); +	return nvkm_output_fini(&outp->base, suspend); +} + +int +_nvkm_output_dp_init(struct nouveau_object *object) +{ +	struct nvkm_output_dp *outp = (void *)object; +	nvkm_output_dp_detect(outp); +	return nvkm_output_init(&outp->base); +} + +void +_nvkm_output_dp_dtor(struct nouveau_object *object) +{ +	struct nvkm_output_dp *outp = (void *)object; +	nouveau_event_ref(NULL, &outp->irq); +	nvkm_output_destroy(&outp->base); +} + +int +nvkm_output_dp_create_(struct nouveau_object *parent, +		       struct nouveau_object *engine, +		       struct nouveau_oclass *oclass, +		       struct dcb_output *info, int index, +		       int length, void **pobject) +{ +	struct nouveau_bios *bios = nouveau_bios(parent); +	struct nouveau_i2c *i2c = nouveau_i2c(parent); +	struct nvkm_output_dp *outp; +	u8  hdr, cnt, len; +	u32 data; +	int ret; + +	ret = nvkm_output_create_(parent, engine, oclass, info, index, +				  length, pobject); +	outp = *pobject; +	if (ret) +		return ret; + +	nouveau_event_ref(NULL, &outp->base.conn->hpd.event); + +	/* access to the aux channel is not optional... */ +	if (!outp->base.edid) { +		ERR("aux channel not found\n"); +		return -ENODEV; +	} + +	/* nor is the bios data for this output... */ +	data = nvbios_dpout_match(bios, outp->base.info.hasht, +				  outp->base.info.hashm, &outp->version, +				  &hdr, &cnt, &len, &outp->info); +	if (!data) { +		ERR("no bios dp data\n"); +		return -ENODEV; +	} + +	DBG("bios dp %02x %02x %02x %02x\n", outp->version, hdr, cnt, len); + +	/* link training */ +	INIT_WORK(&outp->lt.work, nouveau_dp_train); +	init_waitqueue_head(&outp->lt.wait); +	atomic_set(&outp->lt.done, 0); + +	/* link maintenance */ +	ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_IRQ, outp->base.edid->index, +				nvkm_output_dp_service, outp, &outp->irq); +	if (ret) { +		ERR("error monitoring aux irq event: %d\n", ret); +		return ret; +	} + +	INIT_WORK(&outp->work, nvkm_output_dp_service_work); + +	/* hotplug detect, replaces gpio-based mechanism with aux events */ +	ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG, +				outp->base.edid->index, +				nvkm_output_dp_service, outp, +			       &outp->base.conn->hpd.event); +	if (ret) { +		ERR("error monitoring aux hpd events: %d\n", ret); +		return ret; +	} + +	return 0; +} + +int +_nvkm_output_dp_ctor(struct nouveau_object *parent, +		     struct nouveau_object *engine, +		     struct nouveau_oclass *oclass, void *info, u32 index, +		     struct nouveau_object **pobject) +{ +	struct nvkm_output_dp *outp; +	int ret; + +	ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp); +	*pobject = nv_object(outp); +	if (ret) +		return ret; + +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h new file mode 100644 index 00000000000..ff33ba12cb6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h @@ -0,0 +1,65 @@ +#ifndef __NVKM_DISP_OUTP_DP_H__ +#define __NVKM_DISP_OUTP_DP_H__ + +#include <subdev/bios.h> +#include <subdev/bios/dp.h> + +#include "outp.h" + +struct nvkm_output_dp { +	struct nvkm_output base; + +	struct nvbios_dpout info; +	u8 version; + +	struct nouveau_eventh *irq; +	struct nouveau_eventh *hpd; +	struct work_struct work; +	atomic_t pending; +	bool present; +	u8 dpcd[16]; + +	struct { +		struct work_struct work; +		wait_queue_head_t wait; +		atomic_t done; +	} lt; +}; + +#define nvkm_output_dp_create(p,e,c,b,i,d)                                     \ +	nvkm_output_dp_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) +#define nvkm_output_dp_destroy(d) ({                                           \ +	struct nvkm_output_dp *_outp = (d);                                    \ +	_nvkm_output_dp_dtor(nv_object(_outp));                                \ +}) +#define nvkm_output_dp_init(d) ({                                              \ +	struct nvkm_output_dp *_outp = (d);                                    \ +	_nvkm_output_dp_init(nv_object(_outp));                                \ +}) +#define nvkm_output_dp_fini(d,s) ({                                            \ +	struct nvkm_output_dp *_outp = (d);                                    \ +	_nvkm_output_dp_fini(nv_object(_outp), (s));                           \ +}) + +int nvkm_output_dp_create_(struct nouveau_object *, struct nouveau_object *, +			   struct nouveau_oclass *, struct dcb_output *, +			   int, int, void **); + +int  _nvkm_output_dp_ctor(struct nouveau_object *, struct nouveau_object *, +			  struct nouveau_oclass *, void *, u32, +			  struct nouveau_object **); +void _nvkm_output_dp_dtor(struct nouveau_object *); +int  _nvkm_output_dp_init(struct nouveau_object *); +int  _nvkm_output_dp_fini(struct nouveau_object *, bool); + +struct nvkm_output_dp_impl { +	struct nvkm_output_impl base; +	int (*pattern)(struct nvkm_output_dp *, int); +	int (*lnk_pwr)(struct nvkm_output_dp *, int nr); +	int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef); +	int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc); +}; + +int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c index 2c8ce351b52..fe0f256f11b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c @@ -33,68 +33,107 @@  #include "nv50.h"  /****************************************************************************** - * DisplayPort + * TMDS   *****************************************************************************/ -static struct nouveau_i2c_port * -nv50_pior_dp_find(struct nouveau_disp *disp, struct dcb_output *outp) + +static int +nv50_pior_tmds_ctor(struct nouveau_object *parent, +		    struct nouveau_object *engine, +		    struct nouveau_oclass *oclass, void *info, u32 index, +		    struct nouveau_object **pobject)  { -	struct nouveau_i2c *i2c = nouveau_i2c(disp); -	return i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); +	struct nouveau_i2c *i2c = nouveau_i2c(parent); +	struct nvkm_output *outp; +	int ret; + +	ret = nvkm_output_create(parent, engine, oclass, info, index, &outp); +	*pobject = nv_object(outp); +	if (ret) +		return ret; + +	outp->edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(outp->info.extdev)); +	return 0;  } +struct nvkm_output_impl +nv50_pior_tmds_impl = { +	.base.handle = DCB_OUTPUT_TMDS | 0x0100, +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_pior_tmds_ctor, +		.dtor = _nvkm_output_dtor, +		.init = _nvkm_output_init, +		.fini = _nvkm_output_fini, +	}, +}; + +/****************************************************************************** + * DisplayPort + *****************************************************************************/ +  static int -nv50_pior_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, -		     int head, int pattern) +nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern)  { -	struct nouveau_i2c_port *port; -	int ret = -EINVAL; - -	port = nv50_pior_dp_find(disp, outp); -	if (port) { -		if (port->func->pattern) -			ret = port->func->pattern(port, pattern); -		else -			ret = 0; -	} - -	return ret; +	struct nouveau_i2c_port *port = outp->base.edid; +	if (port && port->func->pattern) +		return port->func->pattern(port, pattern); +	return port ? 0 : -ENODEV;  }  static int -nv50_pior_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, -		     int head, int lane_nr, int link_bw, bool enh) +nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)  { -	struct nouveau_i2c_port *port; -	int ret = -EINVAL; +	return 0; +} -	port = nv50_pior_dp_find(disp, outp); +static int +nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) +{ +	struct nouveau_i2c_port *port = outp->base.edid;  	if (port && port->func->lnk_ctl) -		ret = port->func->lnk_ctl(port, lane_nr, link_bw, enh); +		return port->func->lnk_ctl(port, nr, bw, ef); +	return port ? 0 : -ENODEV; +} -	return ret; +static int +nv50_pior_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) +{ +	struct nouveau_i2c_port *port = outp->base.edid; +	if (port && port->func->drv_ctl) +		return port->func->drv_ctl(port, ln, vs, pe); +	return port ? 0 : -ENODEV;  }  static int -nv50_pior_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, -		     int head, int lane, int vsw, int pre) +nv50_pior_dp_ctor(struct nouveau_object *parent, +		  struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *info, u32 index, +		  struct nouveau_object **pobject)  { -	struct nouveau_i2c_port *port; -	int ret = -EINVAL; - -	port = nv50_pior_dp_find(disp, outp); -	if (port) { -		if (port->func->drv_ctl) -			ret = port->func->drv_ctl(port, lane, vsw, pre); -		else -			ret = 0; -	} +	struct nouveau_i2c *i2c = nouveau_i2c(parent); +	struct nvkm_output_dp *outp; +	int ret; -	return ret; +	ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp); +	*pobject = nv_object(outp); +	if (ret) +		return ret; + +	outp->base.edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX( +					 outp->base.info.extdev)); +	return 0;  } -const struct nouveau_dp_func -nv50_pior_dp_func = { +struct nvkm_output_dp_impl +nv50_pior_dp_impl = { +	.base.base.handle = DCB_OUTPUT_DP | 0x0010, +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_pior_dp_ctor, +		.dtor = _nvkm_output_dp_dtor, +		.init = _nvkm_output_dp_init, +		.fini = _nvkm_output_dp_fini, +	},  	.pattern = nv50_pior_dp_pattern, +	.lnk_pwr = nv50_pior_dp_lnk_pwr,  	.lnk_ctl = nv50_pior_dp_lnk_ctl,  	.drv_ctl = nv50_pior_dp_drv_ctl,  }; @@ -102,6 +141,7 @@ nv50_pior_dp_func = {  /******************************************************************************   * General PIOR handling   *****************************************************************************/ +  int  nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data)  { diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/priv.h b/drivers/gpu/drm/nouveau/core/engine/disp/priv.h new file mode 100644 index 00000000000..26e9a42569c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/disp/priv.h @@ -0,0 +1,42 @@ +#ifndef __NVKM_DISP_PRIV_H__ +#define __NVKM_DISP_PRIV_H__ + +#include <subdev/bios.h> +#include <subdev/bios/dcb.h> +#include <subdev/bios/conn.h> + +#include <engine/disp.h> + +struct nouveau_disp_impl { +	struct nouveau_oclass base; +	struct nouveau_oclass **outp; +	struct nouveau_oclass **conn; +}; + +#define nouveau_disp_create(p,e,c,h,i,x,d)                                     \ +	nouveau_disp_create_((p), (e), (c), (h), (i), (x),                     \ +			     sizeof(**d), (void **)d) +#define nouveau_disp_destroy(d) ({                                             \ +	struct nouveau_disp *disp = (d);                                       \ +	_nouveau_disp_dtor(nv_object(disp));                                   \ +}) +#define nouveau_disp_init(d) ({                                                \ +	struct nouveau_disp *disp = (d);                                       \ +	_nouveau_disp_init(nv_object(disp));                                   \ +}) +#define nouveau_disp_fini(d,s) ({                                              \ +	struct nouveau_disp *disp = (d);                                       \ +	_nouveau_disp_fini(nv_object(disp), (s));                              \ +}) + +int  nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *, +			  struct nouveau_oclass *, int heads, +			  const char *, const char *, int, void **); +void _nouveau_disp_dtor(struct nouveau_object *); +int  _nouveau_disp_init(struct nouveau_object *); +int  _nouveau_disp_fini(struct nouveau_object *, bool); + +extern struct nouveau_oclass *nvkm_output_oclass; +extern struct nouveau_oclass *nvkm_connector_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index 526b7524289..7a1ebdfa9e1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -47,8 +47,12 @@ int  nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)  {  	struct nv50_disp_priv *priv = (void *)object->engine; +	const u8  type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;  	const u8  head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; +	const u8  link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;  	const u8    or = (mthd & NV50_DISP_SOR_MTHD_OR); +	const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or); +	struct nvkm_output *outp = NULL, *temp;  	u32 data;  	int ret = -EINVAL; @@ -56,6 +60,13 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)  		return -EINVAL;  	data = *(u32 *)args; +	list_for_each_entry(temp, &priv->base.outp, head) { +		if ((temp->info.hasht & 0xff) == type && +		    (temp->info.hashm & mask) == mask) { +			outp = temp; +			break; +		} +	}  	switch (mthd & ~0x3f) {  	case NV50_DISP_SOR_PWR: @@ -71,6 +82,24 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)  		priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID;  		ret = 0;  		break; +	case NV94_DISP_SOR_DP_PWR: +		if (outp) { +			struct nvkm_output_dp *outpdp = (void *)outp; +			switch (data) { +			case NV94_DISP_SOR_DP_PWR_STATE_OFF: +				nouveau_event_put(outpdp->irq); +				((struct nvkm_output_dp_impl *)nv_oclass(outp)) +					->lnk_pwr(outpdp, 0); +				atomic_set(&outpdp->lt.done, 0); +				break; +			case NV94_DISP_SOR_DP_PWR_STATE_ON: +				nvkm_output_dp_train(&outpdp->base, 0, true); +				break; +			default: +				return -EINVAL; +			} +		} +		break;  	default:  		BUG_ON(1);  	} diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c index 7ec4ee83fb6..05487cda84a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c @@ -29,19 +29,21 @@  #include <subdev/bios/dcb.h>  #include <subdev/bios/dp.h>  #include <subdev/bios/init.h> +#include <subdev/timer.h>  #include "nv50.h" +#include "outpdp.h"  static inline u32 -nv94_sor_soff(struct dcb_output *outp) +nv94_sor_soff(struct nvkm_output_dp *outp)  { -	return (ffs(outp->or) - 1) * 0x800; +	return (ffs(outp->base.info.or) - 1) * 0x800;  }  static inline u32 -nv94_sor_loff(struct dcb_output *outp) +nv94_sor_loff(struct nvkm_output_dp *outp)  { -	return nv94_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; +	return nv94_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;  }  static inline u32 @@ -55,73 +57,96 @@ nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)  }  static int -nv94_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, -		    int head, int pattern) +nv94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)  { -	struct nv50_disp_priv *priv = (void *)disp; +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);  	const u32 loff = nv94_sor_loff(outp);  	nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24);  	return 0;  } +int +nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) +{ +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); +	const u32 soff = nv94_sor_soff(outp); +	const u32 loff = nv94_sor_loff(outp); +	u32 mask = 0, i; + +	for (i = 0; i < nr; i++) +		mask |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3); + +	nv_mask(priv, 0x61c130 + loff, 0x0000000f, mask); +	nv_mask(priv, 0x61c034 + soff, 0x80000000, 0x80000000); +	nv_wait(priv, 0x61c034 + soff, 0x80000000, 0x00000000); +	return 0; +} +  static int -nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, -		    int head, int link_nr, int link_bw, bool enh_frame) +nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)  { -	struct nv50_disp_priv *priv = (void *)disp; +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);  	const u32 soff = nv94_sor_soff(outp);  	const u32 loff = nv94_sor_loff(outp);  	u32 dpctrl = 0x00000000;  	u32 clksor = 0x00000000; -	u32 lane = 0; -	int i; -	dpctrl |= ((1 << link_nr) - 1) << 16; -	if (enh_frame) +	dpctrl |= ((1 << nr) - 1) << 16; +	if (ef)  		dpctrl |= 0x00004000; -	if (link_bw > 0x06) +	if (bw > 0x06)  		clksor |= 0x00040000; -	for (i = 0; i < link_nr; i++) -		lane |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3); -  	nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor);  	nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); -	nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane);  	return 0;  }  static int -nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, -		    int head, int lane, int swing, int preem) +nv94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)  { -	struct nouveau_bios *bios = nouveau_bios(disp); -	struct nv50_disp_priv *priv = (void *)disp; +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); +	struct nouveau_bios *bios = nouveau_bios(priv); +	const u32 shift = nv94_sor_dp_lane_map(priv, ln);  	const u32 loff = nv94_sor_loff(outp); -	u32 addr, shift = nv94_sor_dp_lane_map(priv, lane); +	u32 addr, data[3];  	u8  ver, hdr, cnt, len;  	struct nvbios_dpout info;  	struct nvbios_dpcfg ocfg; -	addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, +	addr = nvbios_dpout_match(bios, outp->base.info.hasht, +					outp->base.info.hashm,  				 &ver, &hdr, &cnt, &len, &info);  	if (!addr)  		return -ENODEV; -	addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, +	addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe,  				 &ver, &hdr, &cnt, &len, &ocfg);  	if (!addr)  		return -EINVAL; -	nv_mask(priv, 0x61c118 + loff, 0x000000ff << shift, ocfg.drv << shift); -	nv_mask(priv, 0x61c120 + loff, 0x000000ff << shift, ocfg.pre << shift); -	nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8); +	data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); +	data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); +	data[2] = nv_rd32(priv, 0x61c130 + loff); +	if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) +		data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); +	nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); +	nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); +	nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8));  	return 0;  } -const struct nouveau_dp_func -nv94_sor_dp_func = { +struct nvkm_output_dp_impl +nv94_sor_dp_impl = { +	.base.base.handle = DCB_OUTPUT_DP, +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nvkm_output_dp_ctor, +		.dtor = _nvkm_output_dp_dtor, +		.init = _nvkm_output_dp_init, +		.fini = _nvkm_output_dp_fini, +	},  	.pattern = nv94_sor_dp_pattern, +	.lnk_pwr = nv94_sor_dp_lnk_pwr,  	.lnk_ctl = nv94_sor_dp_lnk_ctl,  	.drv_ctl = nv94_sor_dp_drv_ctl,  }; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c index 9e1d435d728..97f0e9cd3d4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c @@ -29,19 +29,20 @@  #include <subdev/bios/dcb.h>  #include <subdev/bios/dp.h>  #include <subdev/bios/init.h> +#include <subdev/timer.h>  #include "nv50.h"  static inline u32 -nvd0_sor_soff(struct dcb_output *outp) +nvd0_sor_soff(struct nvkm_output_dp *outp)  { -	return (ffs(outp->or) - 1) * 0x800; +	return (ffs(outp->base.info.or) - 1) * 0x800;  }  static inline u32 -nvd0_sor_loff(struct dcb_output *outp) +nvd0_sor_loff(struct nvkm_output_dp *outp)  { -	return nvd0_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; +	return nvd0_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80;  }  static inline u32 @@ -52,73 +53,80 @@ nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane)  }  static int -nvd0_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, -		    int head, int pattern) +nvd0_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)  { -	struct nv50_disp_priv *priv = (void *)disp; +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);  	const u32 loff = nvd0_sor_loff(outp);  	nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);  	return 0;  }  static int -nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, -		    int head, int link_nr, int link_bw, bool enh_frame) +nvd0_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)  { -	struct nv50_disp_priv *priv = (void *)disp; +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp);  	const u32 soff = nvd0_sor_soff(outp);  	const u32 loff = nvd0_sor_loff(outp);  	u32 dpctrl = 0x00000000;  	u32 clksor = 0x00000000; -	u32 lane = 0; -	int i; -	clksor |= link_bw << 18; -	dpctrl |= ((1 << link_nr) - 1) << 16; -	if (enh_frame) +	clksor |= bw << 18; +	dpctrl |= ((1 << nr) - 1) << 16; +	if (ef)  		dpctrl |= 0x00004000; -	for (i = 0; i < link_nr; i++) -		lane |= 1 << (nvd0_sor_dp_lane_map(priv, i) >> 3); -  	nv_mask(priv, 0x612300 + soff, 0x007c0000, clksor);  	nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); -	nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane);  	return 0;  }  static int -nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, -		    int head, int lane, int swing, int preem) +nvd0_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc)  { -	struct nouveau_bios *bios = nouveau_bios(disp); -	struct nv50_disp_priv *priv = (void *)disp; +	struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); +	struct nouveau_bios *bios = nouveau_bios(priv); +	const u32 shift = nvd0_sor_dp_lane_map(priv, ln);  	const u32 loff = nvd0_sor_loff(outp); -	u32 addr, shift = nvd0_sor_dp_lane_map(priv, lane); +	u32 addr, data[4];  	u8  ver, hdr, cnt, len;  	struct nvbios_dpout info;  	struct nvbios_dpcfg ocfg; -	addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, +	addr = nvbios_dpout_match(bios, outp->base.info.hasht, +					outp->base.info.hashm,  				 &ver, &hdr, &cnt, &len, &info);  	if (!addr)  		return -ENODEV; -	addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, +	addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe,  				 &ver, &hdr, &cnt, &len, &ocfg);  	if (!addr)  		return -EINVAL; -	nv_mask(priv, 0x61c118 + loff, 0x000000ff << shift, ocfg.drv << shift); -	nv_mask(priv, 0x61c120 + loff, 0x000000ff << shift, ocfg.pre << shift); -	nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8); -	nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000); +	data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); +	data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); +	data[2] = nv_rd32(priv, 0x61c130 + loff); +	if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) +		data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); +	nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); +	nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); +	nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8)); +	data[3] = nv_rd32(priv, 0x61c13c + loff) & ~(0x000000ff << shift); +	nv_wr32(priv, 0x61c13c + loff, data[3] | (ocfg.pc << shift));  	return 0;  } -const struct nouveau_dp_func -nvd0_sor_dp_func = { +struct nvkm_output_dp_impl +nvd0_sor_dp_impl = { +	.base.base.handle = DCB_OUTPUT_DP, +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nvkm_output_dp_ctor, +		.dtor = _nvkm_output_dp_dtor, +		.init = _nvkm_output_dp_init, +		.fini = _nvkm_output_dp_fini, +	},  	.pattern = nvd0_sor_dp_pattern, +	.lnk_pwr = nv94_sor_dp_lnk_pwr,  	.lnk_ctl = nvd0_sor_dp_lnk_ctl,  	.drv_ctl = nvd0_sor_dp_drv_ctl,  }; diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c index 5a1c6847459..8836c3cb99c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/vga.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/vga.c @@ -138,10 +138,15 @@ nv_wrvgai(void *obj, int head, u16 port, u8 index, u8 value)  bool  nv_lockvgac(void *obj, bool lock)  { +	struct nouveau_device *dev = nv_device(obj); +  	bool locked = !nv_rdvgac(obj, 0, 0x1f);  	u8 data = lock ? 0x99 : 0x57; -	nv_wrvgac(obj, 0, 0x1f, data); -	if (nv_device(obj)->chipset == 0x11) { +	if (dev->card_type < NV_50) +		nv_wrvgac(obj, 0, 0x1f, data); +	else +		nv_wrvgac(obj, 0, 0x3f, data); +	if (dev->chipset == 0x11) {  		if (!(nv_rd32(obj, 0x001084) & 0x10000000))  			nv_wrvgac(obj, 1, 0x1f, data);  	} diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c index 944e73ac485..1cfb3bb9013 100644 --- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c @@ -53,6 +53,9 @@ nvd0_dmaobj_bind(struct nouveau_dmaeng *dmaeng,  		case NVF0_DISP_MAST_CLASS:  		case NVF0_DISP_SYNC_CLASS:  		case NVF0_DISP_OVLY_CLASS: +		case GM107_DISP_MAST_CLASS: +		case GM107_DISP_SYNC_CLASS: +		case GM107_DISP_OVLY_CLASS:  			break;  		default:  			return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/core/engine/falcon.c b/drivers/gpu/drm/nouveau/core/engine/falcon.c index e03fc8e4dc1..2914646c870 100644 --- a/drivers/gpu/drm/nouveau/core/engine/falcon.c +++ b/drivers/gpu/drm/nouveau/core/engine/falcon.c @@ -56,6 +56,16 @@ _nouveau_falcon_wr32(struct nouveau_object *object, u64 addr, u32 data)  	nv_wr32(falcon, falcon->addr + addr, data);  } +static void * +vmemdup(const void *src, size_t len) +{ +	void *p = vmalloc(len); + +	if (p) +		memcpy(p, src, len); +	return p; +} +  int  _nouveau_falcon_init(struct nouveau_object *object)  { @@ -109,9 +119,9 @@ _nouveau_falcon_init(struct nouveau_object *object)  		snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03x",  			 device->chipset, falcon->addr >> 12); -		ret = request_firmware(&fw, name, &device->pdev->dev); +		ret = request_firmware(&fw, name, nv_device_base(device));  		if (ret == 0) { -			falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL); +			falcon->code.data = vmemdup(fw->data, fw->size);  			falcon->code.size = fw->size;  			falcon->data.data = NULL;  			falcon->data.size = 0; @@ -128,13 +138,13 @@ _nouveau_falcon_init(struct nouveau_object *object)  		snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xd",  			 device->chipset, falcon->addr >> 12); -		ret = request_firmware(&fw, name, &device->pdev->dev); +		ret = request_firmware(&fw, name, nv_device_base(device));  		if (ret) {  			nv_error(falcon, "unable to load firmware data\n");  			return ret;  		} -		falcon->data.data = kmemdup(fw->data, fw->size, GFP_KERNEL); +		falcon->data.data = vmemdup(fw->data, fw->size);  		falcon->data.size = fw->size;  		release_firmware(fw);  		if (!falcon->data.data) @@ -143,13 +153,13 @@ _nouveau_falcon_init(struct nouveau_object *object)  		snprintf(name, sizeof(name), "nouveau/nv%02x_fuc%03xc",  			 device->chipset, falcon->addr >> 12); -		ret = request_firmware(&fw, name, &device->pdev->dev); +		ret = request_firmware(&fw, name, nv_device_base(device));  		if (ret) {  			nv_error(falcon, "unable to load firmware code\n");  			return ret;  		} -		falcon->code.data = kmemdup(fw->data, fw->size, GFP_KERNEL); +		falcon->code.data = vmemdup(fw->data, fw->size);  		falcon->code.size = fw->size;  		release_firmware(fw);  		if (!falcon->code.data) @@ -235,8 +245,8 @@ _nouveau_falcon_fini(struct nouveau_object *object, bool suspend)  	if (!suspend) {  		nouveau_gpuobj_ref(NULL, &falcon->core);  		if (falcon->external) { -			kfree(falcon->data.data); -			kfree(falcon->code.data); +			vfree(falcon->data.data); +			vfree(falcon->code.data);  			falcon->code.data = NULL;  		}  	} diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index d3ec436d9cb..56ed3d73bf8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -86,12 +86,12 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,  	}  	/* map fifo control registers */ -	chan->user = ioremap(pci_resource_start(device->pdev, bar) + addr + +	chan->user = ioremap(nv_device_resource_start(device, bar) + addr +  			     (chan->chid * size), size);  	if (!chan->user)  		return -EFAULT; -	nouveau_event_trigger(priv->cevent, 0); +	nouveau_event_trigger(priv->cevent, 1, 0);  	chan->size = size;  	return 0; @@ -194,11 +194,11 @@ nouveau_fifo_create_(struct nouveau_object *parent,  	if (!priv->channel)  		return -ENOMEM; -	ret = nouveau_event_create(1, &priv->cevent); +	ret = nouveau_event_create(1, 1, &priv->cevent);  	if (ret)  		return ret; -	ret = nouveau_event_create(1, &priv->uevent); +	ret = nouveau_event_create(1, 1, &priv->uevent);  	if (ret)  		return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c new file mode 100644 index 00000000000..327456eae96 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/gk20a.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "nve0.h" + +struct nouveau_oclass * +gk20a_fifo_oclass = &(struct nve0_fifo_impl) { +	.base.handle = NV_ENGINE(FIFO, 0xea), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nve0_fifo_ctor, +		.dtor = nve0_fifo_dtor, +		.init = nve0_fifo_init, +		.fini = nve0_fifo_fini, +	}, +	.channels = 128, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index f877bd524a9..c61b16a6388 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -539,7 +539,7 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)  			}  			if (status & 0x40000000) { -				nouveau_event_trigger(priv->base.uevent, 0); +				nouveau_event_trigger(priv->base.uevent, 1, 0);  				nv_wr32(priv, 0x002100, 0x40000000);  				status &= ~0x40000000;  			} @@ -632,8 +632,8 @@ nv04_fifo_init(struct nouveau_object *object)  	return 0;  } -struct nouveau_oclass -nv04_fifo_oclass = { +struct nouveau_oclass * +nv04_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0x04),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 2c927c1d173..571a22aa1ae 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -159,8 +159,8 @@ nv10_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -struct nouveau_oclass -nv10_fifo_oclass = { +struct nouveau_oclass * +nv10_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0x10),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv10_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c new file mode 100644 index 00000000000..09362a51ba5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv108.c @@ -0,0 +1,37 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nve0.h" + +struct nouveau_oclass * +nv108_fifo_oclass = &(struct nve0_fifo_impl) { +	.base.handle = NV_ENGINE(FIFO, 0x08), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nve0_fifo_ctor, +		.dtor = nve0_fifo_dtor, +		.init = nve0_fifo_init, +		.fini = _nouveau_fifo_fini, +	}, +	.channels = 1024, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index a9cb51d38c5..f2576020931 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -196,8 +196,8 @@ nv17_fifo_init(struct nouveau_object *object)  	return 0;  } -struct nouveau_oclass -nv17_fifo_oclass = { +struct nouveau_oclass * +nv17_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0x17),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv17_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 5c7433d5069..343487ed223 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -337,8 +337,8 @@ nv40_fifo_init(struct nouveau_object *object)  	return 0;  } -struct nouveau_oclass -nv40_fifo_oclass = { +struct nouveau_oclass * +nv40_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0x40),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv40_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 7e5dff51d3c..e6352bd5b4f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -33,6 +33,7 @@  #include <engine/dmaobj.h>  #include <engine/fifo.h> +#include "nv04.h"  #include "nv50.h"  /******************************************************************************* @@ -460,6 +461,8 @@ nv50_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	nv_subdev(priv)->intr = nv04_fifo_intr;  	nv_engine(priv)->cclass = &nv50_fifo_cclass;  	nv_engine(priv)->sclass = nv50_fifo_sclass; +	priv->base.pause = nv04_fifo_pause; +	priv->base.start = nv04_fifo_start;  	return 0;  } @@ -502,8 +505,8 @@ nv50_fifo_init(struct nouveau_object *object)  	return 0;  } -struct nouveau_oclass -nv50_fifo_oclass = { +struct nouveau_oclass * +nv50_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0x50),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 91a87cd7195..6e5ac16e546 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -35,6 +35,7 @@  #include <engine/dmaobj.h>  #include <engine/fifo.h> +#include "nv04.h"  #include "nv50.h"  /******************************************************************************* @@ -144,7 +145,7 @@ nv84_fifo_object_attach(struct nouveau_object *parent,  	case NVDEV_ENGINE_COPY0 : context |= 0x00300000; break;  	case NVDEV_ENGINE_VP    : context |= 0x00400000; break;  	case NVDEV_ENGINE_CRYPT : -	case NVDEV_ENGINE_UNK1C1: context |= 0x00500000; break; +	case NVDEV_ENGINE_VIC   : context |= 0x00500000; break;  	case NVDEV_ENGINE_BSP   : context |= 0x00600000; break;  	default:  		return -EINVAL; @@ -180,7 +181,7 @@ nv84_fifo_chan_ctor_dma(struct nouveau_object *parent,  					  (1ULL << NVDEV_ENGINE_BSP) |  					  (1ULL << NVDEV_ENGINE_PPP) |  					  (1ULL << NVDEV_ENGINE_COPY0) | -					  (1ULL << NVDEV_ENGINE_UNK1C1), &chan); +					  (1ULL << NVDEV_ENGINE_VIC), &chan);  	*pobject = nv_object(chan);  	if (ret)  		return ret; @@ -243,7 +244,7 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent,  					  (1ULL << NVDEV_ENGINE_BSP) |  					  (1ULL << NVDEV_ENGINE_PPP) |  					  (1ULL << NVDEV_ENGINE_COPY0) | -					  (1ULL << NVDEV_ENGINE_UNK1C1), &chan); +					  (1ULL << NVDEV_ENGINE_VIC), &chan);  	*pobject = nv_object(chan);  	if (ret)  		return ret; @@ -388,14 +389,14 @@ nv84_fifo_cclass = {   ******************************************************************************/  static void -nv84_fifo_uevent_enable(struct nouveau_event *event, int index) +nv84_fifo_uevent_enable(struct nouveau_event *event, int type, int index)  {  	struct nv84_fifo_priv *priv = event->priv;  	nv_mask(priv, 0x002140, 0x40000000, 0x40000000);  }  static void -nv84_fifo_uevent_disable(struct nouveau_event *event, int index) +nv84_fifo_uevent_disable(struct nouveau_event *event, int type, int index)  {  	struct nv84_fifo_priv *priv = event->priv;  	nv_mask(priv, 0x002140, 0x40000000, 0x00000000); @@ -432,11 +433,13 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	nv_subdev(priv)->intr = nv04_fifo_intr;  	nv_engine(priv)->cclass = &nv84_fifo_cclass;  	nv_engine(priv)->sclass = nv84_fifo_sclass; +	priv->base.pause = nv04_fifo_pause; +	priv->base.start = nv04_fifo_start;  	return 0;  } -struct nouveau_oclass -nv84_fifo_oclass = { +struct nouveau_oclass * +nv84_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0x84),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv84_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index ce92f289e75..ae4a4dc5642 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -33,6 +33,7 @@  #include <subdev/timer.h>  #include <subdev/bar.h> +#include <subdev/fb.h>  #include <subdev/vm.h>  #include <engine/dmaobj.h> @@ -40,8 +41,16 @@  struct nvc0_fifo_priv {  	struct nouveau_fifo base; -	struct nouveau_gpuobj *playlist[2]; -	int cur_playlist; + +	struct work_struct fault; +	u64 mask; + +	struct { +		struct nouveau_gpuobj *mem[2]; +		int active; +		wait_queue_head_t wait; +	} runlist; +  	struct {  		struct nouveau_gpuobj *mem;  		struct nouveau_vma bar; @@ -57,6 +66,11 @@ struct nvc0_fifo_base {  struct nvc0_fifo_chan {  	struct nouveau_fifo_chan base; +	enum { +		STOPPED, +		RUNNING, +		KILLED +	} state;  };  /******************************************************************************* @@ -64,29 +78,33 @@ struct nvc0_fifo_chan {   ******************************************************************************/  static void -nvc0_fifo_playlist_update(struct nvc0_fifo_priv *priv) +nvc0_fifo_runlist_update(struct nvc0_fifo_priv *priv)  {  	struct nouveau_bar *bar = nouveau_bar(priv);  	struct nouveau_gpuobj *cur;  	int i, p;  	mutex_lock(&nv_subdev(priv)->mutex); -	cur = priv->playlist[priv->cur_playlist]; -	priv->cur_playlist = !priv->cur_playlist; +	cur = priv->runlist.mem[priv->runlist.active]; +	priv->runlist.active = !priv->runlist.active;  	for (i = 0, p = 0; i < 128; i++) { -		if (!(nv_rd32(priv, 0x003004 + (i * 8)) & 1)) -			continue; -		nv_wo32(cur, p + 0, i); -		nv_wo32(cur, p + 4, 0x00000004); -		p += 8; +		struct nvc0_fifo_chan *chan = (void *)priv->base.channel[i]; +		if (chan && chan->state == RUNNING) { +			nv_wo32(cur, p + 0, i); +			nv_wo32(cur, p + 4, 0x00000004); +			p += 8; +		}  	}  	bar->flush(bar);  	nv_wr32(priv, 0x002270, cur->addr >> 12);  	nv_wr32(priv, 0x002274, 0x01f00000 | (p >> 3)); -	if (!nv_wait(priv, 0x00227c, 0x00100000, 0x00000000)) -		nv_error(priv, "playlist update failed\n"); + +	if (wait_event_timeout(priv->runlist.wait, +			       !(nv_rd32(priv, 0x00227c) & 0x00100000), +			       msecs_to_jiffies(2000)) == 0) +		nv_error(priv, "runlist update timeout\n");  	mutex_unlock(&nv_subdev(priv)->mutex);  } @@ -238,30 +256,32 @@ nvc0_fifo_chan_init(struct nouveau_object *object)  		return ret;  	nv_wr32(priv, 0x003000 + (chid * 8), 0xc0000000 | base->addr >> 12); -	nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001); -	nvc0_fifo_playlist_update(priv); + +	if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) { +		nv_wr32(priv, 0x003004 + (chid * 8), 0x001f0001); +		nvc0_fifo_runlist_update(priv); +	} +  	return 0;  } +static void nvc0_fifo_intr_engine(struct nvc0_fifo_priv *priv); +  static int  nvc0_fifo_chan_fini(struct nouveau_object *object, bool suspend)  {  	struct nvc0_fifo_priv *priv = (void *)object->engine;  	struct nvc0_fifo_chan *chan = (void *)object;  	u32 chid = chan->base.chid; -	u32 mask, engine; -	nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); -	nvc0_fifo_playlist_update(priv); -	mask = nv_rd32(priv, 0x0025a4); -	for (engine = 0; mask && engine < 16; engine++) { -		if (!(mask & (1 << engine))) -			continue; -		nv_mask(priv, 0x0025a8 + (engine * 4), 0x00000000, 0x00000000); -		mask &= ~(1 << engine); +	if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) { +		nv_mask(priv, 0x003004 + (chid * 8), 0x00000001, 0x00000000); +		nvc0_fifo_runlist_update(priv);  	} -	nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000); +	nvc0_fifo_intr_engine(priv); + +	nv_wr32(priv, 0x003000 + (chid * 8), 0x00000000);  	return nouveau_fifo_channel_fini(&chan->base, suspend);  } @@ -344,11 +364,177 @@ nvc0_fifo_cclass = {   * PFIFO engine   ******************************************************************************/ -static const struct nouveau_enum nvc0_fifo_fault_unit[] = { +static inline int +nvc0_fifo_engidx(struct nvc0_fifo_priv *priv, u32 engn) +{ +	switch (engn) { +	case NVDEV_ENGINE_GR   : engn = 0; break; +	case NVDEV_ENGINE_BSP  : engn = 1; break; +	case NVDEV_ENGINE_PPP  : engn = 2; break; +	case NVDEV_ENGINE_VP   : engn = 3; break; +	case NVDEV_ENGINE_COPY0: engn = 4; break; +	case NVDEV_ENGINE_COPY1: engn = 5; break; +	default: +		return -1; +	} + +	return engn; +} + +static inline struct nouveau_engine * +nvc0_fifo_engine(struct nvc0_fifo_priv *priv, u32 engn) +{ +	switch (engn) { +	case 0: engn = NVDEV_ENGINE_GR; break; +	case 1: engn = NVDEV_ENGINE_BSP; break; +	case 2: engn = NVDEV_ENGINE_PPP; break; +	case 3: engn = NVDEV_ENGINE_VP; break; +	case 4: engn = NVDEV_ENGINE_COPY0; break; +	case 5: engn = NVDEV_ENGINE_COPY1; break; +	default: +		return NULL; +	} + +	return nouveau_engine(priv, engn); +} + +static void +nvc0_fifo_recover_work(struct work_struct *work) +{ +	struct nvc0_fifo_priv *priv = container_of(work, typeof(*priv), fault); +	struct nouveau_object *engine; +	unsigned long flags; +	u32 engn, engm = 0; +	u64 mask, todo; + +	spin_lock_irqsave(&priv->base.lock, flags); +	mask = priv->mask; +	priv->mask = 0ULL; +	spin_unlock_irqrestore(&priv->base.lock, flags); + +	for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) +		engm |= 1 << nvc0_fifo_engidx(priv, engn); +	nv_mask(priv, 0x002630, engm, engm); + +	for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { +		if ((engine = (void *)nouveau_engine(priv, engn))) { +			nv_ofuncs(engine)->fini(engine, false); +			WARN_ON(nv_ofuncs(engine)->init(engine)); +		} +	} + +	nvc0_fifo_runlist_update(priv); +	nv_wr32(priv, 0x00262c, engm); +	nv_mask(priv, 0x002630, engm, 0x00000000); +} + +static void +nvc0_fifo_recover(struct nvc0_fifo_priv *priv, struct nouveau_engine *engine, +		  struct nvc0_fifo_chan *chan) +{ +	struct nouveau_object *engobj = nv_object(engine); +	u32 chid = chan->base.chid; +	unsigned long flags; + +	nv_error(priv, "%s engine fault on channel %d, recovering...\n", +		       nv_subdev(engine)->name, chid); + +	nv_mask(priv, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000); +	chan->state = KILLED; + +	spin_lock_irqsave(&priv->base.lock, flags); +	priv->mask |= 1ULL << nv_engidx(engobj); +	spin_unlock_irqrestore(&priv->base.lock, flags); +	schedule_work(&priv->fault); +} + +static int +nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) +{ +	struct nvc0_fifo_chan *chan = NULL; +	struct nouveau_handle *bind; +	unsigned long flags; +	int ret = -EINVAL; + +	spin_lock_irqsave(&priv->base.lock, flags); +	if (likely(chid >= priv->base.min && chid <= priv->base.max)) +		chan = (void *)priv->base.channel[chid]; +	if (unlikely(!chan)) +		goto out; + +	bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e); +	if (likely(bind)) { +		if (!mthd || !nv_call(bind->object, mthd, data)) +			ret = 0; +		nouveau_namedb_put(bind); +	} + +out: +	spin_unlock_irqrestore(&priv->base.lock, flags); +	return ret; +} + +static const struct nouveau_enum +nvc0_fifo_sched_reason[] = { +	{ 0x0a, "CTXSW_TIMEOUT" }, +	{} +}; + +static void +nvc0_fifo_intr_sched_ctxsw(struct nvc0_fifo_priv *priv) +{ +	struct nouveau_engine *engine; +	struct nvc0_fifo_chan *chan; +	u32 engn; + +	for (engn = 0; engn < 6; engn++) { +		u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04)); +		u32 busy = (stat & 0x80000000); +		u32 save = (stat & 0x00100000); /* maybe? */ +		u32 unk0 = (stat & 0x00040000); +		u32 unk1 = (stat & 0x00001000); +		u32 chid = (stat & 0x0000007f); +		(void)save; + +		if (busy && unk0 && unk1) { +			if (!(chan = (void *)priv->base.channel[chid])) +				continue; +			if (!(engine = nvc0_fifo_engine(priv, engn))) +				continue; +			nvc0_fifo_recover(priv, engine, chan); +		} +	} +} + +static void +nvc0_fifo_intr_sched(struct nvc0_fifo_priv *priv) +{ +	u32 intr = nv_rd32(priv, 0x00254c); +	u32 code = intr & 0x000000ff; +	const struct nouveau_enum *en; +	char enunk[6] = ""; + +	en = nouveau_enum_find(nvc0_fifo_sched_reason, code); +	if (!en) +		snprintf(enunk, sizeof(enunk), "UNK%02x", code); + +	nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk); + +	switch (code) { +	case 0x0a: +		nvc0_fifo_intr_sched_ctxsw(priv); +		break; +	default: +		break; +	} +} + +static const struct nouveau_enum +nvc0_fifo_fault_engine[] = {  	{ 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR }, -	{ 0x03, "PEEPHOLE" }, -	{ 0x04, "BAR1" }, -	{ 0x05, "BAR3" }, +	{ 0x03, "PEEPHOLE", NULL, NVDEV_ENGINE_IFB }, +	{ 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR }, +	{ 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM },  	{ 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO },  	{ 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP },  	{ 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP }, @@ -360,7 +546,8 @@ static const struct nouveau_enum nvc0_fifo_fault_unit[] = {  	{}  }; -static const struct nouveau_enum nvc0_fifo_fault_reason[] = { +static const struct nouveau_enum +nvc0_fifo_fault_reason[] = {  	{ 0x00, "PT_NOT_PRESENT" },  	{ 0x01, "PT_TOO_SHORT" },  	{ 0x02, "PAGE_NOT_PRESENT" }, @@ -373,7 +560,8 @@ static const struct nouveau_enum nvc0_fifo_fault_reason[] = {  	{}  }; -static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = { +static const struct nouveau_enum +nvc0_fifo_fault_hubclient[] = {  	{ 0x01, "PCOPY0" },  	{ 0x02, "PCOPY1" },  	{ 0x04, "DISPATCH" }, @@ -391,7 +579,8 @@ static const struct nouveau_enum nvc0_fifo_fault_hubclient[] = {  	{}  }; -static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = { +static const struct nouveau_enum +nvc0_fifo_fault_gpcclient[] = {  	{ 0x01, "TEX" },  	{ 0x0c, "ESETUP" },  	{ 0x0e, "CTXCTL" }, @@ -399,92 +588,92 @@ static const struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {  	{}  }; -static const struct nouveau_bitfield nvc0_fifo_subfifo_intr[] = { -/*	{ 0x00008000, "" }	seen with null ib push */ -	{ 0x00200000, "ILLEGAL_MTHD" }, -	{ 0x00800000, "EMPTY_SUBC" }, -	{} -}; -  static void -nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) +nvc0_fifo_intr_fault(struct nvc0_fifo_priv *priv, int unit)  {  	u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10));  	u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10));  	u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10));  	u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); +	u32 gpc    = (stat & 0x1f000000) >> 24;  	u32 client = (stat & 0x00001f00) >> 8; -	const struct nouveau_enum *en; -	struct nouveau_engine *engine; -	struct nouveau_object *engctx = NULL; - -	switch (unit) { -	case 3: /* PEEPHOLE */ -		nv_mask(priv, 0x001718, 0x00000000, 0x00000000); -		break; -	case 4: /* BAR1 */ -		nv_mask(priv, 0x001704, 0x00000000, 0x00000000); -		break; -	case 5: /* BAR3 */ -		nv_mask(priv, 0x001714, 0x00000000, 0x00000000); -		break; -	default: -		break; +	u32 write  = (stat & 0x00000080); +	u32 hub    = (stat & 0x00000040); +	u32 reason = (stat & 0x0000000f); +	struct nouveau_object *engctx = NULL, *object; +	struct nouveau_engine *engine = NULL; +	const struct nouveau_enum *er, *eu, *ec; +	char erunk[6] = ""; +	char euunk[6] = ""; +	char ecunk[6] = ""; +	char gpcid[3] = ""; + +	er = nouveau_enum_find(nvc0_fifo_fault_reason, reason); +	if (!er) +		snprintf(erunk, sizeof(erunk), "UNK%02X", reason); + +	eu = nouveau_enum_find(nvc0_fifo_fault_engine, unit); +	if (eu) { +		switch (eu->data2) { +		case NVDEV_SUBDEV_BAR: +			nv_mask(priv, 0x001704, 0x00000000, 0x00000000); +			break; +		case NVDEV_SUBDEV_INSTMEM: +			nv_mask(priv, 0x001714, 0x00000000, 0x00000000); +			break; +		case NVDEV_ENGINE_IFB: +			nv_mask(priv, 0x001718, 0x00000000, 0x00000000); +			break; +		default: +			engine = nouveau_engine(priv, eu->data2); +			if (engine) +				engctx = nouveau_engctx_get(engine, inst); +			break; +		} +	} else { +		snprintf(euunk, sizeof(euunk), "UNK%02x", unit);  	} -	nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? -		 "write" : "read", (u64)vahi << 32 | valo); -	nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); -	pr_cont("] from "); -	en = nouveau_enum_print(nvc0_fifo_fault_unit, unit); -	if (stat & 0x00000040) { -		pr_cont("/"); -		nouveau_enum_print(nvc0_fifo_fault_hubclient, client); +	if (hub) { +		ec = nouveau_enum_find(nvc0_fifo_fault_hubclient, client);  	} else { -		pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); -		nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); +		ec = nouveau_enum_find(nvc0_fifo_fault_gpcclient, client); +		snprintf(gpcid, sizeof(gpcid), "%d", gpc);  	} -	if (en && en->data2) { -		engine = nouveau_engine(priv, en->data2); -		if (engine) -			engctx = nouveau_engctx_get(engine, inst); - +	if (!ec) +		snprintf(ecunk, sizeof(ecunk), "UNK%02x", client); + +	nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on " +		       "channel 0x%010llx [%s]\n", write ? "write" : "read", +		 (u64)vahi << 32 | valo, er ? er->name : erunk, +		 eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/", +		 ec ? ec->name : ecunk, (u64)inst << 12, +		 nouveau_client_name(engctx)); + +	object = engctx; +	while (object) { +		switch (nv_mclass(object)) { +		case NVC0_CHANNEL_IND_CLASS: +			nvc0_fifo_recover(priv, engine, (void *)object); +			break; +		} +		object = object->parent;  	} -	pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, -			nouveau_client_name(engctx));  	nouveau_engctx_put(engctx);  } -static int -nvc0_fifo_swmthd(struct nvc0_fifo_priv *priv, u32 chid, u32 mthd, u32 data) -{ -	struct nvc0_fifo_chan *chan = NULL; -	struct nouveau_handle *bind; -	unsigned long flags; -	int ret = -EINVAL; - -	spin_lock_irqsave(&priv->base.lock, flags); -	if (likely(chid >= priv->base.min && chid <= priv->base.max)) -		chan = (void *)priv->base.channel[chid]; -	if (unlikely(!chan)) -		goto out; - -	bind = nouveau_namedb_get_class(nv_namedb(chan), 0x906e); -	if (likely(bind)) { -		if (!mthd || !nv_call(bind->object, mthd, data)) -			ret = 0; -		nouveau_namedb_put(bind); -	} - -out: -	spin_unlock_irqrestore(&priv->base.lock, flags); -	return ret; -} +static const struct nouveau_bitfield +nvc0_fifo_pbdma_intr[] = { +/*	{ 0x00008000, "" }	seen with null ib push */ +	{ 0x00200000, "ILLEGAL_MTHD" }, +	{ 0x00800000, "EMPTY_SUBC" }, +	{} +};  static void -nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit) +nvc0_fifo_intr_pbdma(struct nvc0_fifo_priv *priv, int unit)  {  	u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));  	u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); @@ -494,24 +683,17 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)  	u32 mthd = (addr & 0x00003ffc);  	u32 show = stat; -	if (stat & 0x00200000) { -		if (mthd == 0x0054) { -			if (!nvc0_fifo_swmthd(priv, chid, 0x0500, 0x00000000)) -				show &= ~0x00200000; -		} -	} -  	if (stat & 0x00800000) {  		if (!nvc0_fifo_swmthd(priv, chid, mthd, data))  			show &= ~0x00800000;  	}  	if (show) { -		nv_error(priv, "SUBFIFO%d:", unit); -		nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); +		nv_error(priv, "PBDMA%d:", unit); +		nouveau_bitfield_print(nvc0_fifo_pbdma_intr, show);  		pr_cont("\n");  		nv_error(priv, -			 "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", +			 "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",  			 unit, chid,  			 nouveau_client_name_for_fifo_chid(&priv->base, chid),  			 subc, mthd, data); @@ -522,6 +704,56 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit)  }  static void +nvc0_fifo_intr_runlist(struct nvc0_fifo_priv *priv) +{ +	u32 intr = nv_rd32(priv, 0x002a00); + +	if (intr & 0x10000000) { +		wake_up(&priv->runlist.wait); +		nv_wr32(priv, 0x002a00, 0x10000000); +		intr &= ~0x10000000; +	} + +	if (intr) { +		nv_error(priv, "RUNLIST 0x%08x\n", intr); +		nv_wr32(priv, 0x002a00, intr); +	} +} + +static void +nvc0_fifo_intr_engine_unit(struct nvc0_fifo_priv *priv, int engn) +{ +	u32 intr = nv_rd32(priv, 0x0025a8 + (engn * 0x04)); +	u32 inte = nv_rd32(priv, 0x002628); +	u32 unkn; + +	for (unkn = 0; unkn < 8; unkn++) { +		u32 ints = (intr >> (unkn * 0x04)) & inte; +		if (ints & 0x1) { +			nouveau_event_trigger(priv->base.uevent, 1, 0); +			ints &= ~1; +		} +		if (ints) { +			nv_error(priv, "ENGINE %d %d %01x", engn, unkn, ints); +			nv_mask(priv, 0x002628, ints, 0); +		} +	} + +	nv_wr32(priv, 0x0025a8 + (engn * 0x04), intr); +} + +static void +nvc0_fifo_intr_engine(struct nvc0_fifo_priv *priv) +{ +	u32 mask = nv_rd32(priv, 0x0025a4); +	while (mask) { +		u32 unit = __ffs(mask); +		nvc0_fifo_intr_engine_unit(priv, unit); +		mask &= ~(1 << unit); +	} +} + +static void  nvc0_fifo_intr(struct nouveau_subdev *subdev)  {  	struct nvc0_fifo_priv *priv = (void *)subdev; @@ -536,8 +768,7 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)  	}  	if (stat & 0x00000100) { -		u32 intr = nv_rd32(priv, 0x00254c); -		nv_warn(priv, "INTR 0x00000100: 0x%08x\n", intr); +		nvc0_fifo_intr_sched(priv);  		nv_wr32(priv, 0x002100, 0x00000100);  		stat &= ~0x00000100;  	} @@ -557,64 +788,53 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev)  	}  	if (stat & 0x10000000) { -		u32 units = nv_rd32(priv, 0x00259c); -		u32 u = units; - -		while (u) { -			int i = ffs(u) - 1; -			nvc0_fifo_isr_vm_fault(priv, i); -			u &= ~(1 << i); +		u32 mask = nv_rd32(priv, 0x00259c); +		while (mask) { +			u32 unit = __ffs(mask); +			nvc0_fifo_intr_fault(priv, unit); +			nv_wr32(priv, 0x00259c, (1 << unit)); +			mask &= ~(1 << unit);  		} - -		nv_wr32(priv, 0x00259c, units);  		stat &= ~0x10000000;  	}  	if (stat & 0x20000000) { -		u32 units = nv_rd32(priv, 0x0025a0); -		u32 u = units; - -		while (u) { -			int i = ffs(u) - 1; -			nvc0_fifo_isr_subfifo_intr(priv, i); -			u &= ~(1 << i); +		u32 mask = nv_rd32(priv, 0x0025a0); +		while (mask) { +			u32 unit = __ffs(mask); +			nvc0_fifo_intr_pbdma(priv, unit); +			nv_wr32(priv, 0x0025a0, (1 << unit)); +			mask &= ~(1 << unit);  		} - -		nv_wr32(priv, 0x0025a0, units);  		stat &= ~0x20000000;  	}  	if (stat & 0x40000000) { -		u32 intr0 = nv_rd32(priv, 0x0025a4); -		u32 intr1 = nv_mask(priv, 0x002a00, 0x00000000, 0x00000); -		nv_debug(priv, "INTR 0x40000000: 0x%08x 0x%08x\n", -			       intr0, intr1); +		nvc0_fifo_intr_runlist(priv);  		stat &= ~0x40000000;  	}  	if (stat & 0x80000000) { -		u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000); -		nouveau_event_trigger(priv->base.uevent, 0); -		nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr); +		nvc0_fifo_intr_engine(priv);  		stat &= ~0x80000000;  	}  	if (stat) { -		nv_fatal(priv, "unhandled status 0x%08x\n", stat); +		nv_error(priv, "INTR 0x%08x\n", stat); +		nv_mask(priv, 0x002140, stat, 0x00000000);  		nv_wr32(priv, 0x002100, stat); -		nv_wr32(priv, 0x002140, 0);  	}  }  static void -nvc0_fifo_uevent_enable(struct nouveau_event *event, int index) +nvc0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)  {  	struct nvc0_fifo_priv *priv = event->priv;  	nv_mask(priv, 0x002140, 0x80000000, 0x80000000);  }  static void -nvc0_fifo_uevent_disable(struct nouveau_event *event, int index) +nvc0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)  {  	struct nvc0_fifo_priv *priv = event->priv;  	nv_mask(priv, 0x002140, 0x80000000, 0x00000000); @@ -633,16 +853,20 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; +	INIT_WORK(&priv->fault, nvc0_fifo_recover_work); +  	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, -				&priv->playlist[0]); +				&priv->runlist.mem[0]);  	if (ret)  		return ret;  	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0x1000, 0, -				&priv->playlist[1]); +				&priv->runlist.mem[1]);  	if (ret)  		return ret; +	init_waitqueue_head(&priv->runlist.wait); +  	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 128 * 0x1000, 0x1000, 0,  				&priv->user.mem);  	if (ret) @@ -671,8 +895,8 @@ nvc0_fifo_dtor(struct nouveau_object *object)  	nouveau_gpuobj_unmap(&priv->user.bar);  	nouveau_gpuobj_ref(NULL, &priv->user.mem); -	nouveau_gpuobj_ref(NULL, &priv->playlist[1]); -	nouveau_gpuobj_ref(NULL, &priv->playlist[0]); +	nouveau_gpuobj_ref(NULL, &priv->runlist.mem[0]); +	nouveau_gpuobj_ref(NULL, &priv->runlist.mem[1]);  	nouveau_fifo_destroy(&priv->base);  } @@ -691,9 +915,9 @@ nvc0_fifo_init(struct nouveau_object *object)  	nv_wr32(priv, 0x002204, 0xffffffff);  	priv->spoon_nr = hweight32(nv_rd32(priv, 0x002204)); -	nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); +	nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr); -	/* assign engines to subfifos */ +	/* assign engines to PBDMAs */  	if (priv->spoon_nr >= 3) {  		nv_wr32(priv, 0x002208, ~(1 << 0)); /* PGRAPH */  		nv_wr32(priv, 0x00220c, ~(1 << 1)); /* PVP */ @@ -703,7 +927,7 @@ nvc0_fifo_init(struct nouveau_object *object)  		nv_wr32(priv, 0x00221c, ~(1 << 1)); /* PCE1 */  	} -	/* PSUBFIFO[n] */ +	/* PBDMA[n] */  	for (i = 0; i < priv->spoon_nr; i++) {  		nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);  		nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ @@ -713,15 +937,14 @@ nvc0_fifo_init(struct nouveau_object *object)  	nv_mask(priv, 0x002200, 0x00000001, 0x00000001);  	nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); -	nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */  	nv_wr32(priv, 0x002100, 0xffffffff); -	nv_wr32(priv, 0x002140, 0x3fffffff); -	nv_wr32(priv, 0x002628, 0x00000001); /* makes mthd 0x20 work */ +	nv_wr32(priv, 0x002140, 0x7fffffff); +	nv_wr32(priv, 0x002628, 0x00000001); /* ENGINE_INTR_EN */  	return 0;  } -struct nouveau_oclass -nvc0_fifo_oclass = { +struct nouveau_oclass * +nvc0_fifo_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(FIFO, 0xc0),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvc0_fifo_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 8e8121abe31..298063edb92 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -33,10 +33,12 @@  #include <subdev/timer.h>  #include <subdev/bar.h> +#include <subdev/fb.h>  #include <subdev/vm.h>  #include <engine/dmaobj.h> -#include <engine/fifo.h> + +#include "nve0.h"  #define _(a,b) { (a), ((1ULL << (a)) | (b)) }  static const struct { @@ -56,12 +58,17 @@ static const struct {  #define FIFO_ENGINE_NR ARRAY_SIZE(fifo_engine)  struct nve0_fifo_engn { -	struct nouveau_gpuobj *playlist[2]; -	int cur_playlist; +	struct nouveau_gpuobj *runlist[2]; +	int cur_runlist; +	wait_queue_head_t wait;  };  struct nve0_fifo_priv {  	struct nouveau_fifo base; + +	struct work_struct fault; +	u64 mask; +  	struct nve0_fifo_engn engine[FIFO_ENGINE_NR];  	struct {  		struct nouveau_gpuobj *mem; @@ -79,6 +86,11 @@ struct nve0_fifo_base {  struct nve0_fifo_chan {  	struct nouveau_fifo_chan base;  	u32 engine; +	enum { +		STOPPED, +		RUNNING, +		KILLED +	} state;  };  /******************************************************************************* @@ -86,32 +98,34 @@ struct nve0_fifo_chan {   ******************************************************************************/  static void -nve0_fifo_playlist_update(struct nve0_fifo_priv *priv, u32 engine) +nve0_fifo_runlist_update(struct nve0_fifo_priv *priv, u32 engine)  {  	struct nouveau_bar *bar = nouveau_bar(priv);  	struct nve0_fifo_engn *engn = &priv->engine[engine];  	struct nouveau_gpuobj *cur; -	u32 match = (engine << 16) | 0x00000001;  	int i, p;  	mutex_lock(&nv_subdev(priv)->mutex); -	cur = engn->playlist[engn->cur_playlist]; -	engn->cur_playlist = !engn->cur_playlist; +	cur = engn->runlist[engn->cur_runlist]; +	engn->cur_runlist = !engn->cur_runlist;  	for (i = 0, p = 0; i < priv->base.max; i++) { -		u32 ctrl = nv_rd32(priv, 0x800004 + (i * 8)) & 0x001f0001; -		if (ctrl != match) -			continue; -		nv_wo32(cur, p + 0, i); -		nv_wo32(cur, p + 4, 0x00000000); -		p += 8; +		struct nve0_fifo_chan *chan = (void *)priv->base.channel[i]; +		if (chan && chan->state == RUNNING && chan->engine == engine) { +			nv_wo32(cur, p + 0, i); +			nv_wo32(cur, p + 4, 0x00000000); +			p += 8; +		}  	}  	bar->flush(bar);  	nv_wr32(priv, 0x002270, cur->addr >> 12);  	nv_wr32(priv, 0x002274, (engine << 20) | (p >> 3)); -	if (!nv_wait(priv, 0x002284 + (engine * 4), 0x00100000, 0x00000000)) -		nv_error(priv, "playlist %d update timeout\n", engine); + +	if (wait_event_timeout(engn->wait, !(nv_rd32(priv, 0x002284 + +			       (engine * 0x08)) & 0x00100000), +				msecs_to_jiffies(2000)) == 0) +		nv_error(priv, "runlist %d update timeout\n", engine);  	mutex_unlock(&nv_subdev(priv)->mutex);  } @@ -127,9 +141,11 @@ nve0_fifo_context_attach(struct nouveau_object *parent,  	switch (nv_engidx(object->engine)) {  	case NVDEV_ENGINE_SW   : +		return 0;  	case NVDEV_ENGINE_COPY0:  	case NVDEV_ENGINE_COPY1:  	case NVDEV_ENGINE_COPY2: +		nv_engctx(ectx)->addr = nv_gpuobj(base)->addr >> 12;  		return 0;  	case NVDEV_ENGINE_GR   : addr = 0x0210; break;  	case NVDEV_ENGINE_BSP  : addr = 0x0270; break; @@ -277,9 +293,13 @@ nve0_fifo_chan_init(struct nouveau_object *object)  	nv_mask(priv, 0x800004 + (chid * 8), 0x000f0000, chan->engine << 16);  	nv_wr32(priv, 0x800000 + (chid * 8), 0x80000000 | base->addr >> 12); -	nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); -	nve0_fifo_playlist_update(priv, chan->engine); -	nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); + +	if (chan->state == STOPPED && (chan->state = RUNNING) == RUNNING) { +		nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); +		nve0_fifo_runlist_update(priv, chan->engine); +		nv_mask(priv, 0x800004 + (chid * 8), 0x00000400, 0x00000400); +	} +  	return 0;  } @@ -290,10 +310,12 @@ nve0_fifo_chan_fini(struct nouveau_object *object, bool suspend)  	struct nve0_fifo_chan *chan = (void *)object;  	u32 chid = chan->base.chid; -	nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800); -	nve0_fifo_playlist_update(priv, chan->engine); -	nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000); +	if (chan->state == RUNNING && (chan->state = STOPPED) == STOPPED) { +		nv_mask(priv, 0x800004 + (chid * 8), 0x00000800, 0x00000800); +		nve0_fifo_runlist_update(priv, chan->engine); +	} +	nv_wr32(priv, 0x800000 + (chid * 8), 0x00000000);  	return nouveau_fifo_channel_fini(&chan->base, suspend);  } @@ -375,73 +397,81 @@ nve0_fifo_cclass = {   * PFIFO engine   ******************************************************************************/ -static const struct nouveau_enum nve0_fifo_fault_unit[] = { -	{} -}; - -static const struct nouveau_enum nve0_fifo_fault_reason[] = { -	{ 0x00, "PT_NOT_PRESENT" }, -	{ 0x01, "PT_TOO_SHORT" }, -	{ 0x02, "PAGE_NOT_PRESENT" }, -	{ 0x03, "VM_LIMIT_EXCEEDED" }, -	{ 0x04, "NO_CHANNEL" }, -	{ 0x05, "PAGE_SYSTEM_ONLY" }, -	{ 0x06, "PAGE_READ_ONLY" }, -	{ 0x0a, "COMPRESSED_SYSRAM" }, -	{ 0x0c, "INVALID_STORAGE_TYPE" }, -	{} -}; - -static const struct nouveau_enum nve0_fifo_fault_hubclient[] = { -	{} -}; +static inline int +nve0_fifo_engidx(struct nve0_fifo_priv *priv, u32 engn) +{ +	switch (engn) { +	case NVDEV_ENGINE_GR   : +	case NVDEV_ENGINE_COPY2: engn = 0; break; +	case NVDEV_ENGINE_BSP  : engn = 1; break; +	case NVDEV_ENGINE_PPP  : engn = 2; break; +	case NVDEV_ENGINE_VP   : engn = 3; break; +	case NVDEV_ENGINE_COPY0: engn = 4; break; +	case NVDEV_ENGINE_COPY1: engn = 5; break; +	case NVDEV_ENGINE_VENC : engn = 6; break; +	default: +		return -1; +	} -static const struct nouveau_enum nve0_fifo_fault_gpcclient[] = { -	{} -}; +	return engn; +} -static const struct nouveau_bitfield nve0_fifo_subfifo_intr[] = { -	{ 0x00200000, "ILLEGAL_MTHD" }, -	{ 0x00800000, "EMPTY_SUBC" }, -	{} -}; +static inline struct nouveau_engine * +nve0_fifo_engine(struct nve0_fifo_priv *priv, u32 engn) +{ +	if (engn >= ARRAY_SIZE(fifo_engine)) +		return NULL; +	return nouveau_engine(priv, fifo_engine[engn].subdev); +}  static void -nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit) +nve0_fifo_recover_work(struct work_struct *work)  { -	u32 inst = nv_rd32(priv, 0x2800 + (unit * 0x10)); -	u32 valo = nv_rd32(priv, 0x2804 + (unit * 0x10)); -	u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); -	u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); -	u32 client = (stat & 0x00001f00) >> 8; -	const struct nouveau_enum *en; -	struct nouveau_engine *engine; -	struct nouveau_object *engctx = NULL; - -	nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ? -		       "write" : "read", (u64)vahi << 32 | valo); -	nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); -	pr_cont("] from "); -	en = nouveau_enum_print(nve0_fifo_fault_unit, unit); -	if (stat & 0x00000040) { -		pr_cont("/"); -		nouveau_enum_print(nve0_fifo_fault_hubclient, client); -	} else { -		pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); -		nouveau_enum_print(nve0_fifo_fault_gpcclient, client); -	} +	struct nve0_fifo_priv *priv = container_of(work, typeof(*priv), fault); +	struct nouveau_object *engine; +	unsigned long flags; +	u32 engn, engm = 0; +	u64 mask, todo; -	if (en && en->data2) { -		engine = nouveau_engine(priv, en->data2); -		if (engine) -			engctx = nouveau_engctx_get(engine, inst); +	spin_lock_irqsave(&priv->base.lock, flags); +	mask = priv->mask; +	priv->mask = 0ULL; +	spin_unlock_irqrestore(&priv->base.lock, flags); + +	for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) +		engm |= 1 << nve0_fifo_engidx(priv, engn); +	nv_mask(priv, 0x002630, engm, engm); +	for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) { +		if ((engine = (void *)nouveau_engine(priv, engn))) { +			nv_ofuncs(engine)->fini(engine, false); +			WARN_ON(nv_ofuncs(engine)->init(engine)); +		} +		nve0_fifo_runlist_update(priv, nve0_fifo_engidx(priv, engn));  	} -	pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, -			nouveau_client_name(engctx)); +	nv_wr32(priv, 0x00262c, engm); +	nv_mask(priv, 0x002630, engm, 0x00000000); +} -	nouveau_engctx_put(engctx); +static void +nve0_fifo_recover(struct nve0_fifo_priv *priv, struct nouveau_engine *engine, +		  struct nve0_fifo_chan *chan) +{ +	struct nouveau_object *engobj = nv_object(engine); +	u32 chid = chan->base.chid; +	unsigned long flags; + +	nv_error(priv, "%s engine fault on channel %d, recovering...\n", +		       nv_subdev(engine)->name, chid); + +	nv_mask(priv, 0x800004 + (chid * 0x08), 0x00000800, 0x00000800); +	chan->state = KILLED; + +	spin_lock_irqsave(&priv->base.lock, flags); +	priv->mask |= 1ULL << nv_engidx(engobj); +	spin_unlock_irqrestore(&priv->base.lock, flags); +	schedule_work(&priv->fault);  }  static int @@ -470,8 +500,321 @@ out:  	return ret;  } +static const struct nouveau_enum +nve0_fifo_bind_reason[] = { +	{ 0x01, "BIND_NOT_UNBOUND" }, +	{ 0x02, "SNOOP_WITHOUT_BAR1" }, +	{ 0x03, "UNBIND_WHILE_RUNNING" }, +	{ 0x05, "INVALID_RUNLIST" }, +	{ 0x06, "INVALID_CTX_TGT" }, +	{ 0x0b, "UNBIND_WHILE_PARKED" }, +	{} +}; +  static void -nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit) +nve0_fifo_intr_bind(struct nve0_fifo_priv *priv) +{ +	u32 intr = nv_rd32(priv, 0x00252c); +	u32 code = intr & 0x000000ff; +	const struct nouveau_enum *en; +	char enunk[6] = ""; + +	en = nouveau_enum_find(nve0_fifo_bind_reason, code); +	if (!en) +		snprintf(enunk, sizeof(enunk), "UNK%02x", code); + +	nv_error(priv, "BIND_ERROR [ %s ]\n", en ? en->name : enunk); +} + +static const struct nouveau_enum +nve0_fifo_sched_reason[] = { +	{ 0x0a, "CTXSW_TIMEOUT" }, +	{} +}; + +static void +nve0_fifo_intr_sched_ctxsw(struct nve0_fifo_priv *priv) +{ +	struct nouveau_engine *engine; +	struct nve0_fifo_chan *chan; +	u32 engn; + +	for (engn = 0; engn < ARRAY_SIZE(fifo_engine); engn++) { +		u32 stat = nv_rd32(priv, 0x002640 + (engn * 0x04)); +		u32 busy = (stat & 0x80000000); +		u32 next = (stat & 0x07ff0000) >> 16; +		u32 chsw = (stat & 0x00008000); +		u32 save = (stat & 0x00004000); +		u32 load = (stat & 0x00002000); +		u32 prev = (stat & 0x000007ff); +		u32 chid = load ? next : prev; +		(void)save; + +		if (busy && chsw) { +			if (!(chan = (void *)priv->base.channel[chid])) +				continue; +			if (!(engine = nve0_fifo_engine(priv, engn))) +				continue; +			nve0_fifo_recover(priv, engine, chan); +		} +	} +} + +static void +nve0_fifo_intr_sched(struct nve0_fifo_priv *priv) +{ +	u32 intr = nv_rd32(priv, 0x00254c); +	u32 code = intr & 0x000000ff; +	const struct nouveau_enum *en; +	char enunk[6] = ""; + +	en = nouveau_enum_find(nve0_fifo_sched_reason, code); +	if (!en) +		snprintf(enunk, sizeof(enunk), "UNK%02x", code); + +	nv_error(priv, "SCHED_ERROR [ %s ]\n", en ? en->name : enunk); + +	switch (code) { +	case 0x0a: +		nve0_fifo_intr_sched_ctxsw(priv); +		break; +	default: +		break; +	} +} + +static void +nve0_fifo_intr_chsw(struct nve0_fifo_priv *priv) +{ +	u32 stat = nv_rd32(priv, 0x00256c); +	nv_error(priv, "CHSW_ERROR 0x%08x\n", stat); +	nv_wr32(priv, 0x00256c, stat); +} + +static void +nve0_fifo_intr_dropped_fault(struct nve0_fifo_priv *priv) +{ +	u32 stat = nv_rd32(priv, 0x00259c); +	nv_error(priv, "DROPPED_MMU_FAULT 0x%08x\n", stat); +} + +static const struct nouveau_enum +nve0_fifo_fault_engine[] = { +	{ 0x00, "GR", NULL, NVDEV_ENGINE_GR }, +	{ 0x03, "IFB", NULL, NVDEV_ENGINE_IFB }, +	{ 0x04, "BAR1", NULL, NVDEV_SUBDEV_BAR }, +	{ 0x05, "BAR3", NULL, NVDEV_SUBDEV_INSTMEM }, +	{ 0x07, "PBDMA0", NULL, NVDEV_ENGINE_FIFO }, +	{ 0x08, "PBDMA1", NULL, NVDEV_ENGINE_FIFO }, +	{ 0x09, "PBDMA2", NULL, NVDEV_ENGINE_FIFO }, +	{ 0x10, "MSVLD", NULL, NVDEV_ENGINE_BSP }, +	{ 0x11, "MSPPP", NULL, NVDEV_ENGINE_PPP }, +	{ 0x13, "PERF" }, +	{ 0x14, "MSPDEC", NULL, NVDEV_ENGINE_VP }, +	{ 0x15, "CE0", NULL, NVDEV_ENGINE_COPY0 }, +	{ 0x16, "CE1", NULL, NVDEV_ENGINE_COPY1 }, +	{ 0x17, "PMU" }, +	{ 0x19, "MSENC", NULL, NVDEV_ENGINE_VENC }, +	{ 0x1b, "CE2", NULL, NVDEV_ENGINE_COPY2 }, +	{} +}; + +static const struct nouveau_enum +nve0_fifo_fault_reason[] = { +	{ 0x00, "PDE" }, +	{ 0x01, "PDE_SIZE" }, +	{ 0x02, "PTE" }, +	{ 0x03, "VA_LIMIT_VIOLATION" }, +	{ 0x04, "UNBOUND_INST_BLOCK" }, +	{ 0x05, "PRIV_VIOLATION" }, +	{ 0x06, "RO_VIOLATION" }, +	{ 0x07, "WO_VIOLATION" }, +	{ 0x08, "PITCH_MASK_VIOLATION" }, +	{ 0x09, "WORK_CREATION" }, +	{ 0x0a, "UNSUPPORTED_APERTURE" }, +	{ 0x0b, "COMPRESSION_FAILURE" }, +	{ 0x0c, "UNSUPPORTED_KIND" }, +	{ 0x0d, "REGION_VIOLATION" }, +	{ 0x0e, "BOTH_PTES_VALID" }, +	{ 0x0f, "INFO_TYPE_POISONED" }, +	{} +}; + +static const struct nouveau_enum +nve0_fifo_fault_hubclient[] = { +	{ 0x00, "VIP" }, +	{ 0x01, "CE0" }, +	{ 0x02, "CE1" }, +	{ 0x03, "DNISO" }, +	{ 0x04, "FE" }, +	{ 0x05, "FECS" }, +	{ 0x06, "HOST" }, +	{ 0x07, "HOST_CPU" }, +	{ 0x08, "HOST_CPU_NB" }, +	{ 0x09, "ISO" }, +	{ 0x0a, "MMU" }, +	{ 0x0b, "MSPDEC" }, +	{ 0x0c, "MSPPP" }, +	{ 0x0d, "MSVLD" }, +	{ 0x0e, "NISO" }, +	{ 0x0f, "P2P" }, +	{ 0x10, "PD" }, +	{ 0x11, "PERF" }, +	{ 0x12, "PMU" }, +	{ 0x13, "RASTERTWOD" }, +	{ 0x14, "SCC" }, +	{ 0x15, "SCC_NB" }, +	{ 0x16, "SEC" }, +	{ 0x17, "SSYNC" }, +	{ 0x18, "GR_COPY" }, +	{ 0x19, "CE2" }, +	{ 0x1a, "XV" }, +	{ 0x1b, "MMU_NB" }, +	{ 0x1c, "MSENC" }, +	{ 0x1d, "DFALCON" }, +	{ 0x1e, "SKED" }, +	{ 0x1f, "AFALCON" }, +	{} +}; + +static const struct nouveau_enum +nve0_fifo_fault_gpcclient[] = { +	{ 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" }, +	{ 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" }, +	{ 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" }, +	{ 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" }, +	{ 0x0c, "RAST" }, +	{ 0x0d, "GCC" }, +	{ 0x0e, "GPCCS" }, +	{ 0x0f, "PROP_0" }, +	{ 0x10, "PROP_1" }, +	{ 0x11, "PROP_2" }, +	{ 0x12, "PROP_3" }, +	{ 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" }, +	{ 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" }, +	{ 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" }, +	{ 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" }, +	{ 0x1f, "GPM" }, +	{ 0x20, "LTP_UTLB_0" }, +	{ 0x21, "LTP_UTLB_1" }, +	{ 0x22, "LTP_UTLB_2" }, +	{ 0x23, "LTP_UTLB_3" }, +	{ 0x24, "GPC_RGG_UTLB" }, +	{} +}; + +static void +nve0_fifo_intr_fault(struct nve0_fifo_priv *priv, int unit) +{ +	u32 inst = nv_rd32(priv, 0x002800 + (unit * 0x10)); +	u32 valo = nv_rd32(priv, 0x002804 + (unit * 0x10)); +	u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); +	u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); +	u32 gpc    = (stat & 0x1f000000) >> 24; +	u32 client = (stat & 0x00001f00) >> 8; +	u32 write  = (stat & 0x00000080); +	u32 hub    = (stat & 0x00000040); +	u32 reason = (stat & 0x0000000f); +	struct nouveau_object *engctx = NULL, *object; +	struct nouveau_engine *engine = NULL; +	const struct nouveau_enum *er, *eu, *ec; +	char erunk[6] = ""; +	char euunk[6] = ""; +	char ecunk[6] = ""; +	char gpcid[3] = ""; + +	er = nouveau_enum_find(nve0_fifo_fault_reason, reason); +	if (!er) +		snprintf(erunk, sizeof(erunk), "UNK%02X", reason); + +	eu = nouveau_enum_find(nve0_fifo_fault_engine, unit); +	if (eu) { +		switch (eu->data2) { +		case NVDEV_SUBDEV_BAR: +			nv_mask(priv, 0x001704, 0x00000000, 0x00000000); +			break; +		case NVDEV_SUBDEV_INSTMEM: +			nv_mask(priv, 0x001714, 0x00000000, 0x00000000); +			break; +		case NVDEV_ENGINE_IFB: +			nv_mask(priv, 0x001718, 0x00000000, 0x00000000); +			break; +		default: +			engine = nouveau_engine(priv, eu->data2); +			if (engine) +				engctx = nouveau_engctx_get(engine, inst); +			break; +		} +	} else { +		snprintf(euunk, sizeof(euunk), "UNK%02x", unit); +	} + +	if (hub) { +		ec = nouveau_enum_find(nve0_fifo_fault_hubclient, client); +	} else { +		ec = nouveau_enum_find(nve0_fifo_fault_gpcclient, client); +		snprintf(gpcid, sizeof(gpcid), "%d", gpc); +	} + +	if (!ec) +		snprintf(ecunk, sizeof(ecunk), "UNK%02x", client); + +	nv_error(priv, "%s fault at 0x%010llx [%s] from %s/%s%s%s%s on " +		       "channel 0x%010llx [%s]\n", write ? "write" : "read", +		 (u64)vahi << 32 | valo, er ? er->name : erunk, +		 eu ? eu->name : euunk, hub ? "" : "GPC", gpcid, hub ? "" : "/", +		 ec ? ec->name : ecunk, (u64)inst << 12, +		 nouveau_client_name(engctx)); + +	object = engctx; +	while (object) { +		switch (nv_mclass(object)) { +		case NVE0_CHANNEL_IND_CLASS: +			nve0_fifo_recover(priv, engine, (void *)object); +			break; +		} +		object = object->parent; +	} + +	nouveau_engctx_put(engctx); +} + +static const struct nouveau_bitfield nve0_fifo_pbdma_intr[] = { +	{ 0x00000001, "MEMREQ" }, +	{ 0x00000002, "MEMACK_TIMEOUT" }, +	{ 0x00000004, "MEMACK_EXTRA" }, +	{ 0x00000008, "MEMDAT_TIMEOUT" }, +	{ 0x00000010, "MEMDAT_EXTRA" }, +	{ 0x00000020, "MEMFLUSH" }, +	{ 0x00000040, "MEMOP" }, +	{ 0x00000080, "LBCONNECT" }, +	{ 0x00000100, "LBREQ" }, +	{ 0x00000200, "LBACK_TIMEOUT" }, +	{ 0x00000400, "LBACK_EXTRA" }, +	{ 0x00000800, "LBDAT_TIMEOUT" }, +	{ 0x00001000, "LBDAT_EXTRA" }, +	{ 0x00002000, "GPFIFO" }, +	{ 0x00004000, "GPPTR" }, +	{ 0x00008000, "GPENTRY" }, +	{ 0x00010000, "GPCRC" }, +	{ 0x00020000, "PBPTR" }, +	{ 0x00040000, "PBENTRY" }, +	{ 0x00080000, "PBCRC" }, +	{ 0x00100000, "XBARCONNECT" }, +	{ 0x00200000, "METHOD" }, +	{ 0x00400000, "METHODCRC" }, +	{ 0x00800000, "DEVICE" }, +	{ 0x02000000, "SEMAPHORE" }, +	{ 0x04000000, "ACQUIRE" }, +	{ 0x08000000, "PRI" }, +	{ 0x20000000, "NO_CTXSW_SEG" }, +	{ 0x40000000, "PBSEG" }, +	{ 0x80000000, "SIGNATURE" }, +	{} +}; + +static void +nve0_fifo_intr_pbdma(struct nve0_fifo_priv *priv, int unit)  {  	u32 stat = nv_rd32(priv, 0x040108 + (unit * 0x2000));  	u32 addr = nv_rd32(priv, 0x0400c0 + (unit * 0x2000)); @@ -481,24 +824,17 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)  	u32 mthd = (addr & 0x00003ffc);  	u32 show = stat; -	if (stat & 0x00200000) { -		if (mthd == 0x0054) { -			if (!nve0_fifo_swmthd(priv, chid, 0x0500, 0x00000000)) -				show &= ~0x00200000; -		} -	} -  	if (stat & 0x00800000) {  		if (!nve0_fifo_swmthd(priv, chid, mthd, data))  			show &= ~0x00800000;  	}  	if (show) { -		nv_error(priv, "SUBFIFO%d:", unit); -		nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); +		nv_error(priv, "PBDMA%d:", unit); +		nouveau_bitfield_print(nve0_fifo_pbdma_intr, show);  		pr_cont("\n");  		nv_error(priv, -			 "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", +			 "PBDMA%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n",  			 unit, chid,  			 nouveau_client_name_for_fifo_chid(&priv->base, chid),  			 subc, mthd, data); @@ -509,126 +845,171 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit)  }  static void +nve0_fifo_intr_runlist(struct nve0_fifo_priv *priv) +{ +	u32 mask = nv_rd32(priv, 0x002a00); +	while (mask) { +		u32 engn = __ffs(mask); +		wake_up(&priv->engine[engn].wait); +		nv_wr32(priv, 0x002a00, 1 << engn); +		mask &= ~(1 << engn); +	} +} + +static void +nve0_fifo_intr_engine(struct nve0_fifo_priv *priv) +{ +	nouveau_event_trigger(priv->base.uevent, 1, 0); +} + +static void  nve0_fifo_intr(struct nouveau_subdev *subdev)  {  	struct nve0_fifo_priv *priv = (void *)subdev;  	u32 mask = nv_rd32(priv, 0x002140);  	u32 stat = nv_rd32(priv, 0x002100) & mask; +	if (stat & 0x00000001) { +		nve0_fifo_intr_bind(priv); +		nv_wr32(priv, 0x002100, 0x00000001); +		stat &= ~0x00000001; +	} + +	if (stat & 0x00000010) { +		nv_error(priv, "PIO_ERROR\n"); +		nv_wr32(priv, 0x002100, 0x00000010); +		stat &= ~0x00000010; +	} +  	if (stat & 0x00000100) { -		nv_warn(priv, "unknown status 0x00000100\n"); +		nve0_fifo_intr_sched(priv);  		nv_wr32(priv, 0x002100, 0x00000100);  		stat &= ~0x00000100;  	} -	if (stat & 0x10000000) { -		u32 units = nv_rd32(priv, 0x00259c); -		u32 u = units; +	if (stat & 0x00010000) { +		nve0_fifo_intr_chsw(priv); +		nv_wr32(priv, 0x002100, 0x00010000); +		stat &= ~0x00010000; +	} -		while (u) { -			int i = ffs(u) - 1; -			nve0_fifo_isr_vm_fault(priv, i); -			u &= ~(1 << i); -		} +	if (stat & 0x00800000) { +		nv_error(priv, "FB_FLUSH_TIMEOUT\n"); +		nv_wr32(priv, 0x002100, 0x00800000); +		stat &= ~0x00800000; +	} -		nv_wr32(priv, 0x00259c, units); -		stat &= ~0x10000000; +	if (stat & 0x01000000) { +		nv_error(priv, "LB_ERROR\n"); +		nv_wr32(priv, 0x002100, 0x01000000); +		stat &= ~0x01000000;  	} -	if (stat & 0x20000000) { -		u32 units = nv_rd32(priv, 0x0025a0); -		u32 u = units; +	if (stat & 0x08000000) { +		nve0_fifo_intr_dropped_fault(priv); +		nv_wr32(priv, 0x002100, 0x08000000); +		stat &= ~0x08000000; +	} -		while (u) { -			int i = ffs(u) - 1; -			nve0_fifo_isr_subfifo_intr(priv, i); -			u &= ~(1 << i); +	if (stat & 0x10000000) { +		u32 mask = nv_rd32(priv, 0x00259c); +		while (mask) { +			u32 unit = __ffs(mask); +			nve0_fifo_intr_fault(priv, unit); +			nv_wr32(priv, 0x00259c, (1 << unit)); +			mask &= ~(1 << unit);  		} +		stat &= ~0x10000000; +	} -		nv_wr32(priv, 0x0025a0, units); +	if (stat & 0x20000000) { +		u32 mask = nv_rd32(priv, 0x0025a0); +		while (mask) { +			u32 unit = __ffs(mask); +			nve0_fifo_intr_pbdma(priv, unit); +			nv_wr32(priv, 0x0025a0, (1 << unit)); +			mask &= ~(1 << unit); +		}  		stat &= ~0x20000000;  	}  	if (stat & 0x40000000) { -		nv_warn(priv, "unknown status 0x40000000\n"); -		nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); +		nve0_fifo_intr_runlist(priv);  		stat &= ~0x40000000;  	}  	if (stat & 0x80000000) { -		nouveau_event_trigger(priv->base.uevent, 0); +		nve0_fifo_intr_engine(priv);  		nv_wr32(priv, 0x002100, 0x80000000);  		stat &= ~0x80000000;  	}  	if (stat) { -		nv_fatal(priv, "unhandled status 0x%08x\n", stat); +		nv_error(priv, "INTR 0x%08x\n", stat); +		nv_mask(priv, 0x002140, stat, 0x00000000);  		nv_wr32(priv, 0x002100, stat); -		nv_wr32(priv, 0x002140, 0);  	}  }  static void -nve0_fifo_uevent_enable(struct nouveau_event *event, int index) +nve0_fifo_uevent_enable(struct nouveau_event *event, int type, int index)  {  	struct nve0_fifo_priv *priv = event->priv;  	nv_mask(priv, 0x002140, 0x80000000, 0x80000000);  }  static void -nve0_fifo_uevent_disable(struct nouveau_event *event, int index) +nve0_fifo_uevent_disable(struct nouveau_event *event, int type, int index)  {  	struct nve0_fifo_priv *priv = event->priv;  	nv_mask(priv, 0x002140, 0x80000000, 0x00000000);  } -static int -nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	       struct nouveau_oclass *oclass, void *data, u32 size, -	       struct nouveau_object **pobject) +int +nve0_fifo_fini(struct nouveau_object *object, bool suspend)  { -	struct nve0_fifo_priv *priv; -	int ret, i; +	struct nve0_fifo_priv *priv = (void *)object; +	int ret; -	ret = nouveau_fifo_create(parent, engine, oclass, 0, 4095, &priv); -	*pobject = nv_object(priv); +	ret = nouveau_fifo_fini(&priv->base, suspend);  	if (ret)  		return ret; -	for (i = 0; i < FIFO_ENGINE_NR; i++) { -		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, -					 0, &priv->engine[i].playlist[0]); -		if (ret) -			return ret; +	/* allow mmu fault interrupts, even when we're not using fifo */ +	nv_mask(priv, 0x002140, 0x10000000, 0x10000000); +	return 0; +} -		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, -					 0, &priv->engine[i].playlist[1]); -		if (ret) -			return ret; -	} +int +nve0_fifo_init(struct nouveau_object *object) +{ +	struct nve0_fifo_priv *priv = (void *)object; +	int ret, i; -	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 4096 * 0x200, 0x1000, -				 NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); +	ret = nouveau_fifo_init(&priv->base);  	if (ret)  		return ret; -	ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, -				&priv->user.bar); -	if (ret) -		return ret; +	/* enable all available PBDMA units */ +	nv_wr32(priv, 0x000204, 0xffffffff); +	priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204)); +	nv_debug(priv, "%d PBDMA unit(s)\n", priv->spoon_nr); -	priv->base.uevent->enable = nve0_fifo_uevent_enable; -	priv->base.uevent->disable = nve0_fifo_uevent_disable; -	priv->base.uevent->priv = priv; +	/* PBDMA[n] */ +	for (i = 0; i < priv->spoon_nr; i++) { +		nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); +		nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ +		nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ +	} -	nv_subdev(priv)->unit = 0x00000100; -	nv_subdev(priv)->intr = nve0_fifo_intr; -	nv_engine(priv)->cclass = &nve0_fifo_cclass; -	nv_engine(priv)->sclass = nve0_fifo_sclass; +	nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); + +	nv_wr32(priv, 0x002100, 0xffffffff); +	nv_wr32(priv, 0x002140, 0x7fffffff);  	return 0;  } -static void +void  nve0_fifo_dtor(struct nouveau_object *object)  {  	struct nve0_fifo_priv *priv = (void *)object; @@ -638,50 +1019,73 @@ nve0_fifo_dtor(struct nouveau_object *object)  	nouveau_gpuobj_ref(NULL, &priv->user.mem);  	for (i = 0; i < FIFO_ENGINE_NR; i++) { -		nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[1]); -		nouveau_gpuobj_ref(NULL, &priv->engine[i].playlist[0]); +		nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[1]); +		nouveau_gpuobj_ref(NULL, &priv->engine[i].runlist[0]);  	}  	nouveau_fifo_destroy(&priv->base);  } -static int -nve0_fifo_init(struct nouveau_object *object) +int +nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject)  { -	struct nve0_fifo_priv *priv = (void *)object; +	struct nve0_fifo_impl *impl = (void *)oclass; +	struct nve0_fifo_priv *priv;  	int ret, i; -	ret = nouveau_fifo_init(&priv->base); +	ret = nouveau_fifo_create(parent, engine, oclass, 0, +				  impl->channels - 1, &priv); +	*pobject = nv_object(priv);  	if (ret)  		return ret; -	/* enable all available PSUBFIFOs */ -	nv_wr32(priv, 0x000204, 0xffffffff); -	priv->spoon_nr = hweight32(nv_rd32(priv, 0x000204)); -	nv_debug(priv, "%d subfifo(s)\n", priv->spoon_nr); +	INIT_WORK(&priv->fault, nve0_fifo_recover_work); -	/* PSUBFIFO[n] */ -	for (i = 0; i < priv->spoon_nr; i++) { -		nv_mask(priv, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000); -		nv_wr32(priv, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */ -		nv_wr32(priv, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */ +	for (i = 0; i < FIFO_ENGINE_NR; i++) { +		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, +					 0, &priv->engine[i].runlist[0]); +		if (ret) +			return ret; + +		ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0x1000, +					 0, &priv->engine[i].runlist[1]); +		if (ret) +			return ret; + +		init_waitqueue_head(&priv->engine[i].wait);  	} -	nv_wr32(priv, 0x002254, 0x10000000 | priv->user.bar.offset >> 12); +	ret = nouveau_gpuobj_new(nv_object(priv), NULL, impl->channels * 0x200, +				0x1000, NVOBJ_FLAG_ZERO_ALLOC, &priv->user.mem); +	if (ret) +		return ret; -	nv_wr32(priv, 0x002a00, 0xffffffff); -	nv_wr32(priv, 0x002100, 0xffffffff); -	nv_wr32(priv, 0x002140, 0x3fffffff); +	ret = nouveau_gpuobj_map(priv->user.mem, NV_MEM_ACCESS_RW, +				&priv->user.bar); +	if (ret) +		return ret; + +	priv->base.uevent->enable = nve0_fifo_uevent_enable; +	priv->base.uevent->disable = nve0_fifo_uevent_disable; +	priv->base.uevent->priv = priv; + +	nv_subdev(priv)->unit = 0x00000100; +	nv_subdev(priv)->intr = nve0_fifo_intr; +	nv_engine(priv)->cclass = &nve0_fifo_cclass; +	nv_engine(priv)->sclass = nve0_fifo_sclass;  	return 0;  } -struct nouveau_oclass -nve0_fifo_oclass = { -	.handle = NV_ENGINE(FIFO, 0xe0), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nve0_fifo_oclass = &(struct nve0_fifo_impl) { +	.base.handle = NV_ENGINE(FIFO, 0xe0), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nve0_fifo_ctor,  		.dtor = nve0_fifo_dtor,  		.init = nve0_fifo_init, -		.fini = _nouveau_fifo_fini, +		.fini = nve0_fifo_fini,  	}, -}; +	.channels = 4096, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h new file mode 100644 index 00000000000..e96b32bb1bb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.h @@ -0,0 +1,18 @@ +#ifndef __NVKM_FIFO_NVE0_H__ +#define __NVKM_FIFO_NVE0_H__ + +#include <engine/fifo.h> + +int  nve0_fifo_ctor(struct nouveau_object *, struct nouveau_object *, +		    struct nouveau_oclass *, void *, u32, +		    struct nouveau_object **); +void nve0_fifo_dtor(struct nouveau_object *); +int  nve0_fifo_init(struct nouveau_object *); +int  nve0_fifo_fini(struct nouveau_object *, bool); + +struct nve0_fifo_impl { +	struct nouveau_oclass base; +	u32 channels; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c new file mode 100644 index 00000000000..224ee0287ab --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "ctxnvc0.h" + +static const struct nvc0_graph_pack +gk20a_grctx_pack_mthd[] = { +	{ nve4_grctx_init_a097_0, 0xa297 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{} +}; + +struct nouveau_oclass * +gk20a_grctx_oclass = &(struct nvc0_grctx_oclass) { +	.base.handle = NV_ENGCTX(GR, 0xea), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_graph_context_ctor, +		.dtor = nvc0_graph_context_dtor, +		.init = _nouveau_graph_context_init, +		.fini = _nouveau_graph_context_fini, +		.rd32 = _nouveau_graph_context_rd32, +		.wr32 = _nouveau_graph_context_wr32, +	}, +	.main  = nve4_grctx_generate_main, +	.mods  = nve4_grctx_generate_mods, +	.unkn  = nve4_grctx_generate_unkn, +	.hub   = nve4_grctx_pack_hub, +	.gpc   = nve4_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nve4_grctx_pack_tpc, +	.ppc   = nve4_grctx_pack_ppc, +	.icmd  = nve4_grctx_pack_icmd, +	.mthd  = gk20a_grctx_pack_mthd, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c new file mode 100644 index 00000000000..b0d0fb2f4d0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c @@ -0,0 +1,991 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include "ctxnvc0.h" + +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +gm107_grctx_init_icmd_0[] = { +	{ 0x001000,   1, 0x01, 0x00000004 }, +	{ 0x000039,   3, 0x01, 0x00000000 }, +	{ 0x0000a9,   1, 0x01, 0x0000ffff }, +	{ 0x000038,   1, 0x01, 0x0fac6881 }, +	{ 0x00003d,   1, 0x01, 0x00000001 }, +	{ 0x0000e8,   8, 0x01, 0x00000400 }, +	{ 0x000078,   8, 0x01, 0x00000300 }, +	{ 0x000050,   1, 0x01, 0x00000011 }, +	{ 0x000058,   8, 0x01, 0x00000008 }, +	{ 0x000208,   8, 0x01, 0x00000001 }, +	{ 0x000081,   1, 0x01, 0x00000001 }, +	{ 0x000085,   1, 0x01, 0x00000004 }, +	{ 0x000088,   1, 0x01, 0x00000400 }, +	{ 0x000090,   1, 0x01, 0x00000300 }, +	{ 0x000098,   1, 0x01, 0x00001001 }, +	{ 0x0000e3,   1, 0x01, 0x00000001 }, +	{ 0x0000da,   1, 0x01, 0x00000001 }, +	{ 0x0000f8,   1, 0x01, 0x00000003 }, +	{ 0x0000fa,   1, 0x01, 0x00000001 }, +	{ 0x0000b1,   2, 0x01, 0x00000001 }, +	{ 0x00009f,   4, 0x01, 0x0000ffff }, +	{ 0x0000a8,   1, 0x01, 0x0000ffff }, +	{ 0x0000ad,   1, 0x01, 0x0000013e }, +	{ 0x0000e1,   1, 0x01, 0x00000010 }, +	{ 0x000290,  16, 0x01, 0x00000000 }, +	{ 0x0003b0,  16, 0x01, 0x00000000 }, +	{ 0x0002a0,  16, 0x01, 0x00000000 }, +	{ 0x000420,  16, 0x01, 0x00000000 }, +	{ 0x0002b0,  16, 0x01, 0x00000000 }, +	{ 0x000430,  16, 0x01, 0x00000000 }, +	{ 0x0002c0,  16, 0x01, 0x00000000 }, +	{ 0x0004d0,  16, 0x01, 0x00000000 }, +	{ 0x000720,  16, 0x01, 0x00000000 }, +	{ 0x0008c0,  16, 0x01, 0x00000000 }, +	{ 0x000890,  16, 0x01, 0x00000000 }, +	{ 0x0008e0,  16, 0x01, 0x00000000 }, +	{ 0x0008a0,  16, 0x01, 0x00000000 }, +	{ 0x0008f0,  16, 0x01, 0x00000000 }, +	{ 0x00094c,   1, 0x01, 0x000000ff }, +	{ 0x00094d,   1, 0x01, 0xffffffff }, +	{ 0x00094e,   1, 0x01, 0x00000002 }, +	{ 0x0002f2,   2, 0x01, 0x00000001 }, +	{ 0x0002f5,   1, 0x01, 0x00000001 }, +	{ 0x0002f7,   1, 0x01, 0x00000001 }, +	{ 0x000303,   1, 0x01, 0x00000001 }, +	{ 0x0002e6,   1, 0x01, 0x00000001 }, +	{ 0x000466,   1, 0x01, 0x00000052 }, +	{ 0x000301,   1, 0x01, 0x3f800000 }, +	{ 0x000304,   1, 0x01, 0x30201000 }, +	{ 0x000305,   1, 0x01, 0x70605040 }, +	{ 0x000306,   1, 0x01, 0xb8a89888 }, +	{ 0x000307,   1, 0x01, 0xf8e8d8c8 }, +	{ 0x00030a,   1, 0x01, 0x00ffff00 }, +	{ 0x0000de,   1, 0x01, 0x00000001 }, +	{ 0x00030b,   1, 0x01, 0x0000001a }, +	{ 0x00030c,   1, 0x01, 0x00000001 }, +	{ 0x000318,   1, 0x01, 0x00000001 }, +	{ 0x000340,   1, 0x01, 0x00000000 }, +	{ 0x00037d,   1, 0x01, 0x00000006 }, +	{ 0x0003a0,   1, 0x01, 0x00000002 }, +	{ 0x0003aa,   1, 0x01, 0x00000001 }, +	{ 0x0003a9,   1, 0x01, 0x00000001 }, +	{ 0x000380,   1, 0x01, 0x00000001 }, +	{ 0x000383,   1, 0x01, 0x00000011 }, +	{ 0x000360,   1, 0x01, 0x00000040 }, +	{ 0x000366,   2, 0x01, 0x00000000 }, +	{ 0x000368,   1, 0x01, 0x00000fff }, +	{ 0x000370,   2, 0x01, 0x00000000 }, +	{ 0x000372,   1, 0x01, 0x000fffff }, +	{ 0x00037a,   1, 0x01, 0x00000012 }, +	{ 0x000619,   1, 0x01, 0x00000003 }, +	{ 0x000811,   1, 0x01, 0x00000003 }, +	{ 0x000812,   1, 0x01, 0x00000004 }, +	{ 0x000813,   1, 0x01, 0x00000006 }, +	{ 0x000814,   1, 0x01, 0x00000008 }, +	{ 0x000815,   1, 0x01, 0x0000000b }, +	{ 0x000800,   6, 0x01, 0x00000001 }, +	{ 0x000632,   1, 0x01, 0x00000001 }, +	{ 0x000633,   1, 0x01, 0x00000002 }, +	{ 0x000634,   1, 0x01, 0x00000003 }, +	{ 0x000635,   1, 0x01, 0x00000004 }, +	{ 0x000654,   1, 0x01, 0x3f800000 }, +	{ 0x000657,   1, 0x01, 0x3f800000 }, +	{ 0x000655,   2, 0x01, 0x3f800000 }, +	{ 0x0006cd,   1, 0x01, 0x3f800000 }, +	{ 0x0007f5,   1, 0x01, 0x3f800000 }, +	{ 0x0007dc,   1, 0x01, 0x39291909 }, +	{ 0x0007dd,   1, 0x01, 0x79695949 }, +	{ 0x0007de,   1, 0x01, 0xb9a99989 }, +	{ 0x0007df,   1, 0x01, 0xf9e9d9c9 }, +	{ 0x0007e8,   1, 0x01, 0x00003210 }, +	{ 0x0007e9,   1, 0x01, 0x00007654 }, +	{ 0x0007ea,   1, 0x01, 0x00000098 }, +	{ 0x0007ec,   1, 0x01, 0x39291909 }, +	{ 0x0007ed,   1, 0x01, 0x79695949 }, +	{ 0x0007ee,   1, 0x01, 0xb9a99989 }, +	{ 0x0007ef,   1, 0x01, 0xf9e9d9c9 }, +	{ 0x0007f0,   1, 0x01, 0x00003210 }, +	{ 0x0007f1,   1, 0x01, 0x00007654 }, +	{ 0x0007f2,   1, 0x01, 0x00000098 }, +	{ 0x0005a5,   1, 0x01, 0x00000001 }, +	{ 0x0005d0,   1, 0x01, 0x20181008 }, +	{ 0x0005d1,   1, 0x01, 0x40383028 }, +	{ 0x0005d2,   1, 0x01, 0x60585048 }, +	{ 0x0005d3,   1, 0x01, 0x80787068 }, +	{ 0x000980, 128, 0x01, 0x00000000 }, +	{ 0x000468,   1, 0x01, 0x00000004 }, +	{ 0x00046c,   1, 0x01, 0x00000001 }, +	{ 0x000470,  96, 0x01, 0x00000000 }, +	{ 0x000510,  16, 0x01, 0x3f800000 }, +	{ 0x000520,   1, 0x01, 0x000002b6 }, +	{ 0x000529,   1, 0x01, 0x00000001 }, +	{ 0x000530,  16, 0x01, 0xffff0000 }, +	{ 0x000550,  32, 0x01, 0xffff0000 }, +	{ 0x000585,   1, 0x01, 0x0000003f }, +	{ 0x000576,   1, 0x01, 0x00000003 }, +	{ 0x00057b,   1, 0x01, 0x00000059 }, +	{ 0x000586,   1, 0x01, 0x00000040 }, +	{ 0x000582,   2, 0x01, 0x00000080 }, +	{ 0x000595,   1, 0x01, 0x00400040 }, +	{ 0x000596,   1, 0x01, 0x00000492 }, +	{ 0x000597,   1, 0x01, 0x08080203 }, +	{ 0x0005ad,   1, 0x01, 0x00000008 }, +	{ 0x000598,   1, 0x01, 0x00020001 }, +	{ 0x0005c2,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 }, +	{ 0x00063a,   1, 0x01, 0x00000002 }, +	{ 0x00063b,   2, 0x01, 0x00000001 }, +	{ 0x00063d,   1, 0x01, 0x00000002 }, +	{ 0x00063e,   1, 0x01, 0x00000001 }, +	{ 0x0008b8,   8, 0x01, 0x00000001 }, +	{ 0x000900,   8, 0x01, 0x00000001 }, +	{ 0x000908,   8, 0x01, 0x00000002 }, +	{ 0x000910,  16, 0x01, 0x00000001 }, +	{ 0x000920,   8, 0x01, 0x00000002 }, +	{ 0x000928,   8, 0x01, 0x00000001 }, +	{ 0x000662,   1, 0x01, 0x00000001 }, +	{ 0x000648,   9, 0x01, 0x00000001 }, +	{ 0x000658,   1, 0x01, 0x0000000f }, +	{ 0x0007ff,   1, 0x01, 0x0000000a }, +	{ 0x00066a,   1, 0x01, 0x40000000 }, +	{ 0x00066b,   1, 0x01, 0x10000000 }, +	{ 0x00066c,   2, 0x01, 0xffff0000 }, +	{ 0x0007af,   2, 0x01, 0x00000008 }, +	{ 0x0007f6,   1, 0x01, 0x00000001 }, +	{ 0x0006b2,   1, 0x01, 0x00000055 }, +	{ 0x0007ad,   1, 0x01, 0x00000003 }, +	{ 0x000971,   1, 0x01, 0x00000008 }, +	{ 0x000972,   1, 0x01, 0x00000040 }, +	{ 0x000973,   1, 0x01, 0x0000012c }, +	{ 0x00097c,   1, 0x01, 0x00000040 }, +	{ 0x000975,   1, 0x01, 0x00000020 }, +	{ 0x000976,   1, 0x01, 0x00000001 }, +	{ 0x000977,   1, 0x01, 0x00000020 }, +	{ 0x000978,   1, 0x01, 0x00000001 }, +	{ 0x000957,   1, 0x01, 0x00000003 }, +	{ 0x00095e,   1, 0x01, 0x20164010 }, +	{ 0x00095f,   1, 0x01, 0x00000020 }, +	{ 0x000a0d,   1, 0x01, 0x00000006 }, +	{ 0x00097d,   1, 0x01, 0x0000000c }, +	{ 0x000683,   1, 0x01, 0x00000006 }, +	{ 0x000687,   1, 0x01, 0x003fffff }, +	{ 0x0006a0,   1, 0x01, 0x00000005 }, +	{ 0x000840,   1, 0x01, 0x00400008 }, +	{ 0x000841,   1, 0x01, 0x08000080 }, +	{ 0x000842,   1, 0x01, 0x00400008 }, +	{ 0x000843,   1, 0x01, 0x08000080 }, +	{ 0x000818,   8, 0x01, 0x00000000 }, +	{ 0x000848,  16, 0x01, 0x00000000 }, +	{ 0x000738,   1, 0x01, 0x00000000 }, +	{ 0x0006aa,   1, 0x01, 0x00000001 }, +	{ 0x0006ab,   1, 0x01, 0x00000002 }, +	{ 0x0006ac,   1, 0x01, 0x00000080 }, +	{ 0x0006ad,   2, 0x01, 0x00000100 }, +	{ 0x0006b1,   1, 0x01, 0x00000011 }, +	{ 0x0006bb,   1, 0x01, 0x000000cf }, +	{ 0x0006ce,   1, 0x01, 0x2a712488 }, +	{ 0x000739,   1, 0x01, 0x4085c000 }, +	{ 0x00073a,   1, 0x01, 0x00000080 }, +	{ 0x000786,   1, 0x01, 0x80000100 }, +	{ 0x00073c,   1, 0x01, 0x00010100 }, +	{ 0x00073d,   1, 0x01, 0x02800000 }, +	{ 0x000787,   1, 0x01, 0x000000cf }, +	{ 0x00078c,   1, 0x01, 0x00000008 }, +	{ 0x000792,   1, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 }, +	{ 0x000797,   1, 0x01, 0x000000cf }, +	{ 0x000836,   1, 0x01, 0x00000001 }, +	{ 0x00079a,   1, 0x01, 0x00000002 }, +	{ 0x000833,   1, 0x01, 0x04444480 }, +	{ 0x0007a1,   1, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 }, +	{ 0x000831,   1, 0x01, 0x00000004 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x000a04,   1, 0x01, 0x000000ff }, +	{ 0x000a0b,   1, 0x01, 0x00000040 }, +	{ 0x00097f,   1, 0x01, 0x00000100 }, +	{ 0x000a02,   1, 0x01, 0x00000001 }, +	{ 0x000809,   1, 0x01, 0x00000007 }, +	{ 0x00c221,   1, 0x01, 0x00000040 }, +	{ 0x00c1b0,   8, 0x01, 0x0000000f }, +	{ 0x00c1b8,   1, 0x01, 0x0fac6881 }, +	{ 0x00c1b9,   1, 0x01, 0x00fac688 }, +	{ 0x00c401,   1, 0x01, 0x00000001 }, +	{ 0x00c402,   1, 0x01, 0x00010001 }, +	{ 0x00c403,   2, 0x01, 0x00000001 }, +	{ 0x00c40e,   1, 0x01, 0x00000020 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000002 }, +	{ 0x0006aa,   1, 0x01, 0x00000001 }, +	{ 0x0006ad,   2, 0x01, 0x00000100 }, +	{ 0x0006b1,   1, 0x01, 0x00000011 }, +	{ 0x00078c,   1, 0x01, 0x00000008 }, +	{ 0x000792,   1, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 }, +	{ 0x000797,   1, 0x01, 0x000000cf }, +	{ 0x00079a,   1, 0x01, 0x00000002 }, +	{ 0x0007a1,   1, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 }, +	{ 0x000831,   1, 0x01, 0x00000004 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000008 }, +	{ 0x000039,   3, 0x01, 0x00000000 }, +	{ 0x000380,   1, 0x01, 0x00000001 }, +	{ 0x000366,   2, 0x01, 0x00000000 }, +	{ 0x000368,   1, 0x01, 0x00000fff }, +	{ 0x000370,   2, 0x01, 0x00000000 }, +	{ 0x000372,   1, 0x01, 0x000fffff }, +	{ 0x000813,   1, 0x01, 0x00000006 }, +	{ 0x000814,   1, 0x01, 0x00000008 }, +	{ 0x000818,   8, 0x01, 0x00000000 }, +	{ 0x000848,  16, 0x01, 0x00000000 }, +	{ 0x000738,   1, 0x01, 0x00000000 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x000a04,   1, 0x01, 0x000000ff }, +	{ 0x000a0b,   1, 0x01, 0x00000040 }, +	{ 0x00097f,   1, 0x01, 0x00000100 }, +	{ 0x000a02,   1, 0x01, 0x00000001 }, +	{ 0x000809,   1, 0x01, 0x00000007 }, +	{ 0x00c221,   1, 0x01, 0x00000040 }, +	{ 0x00c401,   1, 0x01, 0x00000001 }, +	{ 0x00c402,   1, 0x01, 0x00010001 }, +	{ 0x00c403,   2, 0x01, 0x00000001 }, +	{ 0x00c40e,   1, 0x01, 0x00000020 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000001 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_grctx_pack_icmd[] = { +	{ gm107_grctx_init_icmd_0 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_b097_0[] = { +	{ 0x000800,   8, 0x40, 0x00000000 }, +	{ 0x000804,   8, 0x40, 0x00000000 }, +	{ 0x000808,   8, 0x40, 0x00000400 }, +	{ 0x00080c,   8, 0x40, 0x00000300 }, +	{ 0x000810,   1, 0x04, 0x000000cf }, +	{ 0x000850,   7, 0x40, 0x00000000 }, +	{ 0x000814,   8, 0x40, 0x00000040 }, +	{ 0x000818,   8, 0x40, 0x00000001 }, +	{ 0x00081c,   8, 0x40, 0x00000000 }, +	{ 0x000820,   8, 0x40, 0x00000000 }, +	{ 0x001c00,  16, 0x10, 0x00000000 }, +	{ 0x001c04,  16, 0x10, 0x00000000 }, +	{ 0x001c08,  16, 0x10, 0x00000000 }, +	{ 0x001c0c,  16, 0x10, 0x00000000 }, +	{ 0x001d00,  16, 0x10, 0x00000000 }, +	{ 0x001d04,  16, 0x10, 0x00000000 }, +	{ 0x001d08,  16, 0x10, 0x00000000 }, +	{ 0x001d0c,  16, 0x10, 0x00000000 }, +	{ 0x001f00,  16, 0x08, 0x00000000 }, +	{ 0x001f04,  16, 0x08, 0x00000000 }, +	{ 0x001f80,  16, 0x08, 0x00000000 }, +	{ 0x001f84,  16, 0x08, 0x00000000 }, +	{ 0x002000,   1, 0x04, 0x00000000 }, +	{ 0x002040,   1, 0x04, 0x00000011 }, +	{ 0x002080,   1, 0x04, 0x00000020 }, +	{ 0x0020c0,   1, 0x04, 0x00000030 }, +	{ 0x002100,   1, 0x04, 0x00000040 }, +	{ 0x002140,   1, 0x04, 0x00000051 }, +	{ 0x00200c,   6, 0x40, 0x00000001 }, +	{ 0x002010,   1, 0x04, 0x00000000 }, +	{ 0x002050,   1, 0x04, 0x00000000 }, +	{ 0x002090,   1, 0x04, 0x00000001 }, +	{ 0x0020d0,   1, 0x04, 0x00000002 }, +	{ 0x002110,   1, 0x04, 0x00000003 }, +	{ 0x002150,   1, 0x04, 0x00000004 }, +	{ 0x000380,   4, 0x20, 0x00000000 }, +	{ 0x000384,   4, 0x20, 0x00000000 }, +	{ 0x000388,   4, 0x20, 0x00000000 }, +	{ 0x00038c,   4, 0x20, 0x00000000 }, +	{ 0x000700,   4, 0x10, 0x00000000 }, +	{ 0x000704,   4, 0x10, 0x00000000 }, +	{ 0x000708,   4, 0x10, 0x00000000 }, +	{ 0x002800, 128, 0x04, 0x00000000 }, +	{ 0x000a00,  16, 0x20, 0x00000000 }, +	{ 0x000a04,  16, 0x20, 0x00000000 }, +	{ 0x000a08,  16, 0x20, 0x00000000 }, +	{ 0x000a0c,  16, 0x20, 0x00000000 }, +	{ 0x000a10,  16, 0x20, 0x00000000 }, +	{ 0x000a14,  16, 0x20, 0x00000000 }, +	{ 0x000c00,  16, 0x10, 0x00000000 }, +	{ 0x000c04,  16, 0x10, 0x00000000 }, +	{ 0x000c08,  16, 0x10, 0x00000000 }, +	{ 0x000c0c,  16, 0x10, 0x3f800000 }, +	{ 0x000d00,   8, 0x08, 0xffff0000 }, +	{ 0x000d04,   8, 0x08, 0xffff0000 }, +	{ 0x000e00,  16, 0x10, 0x00000000 }, +	{ 0x000e04,  16, 0x10, 0xffff0000 }, +	{ 0x000e08,  16, 0x10, 0xffff0000 }, +	{ 0x000d40,   4, 0x08, 0x00000000 }, +	{ 0x000d44,   4, 0x08, 0x00000000 }, +	{ 0x001e00,   8, 0x20, 0x00000001 }, +	{ 0x001e04,   8, 0x20, 0x00000001 }, +	{ 0x001e08,   8, 0x20, 0x00000002 }, +	{ 0x001e0c,   8, 0x20, 0x00000001 }, +	{ 0x001e10,   8, 0x20, 0x00000001 }, +	{ 0x001e14,   8, 0x20, 0x00000002 }, +	{ 0x001e18,   8, 0x20, 0x00000001 }, +	{ 0x001480,   8, 0x10, 0x00000000 }, +	{ 0x001484,   8, 0x10, 0x00000000 }, +	{ 0x001488,   8, 0x10, 0x00000000 }, +	{ 0x003400, 128, 0x04, 0x00000000 }, +	{ 0x00030c,   1, 0x04, 0x00000001 }, +	{ 0x001944,   1, 0x04, 0x00000000 }, +	{ 0x001514,   1, 0x04, 0x00000000 }, +	{ 0x000d68,   1, 0x04, 0x0000ffff }, +	{ 0x00121c,   1, 0x04, 0x0fac6881 }, +	{ 0x000fac,   1, 0x04, 0x00000001 }, +	{ 0x001538,   1, 0x04, 0x00000001 }, +	{ 0x000fe0,   2, 0x04, 0x00000000 }, +	{ 0x000fe8,   1, 0x04, 0x00000014 }, +	{ 0x000fec,   1, 0x04, 0x00000040 }, +	{ 0x000ff0,   1, 0x04, 0x00000000 }, +	{ 0x00179c,   1, 0x04, 0x00000000 }, +	{ 0x001228,   1, 0x04, 0x00000400 }, +	{ 0x00122c,   1, 0x04, 0x00000300 }, +	{ 0x001230,   1, 0x04, 0x00010001 }, +	{ 0x0007f8,   1, 0x04, 0x00000000 }, +	{ 0x0015b4,   1, 0x04, 0x00000001 }, +	{ 0x0015cc,   1, 0x04, 0x00000000 }, +	{ 0x001534,   1, 0x04, 0x00000000 }, +	{ 0x000754,   1, 0x04, 0x00000001 }, +	{ 0x000fb0,   1, 0x04, 0x00000000 }, +	{ 0x0015d0,   1, 0x04, 0x00000000 }, +	{ 0x00153c,   1, 0x04, 0x00000000 }, +	{ 0x0016b4,   1, 0x04, 0x00000003 }, +	{ 0x000fbc,   4, 0x04, 0x0000ffff }, +	{ 0x000df8,   2, 0x04, 0x00000000 }, +	{ 0x001948,   1, 0x04, 0x00000000 }, +	{ 0x001970,   1, 0x04, 0x00000001 }, +	{ 0x00161c,   1, 0x04, 0x000009f0 }, +	{ 0x000dcc,   1, 0x04, 0x00000010 }, +	{ 0x0015e4,   1, 0x04, 0x00000000 }, +	{ 0x001160,  32, 0x04, 0x25e00040 }, +	{ 0x001880,  32, 0x04, 0x00000000 }, +	{ 0x000f84,   2, 0x04, 0x00000000 }, +	{ 0x0017c8,   2, 0x04, 0x00000000 }, +	{ 0x0017d0,   1, 0x04, 0x000000ff }, +	{ 0x0017d4,   1, 0x04, 0xffffffff }, +	{ 0x0017d8,   1, 0x04, 0x00000002 }, +	{ 0x0017dc,   1, 0x04, 0x00000000 }, +	{ 0x0015f4,   2, 0x04, 0x00000000 }, +	{ 0x001434,   2, 0x04, 0x00000000 }, +	{ 0x000d74,   1, 0x04, 0x00000000 }, +	{ 0x0013a4,   1, 0x04, 0x00000000 }, +	{ 0x001318,   1, 0x04, 0x00000001 }, +	{ 0x001080,   2, 0x04, 0x00000000 }, +	{ 0x001088,   2, 0x04, 0x00000001 }, +	{ 0x001090,   1, 0x04, 0x00000000 }, +	{ 0x001094,   1, 0x04, 0x00000001 }, +	{ 0x001098,   1, 0x04, 0x00000000 }, +	{ 0x00109c,   1, 0x04, 0x00000001 }, +	{ 0x0010a0,   2, 0x04, 0x00000000 }, +	{ 0x001644,   1, 0x04, 0x00000000 }, +	{ 0x000748,   1, 0x04, 0x00000000 }, +	{ 0x000de8,   1, 0x04, 0x00000000 }, +	{ 0x001648,   1, 0x04, 0x00000000 }, +	{ 0x0012a4,   1, 0x04, 0x00000000 }, +	{ 0x001120,   4, 0x04, 0x00000000 }, +	{ 0x001118,   1, 0x04, 0x00000000 }, +	{ 0x00164c,   1, 0x04, 0x00000000 }, +	{ 0x001658,   1, 0x04, 0x00000000 }, +	{ 0x001910,   1, 0x04, 0x00000290 }, +	{ 0x001518,   1, 0x04, 0x00000000 }, +	{ 0x00165c,   1, 0x04, 0x00000001 }, +	{ 0x001520,   1, 0x04, 0x00000000 }, +	{ 0x001604,   1, 0x04, 0x00000000 }, +	{ 0x001570,   1, 0x04, 0x00000000 }, +	{ 0x0013b0,   2, 0x04, 0x3f800000 }, +	{ 0x00020c,   1, 0x04, 0x00000000 }, +	{ 0x001670,   1, 0x04, 0x30201000 }, +	{ 0x001674,   1, 0x04, 0x70605040 }, +	{ 0x001678,   1, 0x04, 0xb8a89888 }, +	{ 0x00167c,   1, 0x04, 0xf8e8d8c8 }, +	{ 0x00166c,   1, 0x04, 0x00000000 }, +	{ 0x001680,   1, 0x04, 0x00ffff00 }, +	{ 0x0012d0,   1, 0x04, 0x00000003 }, +	{ 0x0012d4,   1, 0x04, 0x00000002 }, +	{ 0x001684,   2, 0x04, 0x00000000 }, +	{ 0x000dac,   2, 0x04, 0x00001b02 }, +	{ 0x000db4,   1, 0x04, 0x00000000 }, +	{ 0x00168c,   1, 0x04, 0x00000000 }, +	{ 0x0015bc,   1, 0x04, 0x00000000 }, +	{ 0x00156c,   1, 0x04, 0x00000000 }, +	{ 0x00187c,   1, 0x04, 0x00000000 }, +	{ 0x001110,   1, 0x04, 0x00000001 }, +	{ 0x000dc0,   3, 0x04, 0x00000000 }, +	{ 0x000f40,   5, 0x04, 0x00000000 }, +	{ 0x001234,   1, 0x04, 0x00000000 }, +	{ 0x001690,   1, 0x04, 0x00000000 }, +	{ 0x000790,   5, 0x04, 0x00000000 }, +	{ 0x00077c,   1, 0x04, 0x00000000 }, +	{ 0x001000,   1, 0x04, 0x00000010 }, +	{ 0x0010fc,   1, 0x04, 0x00000000 }, +	{ 0x001290,   1, 0x04, 0x00000000 }, +	{ 0x000218,   1, 0x04, 0x00000010 }, +	{ 0x0012d8,   1, 0x04, 0x00000000 }, +	{ 0x0012dc,   1, 0x04, 0x00000010 }, +	{ 0x000d94,   1, 0x04, 0x00000001 }, +	{ 0x00155c,   2, 0x04, 0x00000000 }, +	{ 0x001564,   1, 0x04, 0x00000fff }, +	{ 0x001574,   2, 0x04, 0x00000000 }, +	{ 0x00157c,   1, 0x04, 0x000fffff }, +	{ 0x001354,   1, 0x04, 0x00000000 }, +	{ 0x001610,   1, 0x04, 0x00000012 }, +	{ 0x001608,   2, 0x04, 0x00000000 }, +	{ 0x00260c,   1, 0x04, 0x00000000 }, +	{ 0x0007ac,   1, 0x04, 0x00000000 }, +	{ 0x00162c,   1, 0x04, 0x00000003 }, +	{ 0x000210,   1, 0x04, 0x00000000 }, +	{ 0x000320,   1, 0x04, 0x00000000 }, +	{ 0x000324,   6, 0x04, 0x3f800000 }, +	{ 0x000750,   1, 0x04, 0x00000000 }, +	{ 0x000760,   1, 0x04, 0x39291909 }, +	{ 0x000764,   1, 0x04, 0x79695949 }, +	{ 0x000768,   1, 0x04, 0xb9a99989 }, +	{ 0x00076c,   1, 0x04, 0xf9e9d9c9 }, +	{ 0x000770,   1, 0x04, 0x30201000 }, +	{ 0x000774,   1, 0x04, 0x70605040 }, +	{ 0x000778,   1, 0x04, 0x00009080 }, +	{ 0x000780,   1, 0x04, 0x39291909 }, +	{ 0x000784,   1, 0x04, 0x79695949 }, +	{ 0x000788,   1, 0x04, 0xb9a99989 }, +	{ 0x00078c,   1, 0x04, 0xf9e9d9c9 }, +	{ 0x0007d0,   1, 0x04, 0x30201000 }, +	{ 0x0007d4,   1, 0x04, 0x70605040 }, +	{ 0x0007d8,   1, 0x04, 0x00009080 }, +	{ 0x00037c,   1, 0x04, 0x00000001 }, +	{ 0x000740,   2, 0x04, 0x00000000 }, +	{ 0x002600,   1, 0x04, 0x00000000 }, +	{ 0x001918,   1, 0x04, 0x00000000 }, +	{ 0x00191c,   1, 0x04, 0x00000900 }, +	{ 0x001920,   1, 0x04, 0x00000405 }, +	{ 0x001308,   1, 0x04, 0x00000001 }, +	{ 0x001924,   1, 0x04, 0x00000000 }, +	{ 0x0013ac,   1, 0x04, 0x00000000 }, +	{ 0x00192c,   1, 0x04, 0x00000001 }, +	{ 0x00193c,   1, 0x04, 0x00002c1c }, +	{ 0x000d7c,   1, 0x04, 0x00000000 }, +	{ 0x000f8c,   1, 0x04, 0x00000000 }, +	{ 0x0002c0,   1, 0x04, 0x00000001 }, +	{ 0x001510,   1, 0x04, 0x00000000 }, +	{ 0x001940,   1, 0x04, 0x00000000 }, +	{ 0x000ff4,   2, 0x04, 0x00000000 }, +	{ 0x00194c,   2, 0x04, 0x00000000 }, +	{ 0x001968,   1, 0x04, 0x00000000 }, +	{ 0x001590,   1, 0x04, 0x0000003f }, +	{ 0x0007e8,   4, 0x04, 0x00000000 }, +	{ 0x00196c,   1, 0x04, 0x00000011 }, +	{ 0x0002e4,   1, 0x04, 0x0000b001 }, +	{ 0x00036c,   2, 0x04, 0x00000000 }, +	{ 0x00197c,   1, 0x04, 0x00000000 }, +	{ 0x000fcc,   2, 0x04, 0x00000000 }, +	{ 0x0002d8,   1, 0x04, 0x00000040 }, +	{ 0x001980,   1, 0x04, 0x00000080 }, +	{ 0x001504,   1, 0x04, 0x00000080 }, +	{ 0x001984,   1, 0x04, 0x00000000 }, +	{ 0x000f60,   1, 0x04, 0x00000000 }, +	{ 0x000f64,   1, 0x04, 0x00400040 }, +	{ 0x000f68,   1, 0x04, 0x00002212 }, +	{ 0x000f6c,   1, 0x04, 0x08080203 }, +	{ 0x001108,   1, 0x04, 0x00000008 }, +	{ 0x000f70,   1, 0x04, 0x00080001 }, +	{ 0x000ffc,   1, 0x04, 0x00000000 }, +	{ 0x000300,   1, 0x04, 0x00000001 }, +	{ 0x0013a8,   1, 0x04, 0x00000000 }, +	{ 0x0012ec,   1, 0x04, 0x00000000 }, +	{ 0x001310,   1, 0x04, 0x00000000 }, +	{ 0x001314,   1, 0x04, 0x00000001 }, +	{ 0x001380,   1, 0x04, 0x00000000 }, +	{ 0x001384,   4, 0x04, 0x00000001 }, +	{ 0x001394,   1, 0x04, 0x00000000 }, +	{ 0x00139c,   1, 0x04, 0x00000000 }, +	{ 0x001398,   1, 0x04, 0x00000000 }, +	{ 0x001594,   1, 0x04, 0x00000000 }, +	{ 0x001598,   4, 0x04, 0x00000001 }, +	{ 0x000f54,   3, 0x04, 0x00000000 }, +	{ 0x0019bc,   1, 0x04, 0x00000000 }, +	{ 0x000f9c,   2, 0x04, 0x00000000 }, +	{ 0x0012cc,   1, 0x04, 0x00000000 }, +	{ 0x0012e8,   1, 0x04, 0x00000000 }, +	{ 0x00130c,   1, 0x04, 0x00000001 }, +	{ 0x001360,   8, 0x04, 0x00000000 }, +	{ 0x00133c,   2, 0x04, 0x00000001 }, +	{ 0x001344,   1, 0x04, 0x00000002 }, +	{ 0x001348,   2, 0x04, 0x00000001 }, +	{ 0x001350,   1, 0x04, 0x00000002 }, +	{ 0x001358,   1, 0x04, 0x00000001 }, +	{ 0x0012e4,   1, 0x04, 0x00000000 }, +	{ 0x00131c,   4, 0x04, 0x00000000 }, +	{ 0x0019c0,   1, 0x04, 0x00000000 }, +	{ 0x001140,   1, 0x04, 0x00000000 }, +	{ 0x000dd0,   1, 0x04, 0x00000000 }, +	{ 0x000dd4,   1, 0x04, 0x00000001 }, +	{ 0x0002f4,   1, 0x04, 0x00000000 }, +	{ 0x0019c4,   1, 0x04, 0x00000000 }, +	{ 0x0019c8,   1, 0x04, 0x00001500 }, +	{ 0x00135c,   1, 0x04, 0x00000000 }, +	{ 0x000f90,   1, 0x04, 0x00000000 }, +	{ 0x0019e0,   8, 0x04, 0x00000001 }, +	{ 0x0019cc,   1, 0x04, 0x00000001 }, +	{ 0x0015b8,   1, 0x04, 0x00000000 }, +	{ 0x001a00,   1, 0x04, 0x00001111 }, +	{ 0x001a04,   7, 0x04, 0x00000000 }, +	{ 0x000d6c,   2, 0x04, 0xffff0000 }, +	{ 0x0010f8,   1, 0x04, 0x00001010 }, +	{ 0x000d80,   5, 0x04, 0x00000000 }, +	{ 0x000da0,   1, 0x04, 0x00000000 }, +	{ 0x0007a4,   2, 0x04, 0x00000000 }, +	{ 0x001508,   1, 0x04, 0x80000000 }, +	{ 0x00150c,   1, 0x04, 0x40000000 }, +	{ 0x001668,   1, 0x04, 0x00000000 }, +	{ 0x000318,   2, 0x04, 0x00000008 }, +	{ 0x000d9c,   1, 0x04, 0x00000001 }, +	{ 0x000f14,   1, 0x04, 0x00000000 }, +	{ 0x000374,   1, 0x04, 0x00000000 }, +	{ 0x000378,   1, 0x04, 0x0000000c }, +	{ 0x0007dc,   1, 0x04, 0x00000000 }, +	{ 0x00074c,   1, 0x04, 0x00000055 }, +	{ 0x001420,   1, 0x04, 0x00000003 }, +	{ 0x001008,   1, 0x04, 0x00000008 }, +	{ 0x00100c,   1, 0x04, 0x00000040 }, +	{ 0x001010,   1, 0x04, 0x0000012c }, +	{ 0x000d60,   1, 0x04, 0x00000040 }, +	{ 0x001018,   1, 0x04, 0x00000020 }, +	{ 0x00101c,   1, 0x04, 0x00000001 }, +	{ 0x001020,   1, 0x04, 0x00000020 }, +	{ 0x001024,   1, 0x04, 0x00000001 }, +	{ 0x001444,   3, 0x04, 0x00000000 }, +	{ 0x000360,   1, 0x04, 0x20164010 }, +	{ 0x000364,   1, 0x04, 0x00000020 }, +	{ 0x000368,   1, 0x04, 0x00000000 }, +	{ 0x000da8,   1, 0x04, 0x00000030 }, +	{ 0x000de4,   1, 0x04, 0x00000000 }, +	{ 0x000204,   1, 0x04, 0x00000006 }, +	{ 0x0002d0,   1, 0x04, 0x003fffff }, +	{ 0x001220,   1, 0x04, 0x00000005 }, +	{ 0x000fdc,   1, 0x04, 0x00000000 }, +	{ 0x000f98,   1, 0x04, 0x00400008 }, +	{ 0x001284,   1, 0x04, 0x08000080 }, +	{ 0x001450,   1, 0x04, 0x00400008 }, +	{ 0x001454,   1, 0x04, 0x08000080 }, +	{ 0x000214,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_grctx_pack_mthd[] = { +	{ gm107_grctx_init_b097_0, 0xb097 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_fe_0[] = { +	{ 0x404004,   8, 0x04, 0x00000000 }, +	{ 0x404024,   1, 0x04, 0x0000e000 }, +	{ 0x404028,   8, 0x04, 0x00000000 }, +	{ 0x4040a8,   8, 0x04, 0x00000000 }, +	{ 0x4040c8,   1, 0x04, 0xf800008f }, +	{ 0x4040d0,   6, 0x04, 0x00000000 }, +	{ 0x4040f8,   1, 0x04, 0x00000000 }, +	{ 0x404100,  10, 0x04, 0x00000000 }, +	{ 0x404130,   2, 0x04, 0x00000000 }, +	{ 0x404150,   1, 0x04, 0x0000002e }, +	{ 0x404154,   1, 0x04, 0x00000400 }, +	{ 0x404158,   1, 0x04, 0x00000200 }, +	{ 0x404164,   1, 0x04, 0x00000045 }, +	{ 0x40417c,   2, 0x04, 0x00000000 }, +	{ 0x404194,   1, 0x04, 0x01000700 }, +	{ 0x4041a0,   4, 0x04, 0x00000000 }, +	{ 0x404200,   4, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_ds_0[] = { +	{ 0x405800,   1, 0x04, 0x0f8001bf }, +	{ 0x405830,   1, 0x04, 0x0aa01000 }, +	{ 0x405834,   1, 0x04, 0x08000000 }, +	{ 0x405838,   1, 0x04, 0x00000000 }, +	{ 0x405854,   1, 0x04, 0x00000000 }, +	{ 0x405870,   4, 0x04, 0x00000001 }, +	{ 0x405a00,   2, 0x04, 0x00000000 }, +	{ 0x405a18,   1, 0x04, 0x00000000 }, +	{ 0x405a1c,   1, 0x04, 0x000000ff }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_pd_0[] = { +	{ 0x406020,   1, 0x04, 0x07410001 }, +	{ 0x406028,   4, 0x04, 0x00000001 }, +	{ 0x4064a8,   1, 0x04, 0x00000000 }, +	{ 0x4064ac,   1, 0x04, 0x00003fff }, +	{ 0x4064b0,   3, 0x04, 0x00000000 }, +	{ 0x4064c0,   1, 0x04, 0x80400280 }, +	{ 0x4064c4,   1, 0x04, 0x0400ffff }, +	{ 0x4064c8,   1, 0x04, 0x018001ff }, +	{ 0x4064cc,   9, 0x04, 0x00000000 }, +	{ 0x4064fc,   1, 0x04, 0x0000022a }, +	{ 0x406500,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_be_0[] = { +	{ 0x408800,   1, 0x04, 0x32802a3c }, +	{ 0x408804,   1, 0x04, 0x00000040 }, +	{ 0x408808,   1, 0x04, 0x1003e005 }, +	{ 0x408840,   1, 0x04, 0x0000000b }, +	{ 0x408900,   1, 0x04, 0xb080b801 }, +	{ 0x408904,   1, 0x04, 0x63038001 }, +	{ 0x408908,   1, 0x04, 0x02c8102f }, +	{ 0x408980,   1, 0x04, 0x0000011d }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ gm107_grctx_init_fe_0 }, +	{ nvf0_grctx_init_pri_0 }, +	{ nve4_grctx_init_memfmt_0 }, +	{ gm107_grctx_init_ds_0 }, +	{ nvf0_grctx_init_cwd_0 }, +	{ gm107_grctx_init_pd_0 }, +	{ nv108_grctx_init_rstr2d_0 }, +	{ nve4_grctx_init_scc_0 }, +	{ gm107_grctx_init_be_0 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_gpc_unk_0[] = { +	{ 0x418380,   1, 0x04, 0x00000056 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_gpc_unk_1[] = { +	{ 0x418600,   1, 0x04, 0x0000007f }, +	{ 0x418684,   1, 0x04, 0x0000001f }, +	{ 0x418700,   1, 0x04, 0x00000002 }, +	{ 0x418704,   1, 0x04, 0x00000080 }, +	{ 0x418708,   1, 0x04, 0x40000000 }, +	{ 0x41870c,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_setup_0[] = { +	{ 0x418800,   1, 0x04, 0x7006863a }, +	{ 0x418810,   1, 0x04, 0x00000000 }, +	{ 0x418828,   1, 0x04, 0x00000044 }, +	{ 0x418830,   1, 0x04, 0x10000001 }, +	{ 0x4188d8,   1, 0x04, 0x00000008 }, +	{ 0x4188e0,   1, 0x04, 0x01000000 }, +	{ 0x4188e8,   5, 0x04, 0x00000000 }, +	{ 0x4188fc,   1, 0x04, 0x20100058 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_gpc_unk_2[] = { +	{ 0x418d24,   1, 0x04, 0x00000000 }, +	{ 0x418e00,   1, 0x04, 0x90000000 }, +	{ 0x418e24,   1, 0x04, 0x00000000 }, +	{ 0x418e28,   1, 0x04, 0x00000030 }, +	{ 0x418e30,   1, 0x04, 0x00000000 }, +	{ 0x418e34,   1, 0x04, 0x00010000 }, +	{ 0x418e38,   1, 0x04, 0x00000000 }, +	{ 0x418e40,  22, 0x04, 0x00000000 }, +	{ 0x418ea0,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_grctx_pack_gpc[] = { +	{ gm107_grctx_init_gpc_unk_0 }, +	{ nv108_grctx_init_prop_0 }, +	{ gm107_grctx_init_gpc_unk_1 }, +	{ gm107_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nv108_grctx_init_crstr_0 }, +	{ nve4_grctx_init_gpm_0 }, +	{ gm107_grctx_init_gpc_unk_2 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_tex_0[] = { +	{ 0x419a00,   1, 0x04, 0x000300f0 }, +	{ 0x419a04,   1, 0x04, 0x00000005 }, +	{ 0x419a08,   1, 0x04, 0x00000421 }, +	{ 0x419a0c,   1, 0x04, 0x00120000 }, +	{ 0x419a10,   1, 0x04, 0x00000000 }, +	{ 0x419a14,   1, 0x04, 0x00002200 }, +	{ 0x419a1c,   1, 0x04, 0x0000c000 }, +	{ 0x419a20,   1, 0x04, 0x20008a00 }, +	{ 0x419a30,   1, 0x04, 0x00000001 }, +	{ 0x419a3c,   1, 0x04, 0x00000002 }, +	{ 0x419ac4,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_mpc_0[] = { +	{ 0x419c00,   1, 0x04, 0x0000001a }, +	{ 0x419c04,   1, 0x04, 0x80000006 }, +	{ 0x419c08,   1, 0x04, 0x00000002 }, +	{ 0x419c20,   1, 0x04, 0x00000000 }, +	{ 0x419c24,   1, 0x04, 0x00084210 }, +	{ 0x419c28,   1, 0x04, 0x3efbefbe }, +	{ 0x419c2c,   1, 0x04, 0x00000000 }, +	{ 0x419c34,   1, 0x04, 0x01ff1ff3 }, +	{ 0x419c3c,   1, 0x04, 0x00001919 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_l1c_0[] = { +	{ 0x419c84,   1, 0x04, 0x00000020 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_sm_0[] = { +	{ 0x419e04,   3, 0x04, 0x00000000 }, +	{ 0x419e10,   1, 0x04, 0x00001c02 }, +	{ 0x419e44,   1, 0x04, 0x00d3eff2 }, +	{ 0x419e48,   1, 0x04, 0x00000000 }, +	{ 0x419e4c,   1, 0x04, 0x0000007f }, +	{ 0x419e50,   1, 0x04, 0x00000000 }, +	{ 0x419e60,   4, 0x04, 0x00000000 }, +	{ 0x419e74,  10, 0x04, 0x00000000 }, +	{ 0x419eac,   1, 0x04, 0x0001cf8b }, +	{ 0x419eb0,   1, 0x04, 0x00030300 }, +	{ 0x419eb8,   1, 0x04, 0x00000000 }, +	{ 0x419ef0,  24, 0x04, 0x00000000 }, +	{ 0x419f68,   2, 0x04, 0x00000000 }, +	{ 0x419f70,   1, 0x04, 0x00000020 }, +	{ 0x419f78,   1, 0x04, 0x000003eb }, +	{ 0x419f7c,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_grctx_pack_tpc[] = { +	{ nvd7_grctx_init_pe_0 }, +	{ gm107_grctx_init_tex_0 }, +	{ gm107_grctx_init_mpc_0 }, +	{ gm107_grctx_init_l1c_0 }, +	{ gm107_grctx_init_sm_0 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_cbm_0[] = { +	{ 0x41bec0,   1, 0x04, 0x00000000 }, +	{ 0x41bec4,   1, 0x04, 0x01050000 }, +	{ 0x41bee4,   1, 0x04, 0x00000000 }, +	{ 0x41bef0,   1, 0x04, 0x000003ff }, +	{ 0x41bef4,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_grctx_init_wwdx_0[] = { +	{ 0x41bf00,   1, 0x04, 0x0a418820 }, +	{ 0x41bf04,   1, 0x04, 0x062080e6 }, +	{ 0x41bf08,   1, 0x04, 0x020398a4 }, +	{ 0x41bf0c,   1, 0x04, 0x0e629062 }, +	{ 0x41bf10,   1, 0x04, 0x0a418820 }, +	{ 0x41bf14,   1, 0x04, 0x000000e6 }, +	{ 0x41bfd0,   1, 0x04, 0x00900103 }, +	{ 0x41bfe0,   1, 0x04, 0x80000000 }, +	{ 0x41bfe4,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_grctx_pack_ppc[] = { +	{ nve4_grctx_init_pes_0 }, +	{ gm107_grctx_init_cbm_0 }, +	{ gm107_grctx_init_wwdx_0 }, +	{} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ + +static void +gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) +{ +	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); +	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); +	mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW); + +	mmio_list(0x40800c, 0x00000000,  8, 1); +	mmio_list(0x408010, 0x80000000,  0, 0); +	mmio_list(0x419004, 0x00000000,  8, 1); +	mmio_list(0x419008, 0x00000000,  0, 0); +	mmio_list(0x4064cc, 0x80000000,  0, 0); +	mmio_list(0x418e30, 0x80000000,  0, 0); + +	mmio_list(0x408004, 0x00000000,  8, 0); +	mmio_list(0x408008, 0x80000030,  0, 0); +	mmio_list(0x418e24, 0x00000000,  8, 0); +	mmio_list(0x418e28, 0x80000030,  0, 0); + +	mmio_list(0x4064c8, 0x018002c0,  0, 0); + +	mmio_list(0x418810, 0x80000000, 12, 2); +	mmio_list(0x419848, 0x10000000, 12, 2); +	mmio_list(0x419c2c, 0x10000000, 12, 2); + +	mmio_list(0x405830, 0x0aa01000,  0, 0); +	mmio_list(0x4064c4, 0x0400ffff,  0, 0); + +	/*XXX*/ +	mmio_list(0x5030c0, 0x00001540,  0, 0); +	mmio_list(0x5030f4, 0x00000000,  0, 0); +	mmio_list(0x5030e4, 0x00002000,  0, 0); +	mmio_list(0x5030f8, 0x00003fc0,  0, 0); +	mmio_list(0x418ea0, 0x07151540,  0, 0); + +	mmio_list(0x5032c0, 0x00001540,  0, 0); +	mmio_list(0x5032f4, 0x00001fe0,  0, 0); +	mmio_list(0x5032e4, 0x00002000,  0, 0); +	mmio_list(0x5032f8, 0x00006fc0,  0, 0); +	mmio_list(0x418ea4, 0x07151540,  0, 0); +} + +static void +gm107_grctx_generate_tpcid(struct nvc0_graph_priv *priv) +{ +	int gpc, tpc, id; + +	for (tpc = 0, id = 0; tpc < 4; tpc++) { +		for (gpc = 0; gpc < priv->gpc_nr; gpc++) { +			if (tpc < priv->tpc_nr[gpc]) { +				nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); +				nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); +				nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); +				id++; +			} + +			nv_wr32(priv, GPC_UNIT(gpc, 0x0c08), priv->tpc_nr[gpc]); +			nv_wr32(priv, GPC_UNIT(gpc, 0x0c8c), priv->tpc_nr[gpc]); +		} +	} +} + +static void +gm107_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) +{ +	struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; +	int i; + +	nvc0_graph_mmio(priv, oclass->hub); +	nvc0_graph_mmio(priv, oclass->gpc); +	nvc0_graph_mmio(priv, oclass->zcull); +	nvc0_graph_mmio(priv, oclass->tpc); +	nvc0_graph_mmio(priv, oclass->ppc); + +	nv_wr32(priv, 0x404154, 0x00000000); + +	oclass->mods(priv, info); +	oclass->unkn(priv); + +	gm107_grctx_generate_tpcid(priv); +	nvc0_grctx_generate_r406028(priv); +	nve4_grctx_generate_r418bb8(priv); +	nvc0_grctx_generate_r406800(priv); + +	nv_wr32(priv, 0x4064d0, 0x00000001); +	for (i = 1; i < 8; i++) +		nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); +	nv_wr32(priv, 0x406500, 0x00000001); + +	nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); + +	if (priv->gpc_nr == 1) { +		nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]); +		nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]); +	} else { +		nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr); +		nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr); +	} + +	nvc0_graph_icmd(priv, oclass->icmd); +	nv_wr32(priv, 0x404154, 0x00000400); +	nvc0_graph_mthd(priv, oclass->mthd); + +	nv_mask(priv, 0x419e00, 0x00808080, 0x00808080); +	nv_mask(priv, 0x419ccc, 0x80000000, 0x80000000); +	nv_mask(priv, 0x419f80, 0x80000000, 0x80000000); +	nv_mask(priv, 0x419f88, 0x80000000, 0x80000000); +} + +struct nouveau_oclass * +gm107_grctx_oclass = &(struct nvc0_grctx_oclass) { +	.base.handle = NV_ENGCTX(GR, 0x08), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_graph_context_ctor, +		.dtor = nvc0_graph_context_dtor, +		.init = _nouveau_graph_context_init, +		.fini = _nouveau_graph_context_fini, +		.rd32 = _nouveau_graph_context_rd32, +		.wr32 = _nouveau_graph_context_wr32, +	}, +	.main  = gm107_grctx_generate_main, +	.mods  = gm107_grctx_generate_mods, +	.unkn  = nve4_grctx_generate_unkn, +	.hub   = gm107_grctx_pack_hub, +	.gpc   = gm107_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = gm107_grctx_pack_tpc, +	.ppc   = gm107_grctx_pack_ppc, +	.icmd  = gm107_grctx_pack_icmd, +	.mthd  = gm107_grctx_pack_mthd, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c new file mode 100644 index 00000000000..8de4a429154 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c @@ -0,0 +1,599 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include "ctxnvc0.h" + +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nv108_grctx_init_icmd_0[] = { +	{ 0x001000,   1, 0x01, 0x00000004 }, +	{ 0x000039,   3, 0x01, 0x00000000 }, +	{ 0x0000a9,   1, 0x01, 0x0000ffff }, +	{ 0x000038,   1, 0x01, 0x0fac6881 }, +	{ 0x00003d,   1, 0x01, 0x00000001 }, +	{ 0x0000e8,   8, 0x01, 0x00000400 }, +	{ 0x000078,   8, 0x01, 0x00000300 }, +	{ 0x000050,   1, 0x01, 0x00000011 }, +	{ 0x000058,   8, 0x01, 0x00000008 }, +	{ 0x000208,   8, 0x01, 0x00000001 }, +	{ 0x000081,   1, 0x01, 0x00000001 }, +	{ 0x000085,   1, 0x01, 0x00000004 }, +	{ 0x000088,   1, 0x01, 0x00000400 }, +	{ 0x000090,   1, 0x01, 0x00000300 }, +	{ 0x000098,   1, 0x01, 0x00001001 }, +	{ 0x0000e3,   1, 0x01, 0x00000001 }, +	{ 0x0000da,   1, 0x01, 0x00000001 }, +	{ 0x0000f8,   1, 0x01, 0x00000003 }, +	{ 0x0000fa,   1, 0x01, 0x00000001 }, +	{ 0x00009f,   4, 0x01, 0x0000ffff }, +	{ 0x0000b1,   1, 0x01, 0x00000001 }, +	{ 0x0000ad,   1, 0x01, 0x0000013e }, +	{ 0x0000e1,   1, 0x01, 0x00000010 }, +	{ 0x000290,  16, 0x01, 0x00000000 }, +	{ 0x0003b0,  16, 0x01, 0x00000000 }, +	{ 0x0002a0,  16, 0x01, 0x00000000 }, +	{ 0x000420,  16, 0x01, 0x00000000 }, +	{ 0x0002b0,  16, 0x01, 0x00000000 }, +	{ 0x000430,  16, 0x01, 0x00000000 }, +	{ 0x0002c0,  16, 0x01, 0x00000000 }, +	{ 0x0004d0,  16, 0x01, 0x00000000 }, +	{ 0x000720,  16, 0x01, 0x00000000 }, +	{ 0x0008c0,  16, 0x01, 0x00000000 }, +	{ 0x000890,  16, 0x01, 0x00000000 }, +	{ 0x0008e0,  16, 0x01, 0x00000000 }, +	{ 0x0008a0,  16, 0x01, 0x00000000 }, +	{ 0x0008f0,  16, 0x01, 0x00000000 }, +	{ 0x00094c,   1, 0x01, 0x000000ff }, +	{ 0x00094d,   1, 0x01, 0xffffffff }, +	{ 0x00094e,   1, 0x01, 0x00000002 }, +	{ 0x0002ec,   1, 0x01, 0x00000001 }, +	{ 0x0002f2,   2, 0x01, 0x00000001 }, +	{ 0x0002f5,   1, 0x01, 0x00000001 }, +	{ 0x0002f7,   1, 0x01, 0x00000001 }, +	{ 0x000303,   1, 0x01, 0x00000001 }, +	{ 0x0002e6,   1, 0x01, 0x00000001 }, +	{ 0x000466,   1, 0x01, 0x00000052 }, +	{ 0x000301,   1, 0x01, 0x3f800000 }, +	{ 0x000304,   1, 0x01, 0x30201000 }, +	{ 0x000305,   1, 0x01, 0x70605040 }, +	{ 0x000306,   1, 0x01, 0xb8a89888 }, +	{ 0x000307,   1, 0x01, 0xf8e8d8c8 }, +	{ 0x00030a,   1, 0x01, 0x00ffff00 }, +	{ 0x00030b,   1, 0x01, 0x0000001a }, +	{ 0x00030c,   1, 0x01, 0x00000001 }, +	{ 0x000318,   1, 0x01, 0x00000001 }, +	{ 0x000340,   1, 0x01, 0x00000000 }, +	{ 0x000375,   1, 0x01, 0x00000001 }, +	{ 0x00037d,   1, 0x01, 0x00000006 }, +	{ 0x0003a0,   1, 0x01, 0x00000002 }, +	{ 0x0003aa,   1, 0x01, 0x00000001 }, +	{ 0x0003a9,   1, 0x01, 0x00000001 }, +	{ 0x000380,   1, 0x01, 0x00000001 }, +	{ 0x000383,   1, 0x01, 0x00000011 }, +	{ 0x000360,   1, 0x01, 0x00000040 }, +	{ 0x000366,   2, 0x01, 0x00000000 }, +	{ 0x000368,   1, 0x01, 0x00000fff }, +	{ 0x000370,   2, 0x01, 0x00000000 }, +	{ 0x000372,   1, 0x01, 0x000fffff }, +	{ 0x00037a,   1, 0x01, 0x00000012 }, +	{ 0x000619,   1, 0x01, 0x00000003 }, +	{ 0x000811,   1, 0x01, 0x00000003 }, +	{ 0x000812,   1, 0x01, 0x00000004 }, +	{ 0x000813,   1, 0x01, 0x00000006 }, +	{ 0x000814,   1, 0x01, 0x00000008 }, +	{ 0x000815,   1, 0x01, 0x0000000b }, +	{ 0x000800,   6, 0x01, 0x00000001 }, +	{ 0x000632,   1, 0x01, 0x00000001 }, +	{ 0x000633,   1, 0x01, 0x00000002 }, +	{ 0x000634,   1, 0x01, 0x00000003 }, +	{ 0x000635,   1, 0x01, 0x00000004 }, +	{ 0x000654,   1, 0x01, 0x3f800000 }, +	{ 0x000657,   1, 0x01, 0x3f800000 }, +	{ 0x000655,   2, 0x01, 0x3f800000 }, +	{ 0x0006cd,   1, 0x01, 0x3f800000 }, +	{ 0x0007f5,   1, 0x01, 0x3f800000 }, +	{ 0x0007dc,   1, 0x01, 0x39291909 }, +	{ 0x0007dd,   1, 0x01, 0x79695949 }, +	{ 0x0007de,   1, 0x01, 0xb9a99989 }, +	{ 0x0007df,   1, 0x01, 0xf9e9d9c9 }, +	{ 0x0007e8,   1, 0x01, 0x00003210 }, +	{ 0x0007e9,   1, 0x01, 0x00007654 }, +	{ 0x0007ea,   1, 0x01, 0x00000098 }, +	{ 0x0007ec,   1, 0x01, 0x39291909 }, +	{ 0x0007ed,   1, 0x01, 0x79695949 }, +	{ 0x0007ee,   1, 0x01, 0xb9a99989 }, +	{ 0x0007ef,   1, 0x01, 0xf9e9d9c9 }, +	{ 0x0007f0,   1, 0x01, 0x00003210 }, +	{ 0x0007f1,   1, 0x01, 0x00007654 }, +	{ 0x0007f2,   1, 0x01, 0x00000098 }, +	{ 0x0005a5,   1, 0x01, 0x00000001 }, +	{ 0x000980, 128, 0x01, 0x00000000 }, +	{ 0x000468,   1, 0x01, 0x00000004 }, +	{ 0x00046c,   1, 0x01, 0x00000001 }, +	{ 0x000470,  96, 0x01, 0x00000000 }, +	{ 0x000510,  16, 0x01, 0x3f800000 }, +	{ 0x000520,   1, 0x01, 0x000002b6 }, +	{ 0x000529,   1, 0x01, 0x00000001 }, +	{ 0x000530,  16, 0x01, 0xffff0000 }, +	{ 0x000585,   1, 0x01, 0x0000003f }, +	{ 0x000576,   1, 0x01, 0x00000003 }, +	{ 0x00057b,   1, 0x01, 0x00000059 }, +	{ 0x000586,   1, 0x01, 0x00000040 }, +	{ 0x000582,   2, 0x01, 0x00000080 }, +	{ 0x0005c2,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 }, +	{ 0x00063a,   1, 0x01, 0x00000002 }, +	{ 0x00063b,   2, 0x01, 0x00000001 }, +	{ 0x00063d,   1, 0x01, 0x00000002 }, +	{ 0x00063e,   1, 0x01, 0x00000001 }, +	{ 0x0008b8,   8, 0x01, 0x00000001 }, +	{ 0x000900,   8, 0x01, 0x00000001 }, +	{ 0x000908,   8, 0x01, 0x00000002 }, +	{ 0x000910,  16, 0x01, 0x00000001 }, +	{ 0x000920,   8, 0x01, 0x00000002 }, +	{ 0x000928,   8, 0x01, 0x00000001 }, +	{ 0x000662,   1, 0x01, 0x00000001 }, +	{ 0x000648,   9, 0x01, 0x00000001 }, +	{ 0x000658,   1, 0x01, 0x0000000f }, +	{ 0x0007ff,   1, 0x01, 0x0000000a }, +	{ 0x00066a,   1, 0x01, 0x40000000 }, +	{ 0x00066b,   1, 0x01, 0x10000000 }, +	{ 0x00066c,   2, 0x01, 0xffff0000 }, +	{ 0x0007af,   2, 0x01, 0x00000008 }, +	{ 0x0007f6,   1, 0x01, 0x00000001 }, +	{ 0x00080b,   1, 0x01, 0x00000002 }, +	{ 0x0006b2,   1, 0x01, 0x00000055 }, +	{ 0x0007ad,   1, 0x01, 0x00000003 }, +	{ 0x000937,   1, 0x01, 0x00000001 }, +	{ 0x000971,   1, 0x01, 0x00000008 }, +	{ 0x000972,   1, 0x01, 0x00000040 }, +	{ 0x000973,   1, 0x01, 0x0000012c }, +	{ 0x00097c,   1, 0x01, 0x00000040 }, +	{ 0x000979,   1, 0x01, 0x00000003 }, +	{ 0x000975,   1, 0x01, 0x00000020 }, +	{ 0x000976,   1, 0x01, 0x00000001 }, +	{ 0x000977,   1, 0x01, 0x00000020 }, +	{ 0x000978,   1, 0x01, 0x00000001 }, +	{ 0x000957,   1, 0x01, 0x00000003 }, +	{ 0x00095e,   1, 0x01, 0x20164010 }, +	{ 0x00095f,   1, 0x01, 0x00000020 }, +	{ 0x000a0d,   1, 0x01, 0x00000006 }, +	{ 0x00097d,   1, 0x01, 0x00000020 }, +	{ 0x000683,   1, 0x01, 0x00000006 }, +	{ 0x000685,   1, 0x01, 0x003fffff }, +	{ 0x000687,   1, 0x01, 0x003fffff }, +	{ 0x0006a0,   1, 0x01, 0x00000005 }, +	{ 0x000840,   1, 0x01, 0x00400008 }, +	{ 0x000841,   1, 0x01, 0x08000080 }, +	{ 0x000842,   1, 0x01, 0x00400008 }, +	{ 0x000843,   1, 0x01, 0x08000080 }, +	{ 0x0006aa,   1, 0x01, 0x00000001 }, +	{ 0x0006ab,   1, 0x01, 0x00000002 }, +	{ 0x0006ac,   1, 0x01, 0x00000080 }, +	{ 0x0006ad,   2, 0x01, 0x00000100 }, +	{ 0x0006b1,   1, 0x01, 0x00000011 }, +	{ 0x0006bb,   1, 0x01, 0x000000cf }, +	{ 0x0006ce,   1, 0x01, 0x2a712488 }, +	{ 0x000739,   1, 0x01, 0x4085c000 }, +	{ 0x00073a,   1, 0x01, 0x00000080 }, +	{ 0x000786,   1, 0x01, 0x80000100 }, +	{ 0x00073c,   1, 0x01, 0x00010100 }, +	{ 0x00073d,   1, 0x01, 0x02800000 }, +	{ 0x000787,   1, 0x01, 0x000000cf }, +	{ 0x00078c,   1, 0x01, 0x00000008 }, +	{ 0x000792,   1, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 }, +	{ 0x000797,   1, 0x01, 0x000000cf }, +	{ 0x000836,   1, 0x01, 0x00000001 }, +	{ 0x00079a,   1, 0x01, 0x00000002 }, +	{ 0x000833,   1, 0x01, 0x04444480 }, +	{ 0x0007a1,   1, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 }, +	{ 0x000831,   1, 0x01, 0x00000004 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x000a04,   1, 0x01, 0x000000ff }, +	{ 0x000a0b,   1, 0x01, 0x00000040 }, +	{ 0x00097f,   1, 0x01, 0x00000100 }, +	{ 0x000a02,   1, 0x01, 0x00000001 }, +	{ 0x000809,   1, 0x01, 0x00000007 }, +	{ 0x00c221,   1, 0x01, 0x00000040 }, +	{ 0x00c1b0,   8, 0x01, 0x0000000f }, +	{ 0x00c1b8,   1, 0x01, 0x0fac6881 }, +	{ 0x00c1b9,   1, 0x01, 0x00fac688 }, +	{ 0x00c401,   1, 0x01, 0x00000001 }, +	{ 0x00c402,   1, 0x01, 0x00010001 }, +	{ 0x00c403,   2, 0x01, 0x00000001 }, +	{ 0x00c40e,   1, 0x01, 0x00000020 }, +	{ 0x00c500,   1, 0x01, 0x00000003 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000002 }, +	{ 0x0006aa,   1, 0x01, 0x00000001 }, +	{ 0x0006ad,   2, 0x01, 0x00000100 }, +	{ 0x0006b1,   1, 0x01, 0x00000011 }, +	{ 0x00078c,   1, 0x01, 0x00000008 }, +	{ 0x000792,   1, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 }, +	{ 0x000797,   1, 0x01, 0x000000cf }, +	{ 0x00079a,   1, 0x01, 0x00000002 }, +	{ 0x0007a1,   1, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 }, +	{ 0x000831,   1, 0x01, 0x00000004 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000008 }, +	{ 0x000039,   3, 0x01, 0x00000000 }, +	{ 0x000380,   1, 0x01, 0x00000001 }, +	{ 0x000366,   2, 0x01, 0x00000000 }, +	{ 0x000368,   1, 0x01, 0x00000fff }, +	{ 0x000370,   2, 0x01, 0x00000000 }, +	{ 0x000372,   1, 0x01, 0x000fffff }, +	{ 0x000813,   1, 0x01, 0x00000006 }, +	{ 0x000814,   1, 0x01, 0x00000008 }, +	{ 0x000957,   1, 0x01, 0x00000003 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x000a04,   1, 0x01, 0x000000ff }, +	{ 0x000a0b,   1, 0x01, 0x00000040 }, +	{ 0x00097f,   1, 0x01, 0x00000100 }, +	{ 0x000a02,   1, 0x01, 0x00000001 }, +	{ 0x000809,   1, 0x01, 0x00000007 }, +	{ 0x00c221,   1, 0x01, 0x00000040 }, +	{ 0x00c401,   1, 0x01, 0x00000001 }, +	{ 0x00c402,   1, 0x01, 0x00010001 }, +	{ 0x00c403,   2, 0x01, 0x00000001 }, +	{ 0x00c40e,   1, 0x01, 0x00000020 }, +	{ 0x00c500,   1, 0x01, 0x00000003 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000001 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{} +}; + +static const struct nvc0_graph_pack +nv108_grctx_pack_icmd[] = { +	{ nv108_grctx_init_icmd_0 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_fe_0[] = { +	{ 0x404004,   8, 0x04, 0x00000000 }, +	{ 0x404024,   1, 0x04, 0x0000e000 }, +	{ 0x404028,   8, 0x04, 0x00000000 }, +	{ 0x4040a8,   8, 0x04, 0x00000000 }, +	{ 0x4040c8,   1, 0x04, 0xf800008f }, +	{ 0x4040d0,   6, 0x04, 0x00000000 }, +	{ 0x4040e8,   1, 0x04, 0x00001000 }, +	{ 0x4040f8,   1, 0x04, 0x00000000 }, +	{ 0x404100,  10, 0x04, 0x00000000 }, +	{ 0x404130,   2, 0x04, 0x00000000 }, +	{ 0x404138,   1, 0x04, 0x20000040 }, +	{ 0x404150,   1, 0x04, 0x0000002e }, +	{ 0x404154,   1, 0x04, 0x00000400 }, +	{ 0x404158,   1, 0x04, 0x00000200 }, +	{ 0x404164,   1, 0x04, 0x00000055 }, +	{ 0x40417c,   2, 0x04, 0x00000000 }, +	{ 0x404194,   1, 0x04, 0x01000700 }, +	{ 0x4041a0,   4, 0x04, 0x00000000 }, +	{ 0x404200,   1, 0x04, 0x0000a197 }, +	{ 0x404204,   1, 0x04, 0x0000a1c0 }, +	{ 0x404208,   1, 0x04, 0x0000a140 }, +	{ 0x40420c,   1, 0x04, 0x0000902d }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_ds_0[] = { +	{ 0x405800,   1, 0x04, 0x0f8000bf }, +	{ 0x405830,   1, 0x04, 0x02180648 }, +	{ 0x405834,   1, 0x04, 0x08000000 }, +	{ 0x405838,   1, 0x04, 0x00000000 }, +	{ 0x405854,   1, 0x04, 0x00000000 }, +	{ 0x405870,   4, 0x04, 0x00000001 }, +	{ 0x405a00,   2, 0x04, 0x00000000 }, +	{ 0x405a18,   1, 0x04, 0x00000000 }, +	{ 0x405a1c,   1, 0x04, 0x000000ff }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_pd_0[] = { +	{ 0x406020,   1, 0x04, 0x034103c1 }, +	{ 0x406028,   4, 0x04, 0x00000001 }, +	{ 0x4064a8,   1, 0x04, 0x00000000 }, +	{ 0x4064ac,   1, 0x04, 0x00003fff }, +	{ 0x4064b0,   3, 0x04, 0x00000000 }, +	{ 0x4064c0,   1, 0x04, 0x802000f0 }, +	{ 0x4064c4,   1, 0x04, 0x0192ffff }, +	{ 0x4064c8,   1, 0x04, 0x00c20200 }, +	{ 0x4064cc,   9, 0x04, 0x00000000 }, +	{ 0x4064fc,   1, 0x04, 0x0000022a }, +	{} +}; + +const struct nvc0_graph_init +nv108_grctx_init_rstr2d_0[] = { +	{ 0x407804,   1, 0x04, 0x00000063 }, +	{ 0x40780c,   1, 0x04, 0x0a418820 }, +	{ 0x407810,   1, 0x04, 0x062080e6 }, +	{ 0x407814,   1, 0x04, 0x020398a4 }, +	{ 0x407818,   1, 0x04, 0x0e629062 }, +	{ 0x40781c,   1, 0x04, 0x0a418820 }, +	{ 0x407820,   1, 0x04, 0x000000e6 }, +	{ 0x4078bc,   1, 0x04, 0x00000103 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_be_0[] = { +	{ 0x408800,   1, 0x04, 0x32802a3c }, +	{ 0x408804,   1, 0x04, 0x00000040 }, +	{ 0x408808,   1, 0x04, 0x1003e005 }, +	{ 0x408840,   1, 0x04, 0x0000000b }, +	{ 0x408900,   1, 0x04, 0xb080b801 }, +	{ 0x408904,   1, 0x04, 0x62000001 }, +	{ 0x408908,   1, 0x04, 0x02c8102f }, +	{ 0x408980,   1, 0x04, 0x0000011d }, +	{} +}; + +static const struct nvc0_graph_pack +nv108_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nv108_grctx_init_fe_0 }, +	{ nvf0_grctx_init_pri_0 }, +	{ nve4_grctx_init_memfmt_0 }, +	{ nv108_grctx_init_ds_0 }, +	{ nvf0_grctx_init_cwd_0 }, +	{ nv108_grctx_init_pd_0 }, +	{ nv108_grctx_init_rstr2d_0 }, +	{ nve4_grctx_init_scc_0 }, +	{ nv108_grctx_init_be_0 }, +	{} +}; + +const struct nvc0_graph_init +nv108_grctx_init_prop_0[] = { +	{ 0x418400,   1, 0x04, 0x38005e00 }, +	{ 0x418404,   1, 0x04, 0x71e0ffff }, +	{ 0x41840c,   1, 0x04, 0x00001008 }, +	{ 0x418410,   1, 0x04, 0x0fff0fff }, +	{ 0x418414,   1, 0x04, 0x02200fff }, +	{ 0x418450,   6, 0x04, 0x00000000 }, +	{ 0x418468,   1, 0x04, 0x00000001 }, +	{ 0x41846c,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_gpc_unk_1[] = { +	{ 0x418600,   1, 0x04, 0x0000007f }, +	{ 0x418684,   1, 0x04, 0x0000001f }, +	{ 0x418700,   1, 0x04, 0x00000002 }, +	{ 0x418704,   2, 0x04, 0x00000080 }, +	{ 0x41870c,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_setup_0[] = { +	{ 0x418800,   1, 0x04, 0x7006863a }, +	{ 0x418808,   1, 0x04, 0x00000000 }, +	{ 0x41880c,   1, 0x04, 0x00000030 }, +	{ 0x418810,   1, 0x04, 0x00000000 }, +	{ 0x418828,   1, 0x04, 0x00000044 }, +	{ 0x418830,   1, 0x04, 0x10000001 }, +	{ 0x4188d8,   1, 0x04, 0x00000008 }, +	{ 0x4188e0,   1, 0x04, 0x01000000 }, +	{ 0x4188e8,   5, 0x04, 0x00000000 }, +	{ 0x4188fc,   1, 0x04, 0x20100058 }, +	{} +}; + +const struct nvc0_graph_init +nv108_grctx_init_crstr_0[] = { +	{ 0x418b00,   1, 0x04, 0x0000001e }, +	{ 0x418b08,   1, 0x04, 0x0a418820 }, +	{ 0x418b0c,   1, 0x04, 0x062080e6 }, +	{ 0x418b10,   1, 0x04, 0x020398a4 }, +	{ 0x418b14,   1, 0x04, 0x0e629062 }, +	{ 0x418b18,   1, 0x04, 0x0a418820 }, +	{ 0x418b1c,   1, 0x04, 0x000000e6 }, +	{ 0x418bb8,   1, 0x04, 0x00000103 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_gpm_0[] = { +	{ 0x418c08,   1, 0x04, 0x00000001 }, +	{ 0x418c10,   8, 0x04, 0x00000000 }, +	{ 0x418c40,   1, 0x04, 0xffffffff }, +	{ 0x418c6c,   1, 0x04, 0x00000001 }, +	{ 0x418c80,   1, 0x04, 0x2020000c }, +	{ 0x418c8c,   1, 0x04, 0x00000001 }, +	{} +}; + +static const struct nvc0_graph_pack +nv108_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nv108_grctx_init_prop_0 }, +	{ nv108_grctx_init_gpc_unk_1 }, +	{ nv108_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nv108_grctx_init_crstr_0 }, +	{ nv108_grctx_init_gpm_0 }, +	{ nvf0_grctx_init_gpc_unk_2 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_tex_0[] = { +	{ 0x419a00,   1, 0x04, 0x000100f0 }, +	{ 0x419a04,   1, 0x04, 0x00000001 }, +	{ 0x419a08,   1, 0x04, 0x00000421 }, +	{ 0x419a0c,   1, 0x04, 0x00120000 }, +	{ 0x419a10,   1, 0x04, 0x00000000 }, +	{ 0x419a14,   1, 0x04, 0x00000200 }, +	{ 0x419a1c,   1, 0x04, 0x0000c000 }, +	{ 0x419a20,   1, 0x04, 0x00000800 }, +	{ 0x419a30,   1, 0x04, 0x00000001 }, +	{ 0x419ac4,   1, 0x04, 0x0037f440 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_sm_0[] = { +	{ 0x419e04,   1, 0x04, 0x00000000 }, +	{ 0x419e08,   1, 0x04, 0x0000001d }, +	{ 0x419e0c,   1, 0x04, 0x00000000 }, +	{ 0x419e10,   1, 0x04, 0x00001c02 }, +	{ 0x419e44,   1, 0x04, 0x0013eff2 }, +	{ 0x419e48,   1, 0x04, 0x00000000 }, +	{ 0x419e4c,   1, 0x04, 0x0000007f }, +	{ 0x419e50,   2, 0x04, 0x00000000 }, +	{ 0x419e58,   1, 0x04, 0x00000001 }, +	{ 0x419e5c,   3, 0x04, 0x00000000 }, +	{ 0x419e68,   1, 0x04, 0x00000002 }, +	{ 0x419e6c,  12, 0x04, 0x00000000 }, +	{ 0x419eac,   1, 0x04, 0x00001f8f }, +	{ 0x419eb0,   1, 0x04, 0x0db00d2f }, +	{ 0x419eb8,   1, 0x04, 0x00000000 }, +	{ 0x419ec8,   1, 0x04, 0x0001304f }, +	{ 0x419f30,   4, 0x04, 0x00000000 }, +	{ 0x419f40,   1, 0x04, 0x00000018 }, +	{ 0x419f44,   3, 0x04, 0x00000000 }, +	{ 0x419f58,   1, 0x04, 0x00000020 }, +	{ 0x419f70,   1, 0x04, 0x00000000 }, +	{ 0x419f78,   1, 0x04, 0x000001eb }, +	{ 0x419f7c,   1, 0x04, 0x00000404 }, +	{} +}; + +static const struct nvc0_graph_pack +nv108_grctx_pack_tpc[] = { +	{ nvd7_grctx_init_pe_0 }, +	{ nv108_grctx_init_tex_0 }, +	{ nvf0_grctx_init_mpc_0 }, +	{ nvf0_grctx_init_l1c_0 }, +	{ nv108_grctx_init_sm_0 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_grctx_init_cbm_0[] = { +	{ 0x41bec0,   1, 0x04, 0x10000000 }, +	{ 0x41bec4,   1, 0x04, 0x00037f7f }, +	{ 0x41bee4,   1, 0x04, 0x00000000 }, +	{ 0x41bef0,   1, 0x04, 0x000003ff }, +	{} +}; + +static const struct nvc0_graph_pack +nv108_grctx_pack_ppc[] = { +	{ nve4_grctx_init_pes_0 }, +	{ nv108_grctx_init_cbm_0 }, +	{ nvd7_grctx_init_wwdx_0 }, +	{} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ + +static void +nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) +{ +	u32 magic[GPC_MAX][2]; +	u32 offset; +	int gpc; + +	mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); +	mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); +	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); +	mmio_list(0x40800c, 0x00000000,  8, 1); +	mmio_list(0x408010, 0x80000000,  0, 0); +	mmio_list(0x419004, 0x00000000,  8, 1); +	mmio_list(0x419008, 0x00000000,  0, 0); +	mmio_list(0x4064cc, 0x80000000,  0, 0); +	mmio_list(0x408004, 0x00000000,  8, 0); +	mmio_list(0x408008, 0x80000030,  0, 0); +	mmio_list(0x418808, 0x00000000,  8, 0); +	mmio_list(0x41880c, 0x80000030,  0, 0); +	mmio_list(0x4064c8, 0x00c20200,  0, 0); +	mmio_list(0x418810, 0x80000000, 12, 2); +	mmio_list(0x419848, 0x10000000, 12, 2); + +	mmio_list(0x405830, 0x02180648,  0, 0); +	mmio_list(0x4064c4, 0x0192ffff,  0, 0); + +	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) { +		u16 magic0 = 0x0218 * priv->tpc_nr[gpc]; +		u16 magic1 = 0x0648 * priv->tpc_nr[gpc]; +		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset; +		magic[gpc][1]  = 0x00000000 | (magic1 << 16); +		offset += 0x0324 * priv->tpc_nr[gpc]; +	} + +	for (gpc = 0; gpc < priv->gpc_nr; gpc++) { +		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0); +		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0); +		offset += 0x07ff * priv->tpc_nr[gpc]; +	} + +	mmio_list(0x17e91c, 0x0b040a0b, 0, 0); +	mmio_list(0x17e920, 0x00090d08, 0, 0); +} + +struct nouveau_oclass * +nv108_grctx_oclass = &(struct nvc0_grctx_oclass) { +	.base.handle = NV_ENGCTX(GR, 0x08), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_graph_context_ctor, +		.dtor = nvc0_graph_context_dtor, +		.init = _nouveau_graph_context_init, +		.fini = _nouveau_graph_context_fini, +		.rd32 = _nouveau_graph_context_rd32, +		.wr32 = _nouveau_graph_context_wr32, +	}, +	.main  = nve4_grctx_generate_main, +	.mods  = nv108_grctx_generate_mods, +	.unkn  = nve4_grctx_generate_unkn, +	.hub   = nv108_grctx_pack_hub, +	.gpc   = nv108_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nv108_grctx_pack_tpc, +	.ppc   = nv108_grctx_pack_ppc, +	.icmd  = nv108_grctx_pack_icmd, +	.mthd  = nvf0_grctx_pack_mthd, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index 64dca260912..833a96508c4 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -22,10 +22,14 @@   * Authors: Ben Skeggs   */ -#include "nvc0.h" +#include "ctxnvc0.h" -struct nvc0_graph_init -nvc0_grctx_init_icmd[] = { +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nvc0_grctx_init_icmd_0[] = {  	{ 0x001000,   1, 0x01, 0x00000004 },  	{ 0x0000a9,   1, 0x01, 0x0000ffff },  	{ 0x000038,   1, 0x01, 0x0fac6881 }, @@ -140,8 +144,7 @@ nvc0_grctx_init_icmd[] = {  	{ 0x000586,   1, 0x01, 0x00000040 },  	{ 0x000582,   2, 0x01, 0x00000080 },  	{ 0x0005c2,   1, 0x01, 0x00000001 }, -	{ 0x000638,   1, 0x01, 0x00000001 }, -	{ 0x000639,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 },  	{ 0x00063a,   1, 0x01, 0x00000002 },  	{ 0x00063b,   2, 0x01, 0x00000001 },  	{ 0x00063d,   1, 0x01, 0x00000002 }, @@ -201,15 +204,13 @@ nvc0_grctx_init_icmd[] = {  	{ 0x000787,   1, 0x01, 0x000000cf },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x000836,   1, 0x01, 0x00000001 },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x00080c,   1, 0x01, 0x00000002 },  	{ 0x00080d,   2, 0x01, 0x00000100 }, @@ -235,14 +236,12 @@ nvc0_grctx_init_icmd[] = {  	{ 0x0006b1,   1, 0x01, 0x00000011 },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x01e100,   1, 0x01, 0x00000001 },  	{ 0x001000,   1, 0x01, 0x00000014 }, @@ -267,8 +266,14 @@ nvc0_grctx_init_icmd[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_9097[] = { +const struct nvc0_graph_pack +nvc0_grctx_pack_icmd[] = { +	{ nvc0_grctx_init_icmd_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_grctx_init_9097_0[] = {  	{ 0x000800,   8, 0x40, 0x00000000 },  	{ 0x000804,   8, 0x40, 0x00000000 },  	{ 0x000808,   8, 0x40, 0x00000400 }, @@ -516,8 +521,7 @@ nvc0_grctx_init_9097[] = {  	{ 0x001350,   1, 0x04, 0x00000002 },  	{ 0x001358,   1, 0x04, 0x00000001 },  	{ 0x0012e4,   1, 0x04, 0x00000000 }, -	{ 0x00131c,   1, 0x04, 0x00000000 }, -	{ 0x001320,   3, 0x04, 0x00000000 }, +	{ 0x00131c,   4, 0x04, 0x00000000 },  	{ 0x0019c0,   1, 0x04, 0x00000000 },  	{ 0x001140,   1, 0x04, 0x00000000 },  	{ 0x0019c4,   1, 0x04, 0x00000000 }, @@ -571,8 +575,8 @@ nvc0_grctx_init_9097[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_902d[] = { +const struct nvc0_graph_init +nvc0_grctx_init_902d_0[] = {  	{ 0x000200,   1, 0x04, 0x000000cf },  	{ 0x000204,   1, 0x04, 0x00000001 },  	{ 0x000208,   1, 0x04, 0x00000020 }, @@ -590,8 +594,8 @@ nvc0_grctx_init_902d[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_9039[] = { +const struct nvc0_graph_init +nvc0_grctx_init_9039_0[] = {  	{ 0x00030c,   3, 0x04, 0x00000000 },  	{ 0x000320,   1, 0x04, 0x00000000 },  	{ 0x000238,   2, 0x04, 0x00000000 }, @@ -599,8 +603,8 @@ nvc0_grctx_init_9039[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_90c0[] = { +const struct nvc0_graph_init +nvc0_grctx_init_90c0_0[] = {  	{ 0x00270c,   8, 0x20, 0x00000000 },  	{ 0x00030c,   1, 0x04, 0x00000001 },  	{ 0x001944,   1, 0x04, 0x00000000 }, @@ -617,38 +621,44 @@ nvc0_grctx_init_90c0[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_base[] = { +const struct nvc0_graph_pack +nvc0_grctx_pack_mthd[] = { +	{ nvc0_grctx_init_9097_0, 0x9097 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{ nvc0_grctx_init_9039_0, 0x9039 }, +	{ nvc0_grctx_init_90c0_0, 0x90c0 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_main_0[] = {  	{ 0x400204,   2, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk40xx[] = { -	{ 0x404004,  10, 0x04, 0x00000000 }, +const struct nvc0_graph_init +nvc0_grctx_init_fe_0[] = { +	{ 0x404004,  11, 0x04, 0x00000000 },  	{ 0x404044,   1, 0x04, 0x00000000 }, -	{ 0x404094,   1, 0x04, 0x00000000 }, -	{ 0x404098,  12, 0x04, 0x00000000 }, +	{ 0x404094,  13, 0x04, 0x00000000 },  	{ 0x4040c8,   1, 0x04, 0xf0000087 },  	{ 0x4040d0,   6, 0x04, 0x00000000 },  	{ 0x4040e8,   1, 0x04, 0x00001000 },  	{ 0x4040f8,   1, 0x04, 0x00000000 }, -	{ 0x404130,   1, 0x04, 0x00000000 }, -	{ 0x404134,   1, 0x04, 0x00000000 }, +	{ 0x404130,   2, 0x04, 0x00000000 },  	{ 0x404138,   1, 0x04, 0x20000040 },  	{ 0x404150,   1, 0x04, 0x0000002e },  	{ 0x404154,   1, 0x04, 0x00000400 },  	{ 0x404158,   1, 0x04, 0x00000200 },  	{ 0x404164,   1, 0x04, 0x00000055 },  	{ 0x404168,   1, 0x04, 0x00000000 }, -	{ 0x404174,   1, 0x04, 0x00000000 }, -	{ 0x404178,   2, 0x04, 0x00000000 }, +	{ 0x404174,   3, 0x04, 0x00000000 },  	{ 0x404200,   8, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk44xx[] = { +const struct nvc0_graph_init +nvc0_grctx_init_pri_0[] = {  	{ 0x404404,  14, 0x04, 0x00000000 },  	{ 0x404460,   2, 0x04, 0x00000000 },  	{ 0x404468,   1, 0x04, 0x00ffffff }, @@ -658,8 +668,8 @@ nvc0_grctx_init_unk44xx[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk46xx[] = { +const struct nvc0_graph_init +nvc0_grctx_init_memfmt_0[] = {  	{ 0x404604,   1, 0x04, 0x00000015 },  	{ 0x404608,   1, 0x04, 0x00000000 },  	{ 0x40460c,   1, 0x04, 0x00002e00 }, @@ -674,19 +684,14 @@ nvc0_grctx_init_unk46xx[] = {  	{ 0x4046a0,   1, 0x04, 0x007f0080 },  	{ 0x4046a4,  18, 0x04, 0x00000000 },  	{ 0x4046f0,   2, 0x04, 0x00000000 }, -	{} -}; - -struct nvc0_graph_init -nvc0_grctx_init_unk47xx[] = {  	{ 0x404700,  13, 0x04, 0x00000000 },  	{ 0x404734,   1, 0x04, 0x00000100 },  	{ 0x404738,   8, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk58xx[] = { +static const struct nvc0_graph_init +nvc0_grctx_init_ds_0[] = {  	{ 0x405800,   1, 0x04, 0x078000bf },  	{ 0x405830,   1, 0x04, 0x02180000 },  	{ 0x405834,   2, 0x04, 0x00000000 }, @@ -697,23 +702,18 @@ nvc0_grctx_init_unk58xx[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk60xx[] = { +static const struct nvc0_graph_init +nvc0_grctx_init_pd_0[] = {  	{ 0x406020,   1, 0x04, 0x000103c1 },  	{ 0x406028,   4, 0x04, 0x00000001 }, -	{} -}; - -struct nvc0_graph_init -nvc0_grctx_init_unk64xx[] = {  	{ 0x4064a8,   1, 0x04, 0x00000000 },  	{ 0x4064ac,   1, 0x04, 0x00003fff },  	{ 0x4064b4,   2, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk78xx[] = { +const struct nvc0_graph_init +nvc0_grctx_init_rstr2d_0[] = {  	{ 0x407804,   1, 0x04, 0x00000023 },  	{ 0x40780c,   1, 0x04, 0x0a418820 },  	{ 0x407810,   1, 0x04, 0x062080e6 }, @@ -725,8 +725,8 @@ nvc0_grctx_init_unk78xx[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_unk80xx[] = { +const struct nvc0_graph_init +nvc0_grctx_init_scc_0[] = {  	{ 0x408000,   2, 0x04, 0x00000000 },  	{ 0x408008,   1, 0x04, 0x00000018 },  	{ 0x40800c,   2, 0x04, 0x00000000 }, @@ -736,8 +736,8 @@ nvc0_grctx_init_unk80xx[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_rop[] = { +static const struct nvc0_graph_init +nvc0_grctx_init_be_0[] = {  	{ 0x408800,   1, 0x04, 0x02802a3c },  	{ 0x408804,   1, 0x04, 0x00000040 },  	{ 0x408808,   1, 0x04, 0x0003e00d }, @@ -748,9 +748,28 @@ nvc0_grctx_init_rop[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_gpc_0[] = { +const struct nvc0_graph_pack +nvc0_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nvc0_grctx_init_fe_0 }, +	{ nvc0_grctx_init_pri_0 }, +	{ nvc0_grctx_init_memfmt_0 }, +	{ nvc0_grctx_init_ds_0 }, +	{ nvc0_grctx_init_pd_0 }, +	{ nvc0_grctx_init_rstr2d_0 }, +	{ nvc0_grctx_init_scc_0 }, +	{ nvc0_grctx_init_be_0 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_gpc_unk_0[] = {  	{ 0x418380,   1, 0x04, 0x00000016 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_prop_0[] = {  	{ 0x418400,   1, 0x04, 0x38004e00 },  	{ 0x418404,   1, 0x04, 0x71e0ffff },  	{ 0x418408,   1, 0x04, 0x00000000 }, @@ -760,6 +779,11 @@ nvc0_grctx_init_gpc_0[] = {  	{ 0x418450,   6, 0x04, 0x00000000 },  	{ 0x418468,   1, 0x04, 0x00000001 },  	{ 0x41846c,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_gpc_unk_1[] = {  	{ 0x418600,   1, 0x04, 0x0000001f },  	{ 0x418684,   1, 0x04, 0x0000000f },  	{ 0x418700,   1, 0x04, 0x00000002 }, @@ -767,6 +791,11 @@ nvc0_grctx_init_gpc_0[] = {  	{ 0x418708,   1, 0x04, 0x00000000 },  	{ 0x41870c,   1, 0x04, 0x07c80000 },  	{ 0x418710,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_grctx_init_setup_0[] = {  	{ 0x418800,   1, 0x04, 0x0006860a },  	{ 0x418808,   3, 0x04, 0x00000000 },  	{ 0x418828,   1, 0x04, 0x00008442 }, @@ -775,10 +804,20 @@ nvc0_grctx_init_gpc_0[] = {  	{ 0x4188e0,   1, 0x04, 0x01000000 },  	{ 0x4188e8,   5, 0x04, 0x00000000 },  	{ 0x4188fc,   1, 0x04, 0x00100000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_zcull_0[] = {  	{ 0x41891c,   1, 0x04, 0x00ff00ff },  	{ 0x418924,   1, 0x04, 0x00000000 },  	{ 0x418928,   1, 0x04, 0x00ffff00 },  	{ 0x41892c,   1, 0x04, 0x0000ff00 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_crstr_0[] = {  	{ 0x418b00,   1, 0x04, 0x00000000 },  	{ 0x418b08,   1, 0x04, 0x0a418820 },  	{ 0x418b0c,   1, 0x04, 0x062080e6 }, @@ -787,18 +826,41 @@ nvc0_grctx_init_gpc_0[] = {  	{ 0x418b18,   1, 0x04, 0x0a418820 },  	{ 0x418b1c,   1, 0x04, 0x000000e6 },  	{ 0x418bb8,   1, 0x04, 0x00000103 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_gpm_0[] = {  	{ 0x418c08,   1, 0x04, 0x00000001 },  	{ 0x418c10,   8, 0x04, 0x00000000 },  	{ 0x418c80,   1, 0x04, 0x20200004 },  	{ 0x418c8c,   1, 0x04, 0x00000001 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_gcc_0[] = {  	{ 0x419000,   1, 0x04, 0x00000780 },  	{ 0x419004,   2, 0x04, 0x00000000 },  	{ 0x419014,   1, 0x04, 0x00000004 },  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_gpc_1[] = { +const struct nvc0_graph_pack +nvc0_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvc0_grctx_init_prop_0 }, +	{ nvc0_grctx_init_gpc_unk_1 }, +	{ nvc0_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvc0_grctx_init_crstr_0 }, +	{ nvc0_grctx_init_gpm_0 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_grctx_init_zcullr_0[] = {  	{ 0x418a00,   3, 0x04, 0x00000000 },  	{ 0x418a0c,   1, 0x04, 0x00010000 },  	{ 0x418a10,   3, 0x04, 0x00000000 }, @@ -826,19 +888,35 @@ nvc0_grctx_init_gpc_1[] = {  	{}  }; -struct nvc0_graph_init -nvc0_grctx_init_tpc[] = { +const struct nvc0_graph_pack +nvc0_grctx_pack_zcull[] = { +	{ nvc0_grctx_init_zcullr_0 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_pe_0[] = {  	{ 0x419818,   1, 0x04, 0x00000000 },  	{ 0x41983c,   1, 0x04, 0x00038bc7 },  	{ 0x419848,   1, 0x04, 0x00000000 },  	{ 0x419864,   1, 0x04, 0x0000012a },  	{ 0x419888,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_grctx_init_tex_0[] = {  	{ 0x419a00,   1, 0x04, 0x000001f0 },  	{ 0x419a04,   1, 0x04, 0x00000001 },  	{ 0x419a08,   1, 0x04, 0x00000023 },  	{ 0x419a0c,   1, 0x04, 0x00020000 },  	{ 0x419a10,   1, 0x04, 0x00000000 },  	{ 0x419a14,   1, 0x04, 0x00000200 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_wwdx_0[] = {  	{ 0x419b00,   1, 0x04, 0x0a418820 },  	{ 0x419b04,   1, 0x04, 0x062080e6 },  	{ 0x419b08,   1, 0x04, 0x020398a4 }, @@ -848,15 +926,35 @@ nvc0_grctx_init_tpc[] = {  	{ 0x419bd0,   1, 0x04, 0x00900103 },  	{ 0x419be0,   1, 0x04, 0x00000001 },  	{ 0x419be4,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_mpc_0[] = {  	{ 0x419c00,   1, 0x04, 0x00000002 },  	{ 0x419c04,   1, 0x04, 0x00000006 },  	{ 0x419c08,   1, 0x04, 0x00000002 },  	{ 0x419c20,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_grctx_init_l1c_0[] = {  	{ 0x419cb0,   1, 0x04, 0x00060048 },  	{ 0x419ce8,   1, 0x04, 0x00000000 },  	{ 0x419cf4,   1, 0x04, 0x00000183 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_grctx_init_tpccs_0[] = {  	{ 0x419d20,   1, 0x04, 0x02180000 },  	{ 0x419d24,   1, 0x04, 0x00001fff }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_grctx_init_sm_0[] = {  	{ 0x419e04,   3, 0x04, 0x00000000 },  	{ 0x419e10,   1, 0x04, 0x00000002 },  	{ 0x419e44,   1, 0x04, 0x001beff2 }, @@ -868,6 +966,22 @@ nvc0_grctx_init_tpc[] = {  	{}  }; +const struct nvc0_graph_pack +nvc0_grctx_pack_tpc[] = { +	{ nvc0_grctx_init_pe_0 }, +	{ nvc0_grctx_init_tex_0 }, +	{ nvc0_grctx_init_wwdx_0 }, +	{ nvc0_grctx_init_mpc_0 }, +	{ nvc0_grctx_init_l1c_0 }, +	{ nvc0_grctx_init_tpccs_0 }, +	{ nvc0_grctx_init_sm_0 }, +	{} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ +  void  nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  { @@ -1039,7 +1153,7 @@ nvc0_grctx_generate_r406800(struct nvc0_graph_priv *priv)  			} while (!tpcnr[gpc]);  			tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; -			tpc_set |= 1 << ((gpc * 8) + tpc); +			tpc_set |= 1ULL << ((gpc * 8) + tpc);  		}  		nv_wr32(priv, 0x406800 + (i * 0x20), lower_32_bits(tpc_set)); @@ -1055,14 +1169,14 @@ void  nvc0_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  {  	struct nvc0_grctx_oclass *oclass = (void *)nv_engine(priv)->cclass; -	int i;  	nv_mask(priv, 0x000260, 0x00000001, 0x00000000); -	for (i = 0; oclass->hub[i]; i++) -		nvc0_graph_mmio(priv, oclass->hub[i]); -	for (i = 0; oclass->gpc[i]; i++) -		nvc0_graph_mmio(priv, oclass->gpc[i]); +	nvc0_graph_mmio(priv, oclass->hub); +	nvc0_graph_mmio(priv, oclass->gpc); +	nvc0_graph_mmio(priv, oclass->zcull); +	nvc0_graph_mmio(priv, oclass->tpc); +	nvc0_graph_mmio(priv, oclass->ppc);  	nv_wr32(priv, 0x404154, 0x00000000); @@ -1182,46 +1296,6 @@ done:  	return ret;  } -struct nvc0_graph_init * -nvc0_grctx_init_hub[] = { -	nvc0_grctx_init_base, -	nvc0_grctx_init_unk40xx, -	nvc0_grctx_init_unk44xx, -	nvc0_grctx_init_unk46xx, -	nvc0_grctx_init_unk47xx, -	nvc0_grctx_init_unk58xx, -	nvc0_grctx_init_unk60xx, -	nvc0_grctx_init_unk64xx, -	nvc0_grctx_init_unk78xx, -	nvc0_grctx_init_unk80xx, -	nvc0_grctx_init_rop, -	NULL -}; - -static struct nvc0_graph_init * -nvc0_grctx_init_gpc[] = { -	nvc0_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvc0_grctx_init_tpc, -	NULL -}; - -struct nvc0_graph_init -nvc0_grctx_init_mthd_magic[] = { -	{ 0x3410, 1, 0x04, 0x00000000 }, -	{} -}; - -struct nvc0_graph_mthd -nvc0_grctx_init_mthd[] = { -	{ 0x9097, nvc0_grctx_init_9097, }, -	{ 0x902d, nvc0_grctx_init_902d, }, -	{ 0x9039, nvc0_grctx_init_9039, }, -	{ 0x90c0, nvc0_grctx_init_90c0, }, -	{ 0x902d, nvc0_grctx_init_mthd_magic, }, -	{} -}; -  struct nouveau_oclass *  nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xc0), @@ -1233,11 +1307,13 @@ nvc0_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nvc0_grctx_generate_main, -	.mods = nvc0_grctx_generate_mods, -	.unkn = nvc0_grctx_generate_unkn, -	.hub  = nvc0_grctx_init_hub, -	.gpc  = nvc0_grctx_init_gpc, -	.icmd = nvc0_grctx_init_icmd, -	.mthd = nvc0_grctx_init_mthd, +	.main  = nvc0_grctx_generate_main, +	.mods  = nvc0_grctx_generate_mods, +	.unkn  = nvc0_grctx_generate_unkn, +	.hub   = nvc0_grctx_pack_hub, +	.gpc   = nvc0_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvc0_grctx_pack_tpc, +	.icmd  = nvc0_grctx_pack_icmd, +	.mthd  = nvc0_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h new file mode 100644 index 00000000000..8da8b627b9d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h @@ -0,0 +1,179 @@ +#ifndef __NVKM_GRCTX_NVC0_H__ +#define __NVKM_GRCTX_NVC0_H__ + +#include "nvc0.h" + +struct nvc0_grctx { +	struct nvc0_graph_priv *priv; +	struct nvc0_graph_data *data; +	struct nvc0_graph_mmio *mmio; +	int buffer_nr; +	u64 buffer[4]; +	u64 addr; +}; + +struct nvc0_grctx_oclass { +	struct nouveau_oclass base; +	/* main context generation function */ +	void  (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *); +	/* context-specific modify-on-first-load list generation function */ +	void  (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *); +	void  (*unkn)(struct nvc0_graph_priv *); +	/* mmio context data */ +	const struct nvc0_graph_pack *hub; +	const struct nvc0_graph_pack *gpc; +	const struct nvc0_graph_pack *zcull; +	const struct nvc0_graph_pack *tpc; +	const struct nvc0_graph_pack *ppc; +	/* indirect context data, generated with icmds/mthds */ +	const struct nvc0_graph_pack *icmd; +	const struct nvc0_graph_pack *mthd; +}; + +#define mmio_data(s,a,p) do {                                                  \ +	info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \ +	info->addr = info->buffer[info->buffer_nr++] + (s);                    \ +	info->data->size = (s);                                                \ +	info->data->align = (a);                                               \ +	info->data->access = (p);                                              \ +	info->data++;                                                          \ +} while(0) + +#define mmio_list(r,d,s,b) do {                                                \ +	info->mmio->addr = (r);                                                \ +	info->mmio->data = (d);                                                \ +	info->mmio->shift = (s);                                               \ +	info->mmio->buffer = (b);                                              \ +	info->mmio++;                                                          \ +	nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0));      \ +} while(0) + +extern struct nouveau_oclass *nvc0_grctx_oclass; +int  nvc0_grctx_generate(struct nvc0_graph_priv *); +void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *); +void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); +void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *); +void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *); +void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *); +void nvc0_grctx_generate_r4060a8(struct nvc0_graph_priv *); +void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *); +void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *); + +extern struct nouveau_oclass *nvc1_grctx_oclass; +void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); +void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *); + +extern struct nouveau_oclass *nvc4_grctx_oclass; +extern struct nouveau_oclass *nvc8_grctx_oclass; +extern struct nouveau_oclass *nvd7_grctx_oclass; +extern struct nouveau_oclass *nvd9_grctx_oclass; + +extern struct nouveau_oclass *nve4_grctx_oclass; +extern struct nouveau_oclass *gk20a_grctx_oclass; +void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *); +void nve4_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); +void nve4_grctx_generate_unkn(struct nvc0_graph_priv *); +void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *); + +extern struct nouveau_oclass *nvf0_grctx_oclass; +extern struct nouveau_oclass *nv108_grctx_oclass; +extern struct nouveau_oclass *gm107_grctx_oclass; + +/* context init value lists */ + +extern const struct nvc0_graph_pack nvc0_grctx_pack_icmd[]; + +extern const struct nvc0_graph_pack nvc0_grctx_pack_mthd[]; +extern const struct nvc0_graph_init nvc0_grctx_init_902d_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_9039_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_90c0_0[]; + +extern const struct nvc0_graph_pack nvc0_grctx_pack_hub[]; +extern const struct nvc0_graph_init nvc0_grctx_init_main_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_fe_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_pri_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_memfmt_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_rstr2d_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_scc_0[]; + +extern const struct nvc0_graph_pack nvc0_grctx_pack_gpc[]; +extern const struct nvc0_graph_init nvc0_grctx_init_gpc_unk_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_prop_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_gpc_unk_1[]; +extern const struct nvc0_graph_init nvc0_grctx_init_zcull_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_crstr_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_gpm_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_gcc_0[]; + +extern const struct nvc0_graph_pack nvc0_grctx_pack_zcull[]; + +extern const struct nvc0_graph_pack nvc0_grctx_pack_tpc[]; +extern const struct nvc0_graph_init nvc0_grctx_init_pe_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_wwdx_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_mpc_0[]; +extern const struct nvc0_graph_init nvc0_grctx_init_tpccs_0[]; + +extern const struct nvc0_graph_init nvc4_grctx_init_tex_0[]; +extern const struct nvc0_graph_init nvc4_grctx_init_l1c_0[]; +extern const struct nvc0_graph_init nvc4_grctx_init_sm_0[]; + +extern const struct nvc0_graph_init nvc1_grctx_init_9097_0[]; + +extern const struct nvc0_graph_init nvc1_grctx_init_gpm_0[]; + +extern const struct nvc0_graph_init nvc1_grctx_init_pe_0[]; +extern const struct nvc0_graph_init nvc1_grctx_init_wwdx_0[]; +extern const struct nvc0_graph_init nvc1_grctx_init_tpccs_0[]; + +extern const struct nvc0_graph_init nvc8_grctx_init_9197_0[]; +extern const struct nvc0_graph_init nvc8_grctx_init_9297_0[]; + +extern const struct nvc0_graph_pack nvd9_grctx_pack_icmd[]; + +extern const struct nvc0_graph_pack nvd9_grctx_pack_mthd[]; + +extern const struct nvc0_graph_init nvd9_grctx_init_fe_0[]; +extern const struct nvc0_graph_init nvd9_grctx_init_be_0[]; + +extern const struct nvc0_graph_init nvd9_grctx_init_prop_0[]; +extern const struct nvc0_graph_init nvd9_grctx_init_gpc_unk_1[]; +extern const struct nvc0_graph_init nvd9_grctx_init_crstr_0[]; + +extern const struct nvc0_graph_init nvd9_grctx_init_sm_0[]; + +extern const struct nvc0_graph_init nvd7_grctx_init_pe_0[]; + +extern const struct nvc0_graph_init nvd7_grctx_init_wwdx_0[]; + +extern const struct nvc0_graph_init nve4_grctx_init_memfmt_0[]; +extern const struct nvc0_graph_init nve4_grctx_init_ds_0[]; +extern const struct nvc0_graph_init nve4_grctx_init_scc_0[]; + +extern const struct nvc0_graph_init nve4_grctx_init_gpm_0[]; + +extern const struct nvc0_graph_init nve4_grctx_init_pes_0[]; + +extern const struct nvc0_graph_pack nve4_grctx_pack_hub[]; +extern const struct nvc0_graph_pack nve4_grctx_pack_gpc[]; +extern const struct nvc0_graph_pack nve4_grctx_pack_tpc[]; +extern const struct nvc0_graph_pack nve4_grctx_pack_ppc[]; +extern const struct nvc0_graph_pack nve4_grctx_pack_icmd[]; +extern const struct nvc0_graph_init nve4_grctx_init_a097_0[]; + +extern const struct nvc0_graph_pack nvf0_grctx_pack_mthd[]; + +extern const struct nvc0_graph_init nvf0_grctx_init_pri_0[]; +extern const struct nvc0_graph_init nvf0_grctx_init_cwd_0[]; + +extern const struct nvc0_graph_init nvf0_grctx_init_gpc_unk_2[]; + +extern const struct nvc0_graph_init nvf0_grctx_init_mpc_0[]; +extern const struct nvc0_graph_init nvf0_grctx_init_l1c_0[]; + +extern const struct nvc0_graph_init nv108_grctx_init_rstr2d_0[]; + +extern const struct nvc0_graph_init nv108_grctx_init_prop_0[]; +extern const struct nvc0_graph_init nv108_grctx_init_crstr_0[]; + + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c index e5be3ee7f17..24a92c569c0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c @@ -22,10 +22,14 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -static struct nvc0_graph_init -nvc1_grctx_init_icmd[] = { +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nvc1_grctx_init_icmd_0[] = {  	{ 0x001000,   1, 0x01, 0x00000004 },  	{ 0x0000a9,   1, 0x01, 0x0000ffff },  	{ 0x000038,   1, 0x01, 0x0fac6881 }, @@ -141,8 +145,7 @@ nvc1_grctx_init_icmd[] = {  	{ 0x000586,   1, 0x01, 0x00000040 },  	{ 0x000582,   2, 0x01, 0x00000080 },  	{ 0x0005c2,   1, 0x01, 0x00000001 }, -	{ 0x000638,   1, 0x01, 0x00000001 }, -	{ 0x000639,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 },  	{ 0x00063a,   1, 0x01, 0x00000002 },  	{ 0x00063b,   2, 0x01, 0x00000001 },  	{ 0x00063d,   1, 0x01, 0x00000002 }, @@ -202,15 +205,13 @@ nvc1_grctx_init_icmd[] = {  	{ 0x000787,   1, 0x01, 0x000000cf },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x000836,   1, 0x01, 0x00000001 },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x00080c,   1, 0x01, 0x00000002 },  	{ 0x00080d,   2, 0x01, 0x00000100 }, @@ -236,14 +237,12 @@ nvc1_grctx_init_icmd[] = {  	{ 0x0006b1,   1, 0x01, 0x00000011 },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x01e100,   1, 0x01, 0x00000001 },  	{ 0x001000,   1, 0x01, 0x00000014 }, @@ -268,8 +267,14 @@ nvc1_grctx_init_icmd[] = {  	{}  }; -struct nvc0_graph_init -nvc1_grctx_init_9097[] = { +static const struct nvc0_graph_pack +nvc1_grctx_pack_icmd[] = { +	{ nvc1_grctx_init_icmd_0 }, +	{} +}; + +const struct nvc0_graph_init +nvc1_grctx_init_9097_0[] = {  	{ 0x000800,   8, 0x40, 0x00000000 },  	{ 0x000804,   8, 0x40, 0x00000000 },  	{ 0x000808,   8, 0x40, 0x00000400 }, @@ -516,8 +521,7 @@ nvc1_grctx_init_9097[] = {  	{ 0x001350,   1, 0x04, 0x00000002 },  	{ 0x001358,   1, 0x04, 0x00000001 },  	{ 0x0012e4,   1, 0x04, 0x00000000 }, -	{ 0x00131c,   1, 0x04, 0x00000000 }, -	{ 0x001320,   3, 0x04, 0x00000000 }, +	{ 0x00131c,   4, 0x04, 0x00000000 },  	{ 0x0019c0,   1, 0x04, 0x00000000 },  	{ 0x001140,   1, 0x04, 0x00000000 },  	{ 0x0019c4,   1, 0x04, 0x00000000 }, @@ -571,15 +575,25 @@ nvc1_grctx_init_9097[] = {  	{}  }; -static struct nvc0_graph_init -nvc1_grctx_init_9197[] = { +static const struct nvc0_graph_init +nvc1_grctx_init_9197_0[] = {  	{ 0x003400, 128, 0x04, 0x00000000 },  	{ 0x0002e4,   1, 0x04, 0x0000b001 },  	{}  }; -static struct nvc0_graph_init -nvc1_grctx_init_unk58xx[] = { +static const struct nvc0_graph_pack +nvc1_grctx_pack_mthd[] = { +	{ nvc1_grctx_init_9097_0, 0x9097 }, +	{ nvc1_grctx_init_9197_0, 0x9197 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{ nvc0_grctx_init_9039_0, 0x9039 }, +	{ nvc0_grctx_init_90c0_0, 0x90c0 }, +	{} +}; + +static const struct nvc0_graph_init +nvc1_grctx_init_ds_0[] = {  	{ 0x405800,   1, 0x04, 0x0f8000bf },  	{ 0x405830,   1, 0x04, 0x02180218 },  	{ 0x405834,   2, 0x04, 0x00000000 }, @@ -587,10 +601,23 @@ nvc1_grctx_init_unk58xx[] = {  	{ 0x405870,   4, 0x04, 0x00000001 },  	{ 0x405a00,   2, 0x04, 0x00000000 },  	{ 0x405a18,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc1_grctx_init_pd_0[] = { +	{ 0x406020,   1, 0x04, 0x000103c1 }, +	{ 0x406028,   4, 0x04, 0x00000001 }, +	{ 0x4064a8,   1, 0x04, 0x00000000 }, +	{ 0x4064ac,   1, 0x04, 0x00003fff }, +	{ 0x4064b4,   2, 0x04, 0x00000000 }, +	{ 0x4064c0,   1, 0x04, 0x80140078 }, +	{ 0x4064c4,   1, 0x04, 0x0086ffff }, +	{}  }; -static struct nvc0_graph_init -nvc1_grctx_init_rop[] = { +static const struct nvc0_graph_init +nvc1_grctx_init_be_0[] = {  	{ 0x408800,   1, 0x04, 0x02802a3c },  	{ 0x408804,   1, 0x04, 0x00000040 },  	{ 0x408808,   1, 0x04, 0x1003e005 }, @@ -598,27 +625,25 @@ nvc1_grctx_init_rop[] = {  	{ 0x408904,   1, 0x04, 0x62000001 },  	{ 0x408908,   1, 0x04, 0x00c80929 },  	{ 0x408980,   1, 0x04, 0x0000011d }, +	{} +}; + +static const struct nvc0_graph_pack +nvc1_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nvc0_grctx_init_fe_0 }, +	{ nvc0_grctx_init_pri_0 }, +	{ nvc0_grctx_init_memfmt_0 }, +	{ nvc1_grctx_init_ds_0 }, +	{ nvc1_grctx_init_pd_0 }, +	{ nvc0_grctx_init_rstr2d_0 }, +	{ nvc0_grctx_init_scc_0 }, +	{ nvc1_grctx_init_be_0 }, +	{}  }; -static struct nvc0_graph_init -nvc1_grctx_init_gpc_0[] = { -	{ 0x418380,   1, 0x04, 0x00000016 }, -	{ 0x418400,   1, 0x04, 0x38004e00 }, -	{ 0x418404,   1, 0x04, 0x71e0ffff }, -	{ 0x418408,   1, 0x04, 0x00000000 }, -	{ 0x41840c,   1, 0x04, 0x00001008 }, -	{ 0x418410,   1, 0x04, 0x0fff0fff }, -	{ 0x418414,   1, 0x04, 0x00200fff }, -	{ 0x418450,   6, 0x04, 0x00000000 }, -	{ 0x418468,   1, 0x04, 0x00000001 }, -	{ 0x41846c,   2, 0x04, 0x00000000 }, -	{ 0x418600,   1, 0x04, 0x0000001f }, -	{ 0x418684,   1, 0x04, 0x0000000f }, -	{ 0x418700,   1, 0x04, 0x00000002 }, -	{ 0x418704,   1, 0x04, 0x00000080 }, -	{ 0x418708,   1, 0x04, 0x00000000 }, -	{ 0x41870c,   1, 0x04, 0x07c80000 }, -	{ 0x418710,   1, 0x04, 0x00000000 }, +static const struct nvc0_graph_init +nvc1_grctx_init_setup_0[] = {  	{ 0x418800,   1, 0x04, 0x0006860a },  	{ 0x418808,   3, 0x04, 0x00000000 },  	{ 0x418828,   1, 0x04, 0x00008442 }, @@ -627,68 +652,44 @@ nvc1_grctx_init_gpc_0[] = {  	{ 0x4188e0,   1, 0x04, 0x01000000 },  	{ 0x4188e8,   5, 0x04, 0x00000000 },  	{ 0x4188fc,   1, 0x04, 0x00100018 }, -	{ 0x41891c,   1, 0x04, 0x00ff00ff }, -	{ 0x418924,   1, 0x04, 0x00000000 }, -	{ 0x418928,   1, 0x04, 0x00ffff00 }, -	{ 0x41892c,   1, 0x04, 0x0000ff00 }, -	{ 0x418a00,   3, 0x04, 0x00000000 }, -	{ 0x418a0c,   1, 0x04, 0x00010000 }, -	{ 0x418a10,   3, 0x04, 0x00000000 }, -	{ 0x418a20,   3, 0x04, 0x00000000 }, -	{ 0x418a2c,   1, 0x04, 0x00010000 }, -	{ 0x418a30,   3, 0x04, 0x00000000 }, -	{ 0x418a40,   3, 0x04, 0x00000000 }, -	{ 0x418a4c,   1, 0x04, 0x00010000 }, -	{ 0x418a50,   3, 0x04, 0x00000000 }, -	{ 0x418a60,   3, 0x04, 0x00000000 }, -	{ 0x418a6c,   1, 0x04, 0x00010000 }, -	{ 0x418a70,   3, 0x04, 0x00000000 }, -	{ 0x418a80,   3, 0x04, 0x00000000 }, -	{ 0x418a8c,   1, 0x04, 0x00010000 }, -	{ 0x418a90,   3, 0x04, 0x00000000 }, -	{ 0x418aa0,   3, 0x04, 0x00000000 }, -	{ 0x418aac,   1, 0x04, 0x00010000 }, -	{ 0x418ab0,   3, 0x04, 0x00000000 }, -	{ 0x418ac0,   3, 0x04, 0x00000000 }, -	{ 0x418acc,   1, 0x04, 0x00010000 }, -	{ 0x418ad0,   3, 0x04, 0x00000000 }, -	{ 0x418ae0,   3, 0x04, 0x00000000 }, -	{ 0x418aec,   1, 0x04, 0x00010000 }, -	{ 0x418af0,   3, 0x04, 0x00000000 }, -	{ 0x418b00,   1, 0x04, 0x00000000 }, -	{ 0x418b08,   1, 0x04, 0x0a418820 }, -	{ 0x418b0c,   1, 0x04, 0x062080e6 }, -	{ 0x418b10,   1, 0x04, 0x020398a4 }, -	{ 0x418b14,   1, 0x04, 0x0e629062 }, -	{ 0x418b18,   1, 0x04, 0x0a418820 }, -	{ 0x418b1c,   1, 0x04, 0x000000e6 }, -	{ 0x418bb8,   1, 0x04, 0x00000103 }, +	{} +}; + +const struct nvc0_graph_init +nvc1_grctx_init_gpm_0[] = {  	{ 0x418c08,   1, 0x04, 0x00000001 },  	{ 0x418c10,   8, 0x04, 0x00000000 },  	{ 0x418c6c,   1, 0x04, 0x00000001 },  	{ 0x418c80,   1, 0x04, 0x20200004 },  	{ 0x418c8c,   1, 0x04, 0x00000001 }, -	{ 0x419000,   1, 0x04, 0x00000780 }, -	{ 0x419004,   2, 0x04, 0x00000000 }, -	{ 0x419014,   1, 0x04, 0x00000004 }, +	{} +}; + +static const struct nvc0_graph_pack +nvc1_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvc0_grctx_init_prop_0 }, +	{ nvc0_grctx_init_gpc_unk_1 }, +	{ nvc1_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvc0_grctx_init_crstr_0 }, +	{ nvc1_grctx_init_gpm_0 }, +	{ nvc0_grctx_init_gcc_0 }, +	{}  }; -static struct nvc0_graph_init -nvc1_grctx_init_tpc[] = { +const struct nvc0_graph_init +nvc1_grctx_init_pe_0[] = {  	{ 0x419818,   1, 0x04, 0x00000000 },  	{ 0x41983c,   1, 0x04, 0x00038bc7 },  	{ 0x419848,   1, 0x04, 0x00000000 },  	{ 0x419864,   1, 0x04, 0x00000129 },  	{ 0x419888,   1, 0x04, 0x00000000 }, -	{ 0x419a00,   1, 0x04, 0x000001f0 }, -	{ 0x419a04,   1, 0x04, 0x00000001 }, -	{ 0x419a08,   1, 0x04, 0x00000023 }, -	{ 0x419a0c,   1, 0x04, 0x00020000 }, -	{ 0x419a10,   1, 0x04, 0x00000000 }, -	{ 0x419a14,   1, 0x04, 0x00000200 }, -	{ 0x419a1c,   1, 0x04, 0x00000000 }, -	{ 0x419a20,   1, 0x04, 0x00000800 }, -	{ 0x419ac4,   1, 0x04, 0x0007f440 }, +	{} +}; + +const struct nvc0_graph_init +nvc1_grctx_init_wwdx_0[] = {  	{ 0x419b00,   1, 0x04, 0x0a418820 },  	{ 0x419b04,   1, 0x04, 0x062080e6 },  	{ 0x419b08,   1, 0x04, 0x020398a4 }, @@ -698,27 +699,33 @@ nvc1_grctx_init_tpc[] = {  	{ 0x419bd0,   1, 0x04, 0x00900103 },  	{ 0x419be0,   1, 0x04, 0x00400001 },  	{ 0x419be4,   1, 0x04, 0x00000000 }, -	{ 0x419c00,   1, 0x04, 0x00000002 }, -	{ 0x419c04,   1, 0x04, 0x00000006 }, -	{ 0x419c08,   1, 0x04, 0x00000002 }, -	{ 0x419c20,   1, 0x04, 0x00000000 }, -	{ 0x419cb0,   1, 0x04, 0x00020048 }, -	{ 0x419ce8,   1, 0x04, 0x00000000 }, -	{ 0x419cf4,   1, 0x04, 0x00000183 }, +	{} +}; + +const struct nvc0_graph_init +nvc1_grctx_init_tpccs_0[] = {  	{ 0x419d20,   1, 0x04, 0x12180000 },  	{ 0x419d24,   1, 0x04, 0x00001fff },  	{ 0x419d44,   1, 0x04, 0x02180218 }, -	{ 0x419e04,   3, 0x04, 0x00000000 }, -	{ 0x419e10,   1, 0x04, 0x00000002 }, -	{ 0x419e44,   1, 0x04, 0x001beff2 }, -	{ 0x419e48,   1, 0x04, 0x00000000 }, -	{ 0x419e4c,   1, 0x04, 0x0000000f }, -	{ 0x419e50,  17, 0x04, 0x00000000 }, -	{ 0x419e98,   1, 0x04, 0x00000000 }, -	{ 0x419ee0,   1, 0x04, 0x00011110 }, -	{ 0x419f30,  11, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +nvc1_grctx_pack_tpc[] = { +	{ nvc1_grctx_init_pe_0 }, +	{ nvc4_grctx_init_tex_0 }, +	{ nvc1_grctx_init_wwdx_0 }, +	{ nvc0_grctx_init_mpc_0 }, +	{ nvc4_grctx_init_l1c_0 }, +	{ nvc1_grctx_init_tpccs_0 }, +	{ nvc4_grctx_init_sm_0 }, +	{}  }; +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ +  void  nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  { @@ -767,41 +774,6 @@ nvc1_grctx_generate_unkn(struct nvc0_graph_priv *priv)  	nv_mask(priv, 0x419c00, 0x00000008, 0x00000008);  } -static struct nvc0_graph_init * -nvc1_grctx_init_hub[] = { -	nvc0_grctx_init_base, -	nvc0_grctx_init_unk40xx, -	nvc0_grctx_init_unk44xx, -	nvc0_grctx_init_unk46xx, -	nvc0_grctx_init_unk47xx, -	nvc1_grctx_init_unk58xx, -	nvc0_grctx_init_unk60xx, -	nvc0_grctx_init_unk64xx, -	nvc0_grctx_init_unk78xx, -	nvc0_grctx_init_unk80xx, -	nvc1_grctx_init_rop, -	NULL -}; - -struct nvc0_graph_init * -nvc1_grctx_init_gpc[] = { -	nvc1_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvc1_grctx_init_tpc, -	NULL -}; - -static struct nvc0_graph_mthd -nvc1_grctx_init_mthd[] = { -	{ 0x9097, nvc1_grctx_init_9097, }, -	{ 0x9197, nvc1_grctx_init_9197, }, -	{ 0x902d, nvc0_grctx_init_902d, }, -	{ 0x9039, nvc0_grctx_init_9039, }, -	{ 0x90c0, nvc0_grctx_init_90c0, }, -	{ 0x902d, nvc0_grctx_init_mthd_magic, }, -	{} -}; -  struct nouveau_oclass *  nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xc1), @@ -813,11 +785,13 @@ nvc1_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nvc0_grctx_generate_main, -	.mods = nvc1_grctx_generate_mods, -	.unkn = nvc1_grctx_generate_unkn, -	.hub  = nvc1_grctx_init_hub, -	.gpc  = nvc1_grctx_init_gpc, -	.icmd = nvc1_grctx_init_icmd, -	.mthd = nvc1_grctx_init_mthd, +	.main  = nvc0_grctx_generate_main, +	.mods  = nvc1_grctx_generate_mods, +	.unkn  = nvc1_grctx_generate_unkn, +	.hub   = nvc1_grctx_pack_hub, +	.gpc   = nvc1_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvc1_grctx_pack_tpc, +	.icmd  = nvc1_grctx_pack_icmd, +	.mthd  = nvc1_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c index 8f237b3bd8c..e11ed553819 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc3.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c @@ -22,15 +22,14 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -static struct nvc0_graph_init -nvc3_grctx_init_tpc[] = { -	{ 0x419818,   1, 0x04, 0x00000000 }, -	{ 0x41983c,   1, 0x04, 0x00038bc7 }, -	{ 0x419848,   1, 0x04, 0x00000000 }, -	{ 0x419864,   1, 0x04, 0x0000012a }, -	{ 0x419888,   1, 0x04, 0x00000000 }, +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +const struct nvc0_graph_init +nvc4_grctx_init_tex_0[] = {  	{ 0x419a00,   1, 0x04, 0x000001f0 },  	{ 0x419a04,   1, 0x04, 0x00000001 },  	{ 0x419a08,   1, 0x04, 0x00000023 }, @@ -40,24 +39,19 @@ nvc3_grctx_init_tpc[] = {  	{ 0x419a1c,   1, 0x04, 0x00000000 },  	{ 0x419a20,   1, 0x04, 0x00000800 },  	{ 0x419ac4,   1, 0x04, 0x0007f440 }, -	{ 0x419b00,   1, 0x04, 0x0a418820 }, -	{ 0x419b04,   1, 0x04, 0x062080e6 }, -	{ 0x419b08,   1, 0x04, 0x020398a4 }, -	{ 0x419b0c,   1, 0x04, 0x0e629062 }, -	{ 0x419b10,   1, 0x04, 0x0a418820 }, -	{ 0x419b14,   1, 0x04, 0x000000e6 }, -	{ 0x419bd0,   1, 0x04, 0x00900103 }, -	{ 0x419be0,   1, 0x04, 0x00000001 }, -	{ 0x419be4,   1, 0x04, 0x00000000 }, -	{ 0x419c00,   1, 0x04, 0x00000002 }, -	{ 0x419c04,   1, 0x04, 0x00000006 }, -	{ 0x419c08,   1, 0x04, 0x00000002 }, -	{ 0x419c20,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc4_grctx_init_l1c_0[] = {  	{ 0x419cb0,   1, 0x04, 0x00020048 },  	{ 0x419ce8,   1, 0x04, 0x00000000 },  	{ 0x419cf4,   1, 0x04, 0x00000183 }, -	{ 0x419d20,   1, 0x04, 0x02180000 }, -	{ 0x419d24,   1, 0x04, 0x00001fff }, +	{} +}; + +const struct nvc0_graph_init +nvc4_grctx_init_sm_0[] = {  	{ 0x419e04,   3, 0x04, 0x00000000 },  	{ 0x419e10,   1, 0x04, 0x00000002 },  	{ 0x419e44,   1, 0x04, 0x001beff2 }, @@ -70,16 +64,24 @@ nvc3_grctx_init_tpc[] = {  	{}  }; -struct nvc0_graph_init * -nvc3_grctx_init_gpc[] = { -	nvc0_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvc3_grctx_init_tpc, -	NULL +static const struct nvc0_graph_pack +nvc4_grctx_pack_tpc[] = { +	{ nvc0_grctx_init_pe_0 }, +	{ nvc4_grctx_init_tex_0 }, +	{ nvc0_grctx_init_wwdx_0 }, +	{ nvc0_grctx_init_mpc_0 }, +	{ nvc4_grctx_init_l1c_0 }, +	{ nvc0_grctx_init_tpccs_0 }, +	{ nvc4_grctx_init_sm_0 }, +	{}  }; +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ +  struct nouveau_oclass * -nvc3_grctx_oclass = &(struct nvc0_grctx_oclass) { +nvc4_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xc3),  	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvc0_graph_context_ctor, @@ -89,11 +91,13 @@ nvc3_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nvc0_grctx_generate_main, -	.mods = nvc0_grctx_generate_mods, -	.unkn = nvc0_grctx_generate_unkn, -	.hub  = nvc0_grctx_init_hub, -	.gpc  = nvc3_grctx_init_gpc, -	.icmd = nvc0_grctx_init_icmd, -	.mthd = nvc0_grctx_init_mthd, +	.main  = nvc0_grctx_generate_main, +	.mods  = nvc0_grctx_generate_mods, +	.unkn  = nvc0_grctx_generate_unkn, +	.hub   = nvc0_grctx_pack_hub, +	.gpc   = nvc0_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvc4_grctx_pack_tpc, +	.icmd  = nvc0_grctx_pack_icmd, +	.mthd  = nvc0_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c index d0d4ce3c489..feebd58dfe8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c @@ -22,10 +22,14 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -static struct nvc0_graph_init -nvc8_grctx_init_icmd[] = { +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nvc8_grctx_init_icmd_0[] = {  	{ 0x001000,   1, 0x01, 0x00000004 },  	{ 0x0000a9,   1, 0x01, 0x0000ffff },  	{ 0x000038,   1, 0x01, 0x0fac6881 }, @@ -141,8 +145,7 @@ nvc8_grctx_init_icmd[] = {  	{ 0x000586,   1, 0x01, 0x00000040 },  	{ 0x000582,   2, 0x01, 0x00000080 },  	{ 0x0005c2,   1, 0x01, 0x00000001 }, -	{ 0x000638,   1, 0x01, 0x00000001 }, -	{ 0x000639,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 },  	{ 0x00063a,   1, 0x01, 0x00000002 },  	{ 0x00063b,   2, 0x01, 0x00000001 },  	{ 0x00063d,   1, 0x01, 0x00000002 }, @@ -203,15 +206,13 @@ nvc8_grctx_init_icmd[] = {  	{ 0x000787,   1, 0x01, 0x000000cf },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x000836,   1, 0x01, 0x00000001 },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x00080c,   1, 0x01, 0x00000002 },  	{ 0x00080d,   2, 0x01, 0x00000100 }, @@ -237,14 +238,12 @@ nvc8_grctx_init_icmd[] = {  	{ 0x0006b1,   1, 0x01, 0x00000011 },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x01e100,   1, 0x01, 0x00000001 },  	{ 0x001000,   1, 0x01, 0x00000014 }, @@ -269,58 +268,20 @@ nvc8_grctx_init_icmd[] = {  	{}  }; -static struct nvc0_graph_init -nvc8_grctx_init_tpc[] = { -	{ 0x419818,   1, 0x04, 0x00000000 }, -	{ 0x41983c,   1, 0x04, 0x00038bc7 }, -	{ 0x419848,   1, 0x04, 0x00000000 }, -	{ 0x419864,   1, 0x04, 0x0000012a }, -	{ 0x419888,   1, 0x04, 0x00000000 }, -	{ 0x419a00,   1, 0x04, 0x000001f0 }, -	{ 0x419a04,   1, 0x04, 0x00000001 }, -	{ 0x419a08,   1, 0x04, 0x00000023 }, -	{ 0x419a0c,   1, 0x04, 0x00020000 }, -	{ 0x419a10,   1, 0x04, 0x00000000 }, -	{ 0x419a14,   1, 0x04, 0x00000200 }, -	{ 0x419a1c,   1, 0x04, 0x00000000 }, -	{ 0x419a20,   1, 0x04, 0x00000800 }, -	{ 0x419b00,   1, 0x04, 0x0a418820 }, -	{ 0x419b04,   1, 0x04, 0x062080e6 }, -	{ 0x419b08,   1, 0x04, 0x020398a4 }, -	{ 0x419b0c,   1, 0x04, 0x0e629062 }, -	{ 0x419b10,   1, 0x04, 0x0a418820 }, -	{ 0x419b14,   1, 0x04, 0x000000e6 }, -	{ 0x419bd0,   1, 0x04, 0x00900103 }, -	{ 0x419be0,   1, 0x04, 0x00000001 }, -	{ 0x419be4,   1, 0x04, 0x00000000 }, -	{ 0x419c00,   1, 0x04, 0x00000002 }, -	{ 0x419c04,   1, 0x04, 0x00000006 }, -	{ 0x419c08,   1, 0x04, 0x00000002 }, -	{ 0x419c20,   1, 0x04, 0x00000000 }, -	{ 0x419cb0,   1, 0x04, 0x00060048 }, -	{ 0x419ce8,   1, 0x04, 0x00000000 }, -	{ 0x419cf4,   1, 0x04, 0x00000183 }, -	{ 0x419d20,   1, 0x04, 0x02180000 }, -	{ 0x419d24,   1, 0x04, 0x00001fff }, -	{ 0x419e04,   3, 0x04, 0x00000000 }, -	{ 0x419e10,   1, 0x04, 0x00000002 }, -	{ 0x419e44,   1, 0x04, 0x001beff2 }, -	{ 0x419e48,   1, 0x04, 0x00000000 }, -	{ 0x419e4c,   1, 0x04, 0x0000000f }, -	{ 0x419e50,  17, 0x04, 0x00000000 }, -	{ 0x419e98,   1, 0x04, 0x00000000 }, -	{ 0x419f50,   2, 0x04, 0x00000000 }, +static const struct nvc0_graph_pack +nvc8_grctx_pack_icmd[] = { +	{ nvc8_grctx_init_icmd_0 },  	{}  }; -struct nvc0_graph_init -nvc8_grctx_init_9197[] = { +const struct nvc0_graph_init +nvc8_grctx_init_9197_0[] = {  	{ 0x0002e4,   1, 0x04, 0x0000b001 },  	{}  }; -struct nvc0_graph_init -nvc8_grctx_init_9297[] = { +const struct nvc0_graph_init +nvc8_grctx_init_9297_0[] = {  	{ 0x003400, 128, 0x04, 0x00000000 },  	{ 0x00036c,   2, 0x04, 0x00000000 },  	{ 0x0007a4,   2, 0x04, 0x00000000 }, @@ -329,26 +290,47 @@ nvc8_grctx_init_9297[] = {  	{}  }; -static struct nvc0_graph_mthd -nvc8_grctx_init_mthd[] = { -	{ 0x9097, nvc1_grctx_init_9097, }, -	{ 0x9197, nvc8_grctx_init_9197, }, -	{ 0x9297, nvc8_grctx_init_9297, }, -	{ 0x902d, nvc0_grctx_init_902d, }, -	{ 0x9039, nvc0_grctx_init_9039, }, -	{ 0x90c0, nvc0_grctx_init_90c0, }, -	{ 0x902d, nvc0_grctx_init_mthd_magic, }, +static const struct nvc0_graph_pack +nvc8_grctx_pack_mthd[] = { +	{ nvc1_grctx_init_9097_0, 0x9097 }, +	{ nvc8_grctx_init_9197_0, 0x9197 }, +	{ nvc8_grctx_init_9297_0, 0x9297 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{ nvc0_grctx_init_9039_0, 0x9039 }, +	{ nvc0_grctx_init_90c0_0, 0x90c0 }, +	{} +}; + +static const struct nvc0_graph_init +nvc8_grctx_init_setup_0[] = { +	{ 0x418800,   1, 0x04, 0x0006860a }, +	{ 0x418808,   3, 0x04, 0x00000000 }, +	{ 0x418828,   1, 0x04, 0x00008442 }, +	{ 0x418830,   1, 0x04, 0x00000001 }, +	{ 0x4188d8,   1, 0x04, 0x00000008 }, +	{ 0x4188e0,   1, 0x04, 0x01000000 }, +	{ 0x4188e8,   5, 0x04, 0x00000000 }, +	{ 0x4188fc,   1, 0x04, 0x20100000 },  	{}  }; -static struct nvc0_graph_init * -nvc8_grctx_init_gpc[] = { -	nvc0_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvc8_grctx_init_tpc, -	NULL +static const struct nvc0_graph_pack +nvc8_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvc0_grctx_init_prop_0 }, +	{ nvc0_grctx_init_gpc_unk_1 }, +	{ nvc8_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvc0_grctx_init_crstr_0 }, +	{ nvc0_grctx_init_gpm_0 }, +	{ nvc0_grctx_init_gcc_0 }, +	{}  }; +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ +  struct nouveau_oclass *  nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xc8), @@ -360,11 +342,13 @@ nvc8_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nvc0_grctx_generate_main, -	.mods = nvc0_grctx_generate_mods, -	.unkn = nvc0_grctx_generate_unkn, -	.hub  = nvc0_grctx_init_hub, -	.gpc  = nvc8_grctx_init_gpc, -	.icmd = nvc8_grctx_init_icmd, -	.mthd = nvc8_grctx_init_mthd, +	.main  = nvc0_grctx_generate_main, +	.mods  = nvc0_grctx_generate_mods, +	.unkn  = nvc0_grctx_generate_unkn, +	.hub   = nvc0_grctx_pack_hub, +	.gpc   = nvc8_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvc0_grctx_pack_tpc, +	.icmd  = nvc8_grctx_pack_icmd, +	.mthd  = nvc8_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c index 438e7841080..1dbc8d7f2e8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c @@ -22,33 +22,14 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -struct nvc0_graph_init -nvd7_grctx_init_unk40xx[] = { -	{ 0x404004,  10, 0x04, 0x00000000 }, -	{ 0x404044,   1, 0x04, 0x00000000 }, -	{ 0x404094,   1, 0x04, 0x00000000 }, -	{ 0x404098,  12, 0x04, 0x00000000 }, -	{ 0x4040c8,   1, 0x04, 0xf0000087 }, -	{ 0x4040d0,   6, 0x04, 0x00000000 }, -	{ 0x4040e8,   1, 0x04, 0x00001000 }, -	{ 0x4040f8,   1, 0x04, 0x00000000 }, -	{ 0x404130,   1, 0x04, 0x00000000 }, -	{ 0x404134,   1, 0x04, 0x00000000 }, -	{ 0x404138,   1, 0x04, 0x20000040 }, -	{ 0x404150,   1, 0x04, 0x0000002e }, -	{ 0x404154,   1, 0x04, 0x00000400 }, -	{ 0x404158,   1, 0x04, 0x00000200 }, -	{ 0x404164,   1, 0x04, 0x00000055 }, -	{ 0x404168,   1, 0x04, 0x00000000 }, -	{ 0x404178,   2, 0x04, 0x00000000 }, -	{ 0x404200,   8, 0x04, 0x00000000 }, -	{} -}; +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ -static struct nvc0_graph_init -nvd7_grctx_init_unk58xx[] = { +static const struct nvc0_graph_init +nvd7_grctx_init_ds_0[] = {  	{ 0x405800,   1, 0x04, 0x0f8000bf },  	{ 0x405830,   1, 0x04, 0x02180324 },  	{ 0x405834,   1, 0x04, 0x08000000 }, @@ -60,8 +41,10 @@ nvd7_grctx_init_unk58xx[] = {  	{}  }; -static struct nvc0_graph_init -nvd7_grctx_init_unk64xx[] = { +static const struct nvc0_graph_init +nvd7_grctx_init_pd_0[] = { +	{ 0x406020,   1, 0x04, 0x000103c1 }, +	{ 0x406028,   4, 0x04, 0x00000001 },  	{ 0x4064a8,   1, 0x04, 0x00000000 },  	{ 0x4064ac,   1, 0x04, 0x00003fff },  	{ 0x4064b4,   3, 0x04, 0x00000000 }, @@ -71,22 +54,22 @@ nvd7_grctx_init_unk64xx[] = {  	{}  }; -static struct nvc0_graph_init -nvd7_grctx_init_gpc_0[] = { -	{ 0x418380,   1, 0x04, 0x00000016 }, -	{ 0x418400,   1, 0x04, 0x38004e00 }, -	{ 0x418404,   1, 0x04, 0x71e0ffff }, -	{ 0x41840c,   1, 0x04, 0x00001008 }, -	{ 0x418410,   1, 0x04, 0x0fff0fff }, -	{ 0x418414,   1, 0x04, 0x02200fff }, -	{ 0x418450,   6, 0x04, 0x00000000 }, -	{ 0x418468,   1, 0x04, 0x00000001 }, -	{ 0x41846c,   2, 0x04, 0x00000000 }, -	{ 0x418600,   1, 0x04, 0x0000001f }, -	{ 0x418684,   1, 0x04, 0x0000000f }, -	{ 0x418700,   1, 0x04, 0x00000002 }, -	{ 0x418704,   1, 0x04, 0x00000080 }, -	{ 0x418708,   3, 0x04, 0x00000000 }, +static const struct nvc0_graph_pack +nvd7_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nvd9_grctx_init_fe_0 }, +	{ nvc0_grctx_init_pri_0 }, +	{ nvc0_grctx_init_memfmt_0 }, +	{ nvd7_grctx_init_ds_0 }, +	{ nvd7_grctx_init_pd_0 }, +	{ nvc0_grctx_init_rstr2d_0 }, +	{ nvc0_grctx_init_scc_0 }, +	{ nvd9_grctx_init_be_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvd7_grctx_init_setup_0[] = {  	{ 0x418800,   1, 0x04, 0x7006860a },  	{ 0x418808,   3, 0x04, 0x00000000 },  	{ 0x418828,   1, 0x04, 0x00008442 }, @@ -95,34 +78,32 @@ nvd7_grctx_init_gpc_0[] = {  	{ 0x4188e0,   1, 0x04, 0x01000000 },  	{ 0x4188e8,   5, 0x04, 0x00000000 },  	{ 0x4188fc,   1, 0x04, 0x20100018 }, -	{ 0x41891c,   1, 0x04, 0x00ff00ff }, -	{ 0x418924,   1, 0x04, 0x00000000 }, -	{ 0x418928,   1, 0x04, 0x00ffff00 }, -	{ 0x41892c,   1, 0x04, 0x0000ff00 }, -	{ 0x418b00,   1, 0x04, 0x00000006 }, -	{ 0x418b08,   1, 0x04, 0x0a418820 }, -	{ 0x418b0c,   1, 0x04, 0x062080e6 }, -	{ 0x418b10,   1, 0x04, 0x020398a4 }, -	{ 0x418b14,   1, 0x04, 0x0e629062 }, -	{ 0x418b18,   1, 0x04, 0x0a418820 }, -	{ 0x418b1c,   1, 0x04, 0x000000e6 }, -	{ 0x418bb8,   1, 0x04, 0x00000103 }, -	{ 0x418c08,   1, 0x04, 0x00000001 }, -	{ 0x418c10,   8, 0x04, 0x00000000 }, -	{ 0x418c6c,   1, 0x04, 0x00000001 }, -	{ 0x418c80,   1, 0x04, 0x20200004 }, -	{ 0x418c8c,   1, 0x04, 0x00000001 }, -	{ 0x419000,   1, 0x04, 0x00000780 }, -	{ 0x419004,   2, 0x04, 0x00000000 }, -	{ 0x419014,   1, 0x04, 0x00000004 },  	{}  }; -static struct nvc0_graph_init -nvd7_grctx_init_tpc[] = { +static const struct nvc0_graph_pack +nvd7_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvd9_grctx_init_prop_0 }, +	{ nvd9_grctx_init_gpc_unk_1 }, +	{ nvd7_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvd9_grctx_init_crstr_0 }, +	{ nvc1_grctx_init_gpm_0 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +const struct nvc0_graph_init +nvd7_grctx_init_pe_0[] = {  	{ 0x419848,   1, 0x04, 0x00000000 },  	{ 0x419864,   1, 0x04, 0x00000129 },  	{ 0x419888,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvd7_grctx_init_tex_0[] = {  	{ 0x419a00,   1, 0x04, 0x000001f0 },  	{ 0x419a04,   1, 0x04, 0x00000001 },  	{ 0x419a08,   1, 0x04, 0x00000023 }, @@ -132,33 +113,46 @@ nvd7_grctx_init_tpc[] = {  	{ 0x419a1c,   1, 0x04, 0x00008000 },  	{ 0x419a20,   1, 0x04, 0x00000800 },  	{ 0x419ac4,   1, 0x04, 0x0017f440 }, +	{} +}; + +static const struct nvc0_graph_init +nvd7_grctx_init_mpc_0[] = {  	{ 0x419c00,   1, 0x04, 0x0000000a },  	{ 0x419c04,   1, 0x04, 0x00000006 },  	{ 0x419c08,   1, 0x04, 0x00000002 },  	{ 0x419c20,   1, 0x04, 0x00000000 },  	{ 0x419c24,   1, 0x04, 0x00084210 },  	{ 0x419c28,   1, 0x04, 0x3efbefbe }, -	{ 0x419cb0,   1, 0x04, 0x00020048 }, -	{ 0x419ce8,   1, 0x04, 0x00000000 }, -	{ 0x419cf4,   1, 0x04, 0x00000183 }, -	{ 0x419e04,   3, 0x04, 0x00000000 }, -	{ 0x419e10,   1, 0x04, 0x00000002 }, -	{ 0x419e44,   1, 0x04, 0x001beff2 }, -	{ 0x419e48,   1, 0x04, 0x00000000 }, -	{ 0x419e4c,   1, 0x04, 0x0000000f }, -	{ 0x419e50,  17, 0x04, 0x00000000 }, -	{ 0x419e98,   1, 0x04, 0x00000000 }, -	{ 0x419ee0,   1, 0x04, 0x00010110 }, -	{ 0x419f30,  11, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvd7_grctx_init_unk[] = { +static const struct nvc0_graph_pack +nvd7_grctx_pack_tpc[] = { +	{ nvd7_grctx_init_pe_0 }, +	{ nvd7_grctx_init_tex_0 }, +	{ nvd7_grctx_init_mpc_0 }, +	{ nvc4_grctx_init_l1c_0 }, +	{ nvd9_grctx_init_sm_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvd7_grctx_init_pes_0[] = {  	{ 0x41be24,   1, 0x04, 0x00000002 }, +	{} +}; + +static const struct nvc0_graph_init +nvd7_grctx_init_cbm_0[] = {  	{ 0x41bec0,   1, 0x04, 0x12180000 },  	{ 0x41bec4,   1, 0x04, 0x00003fff },  	{ 0x41bee4,   1, 0x04, 0x03240218 }, +	{} +}; + +const struct nvc0_graph_init +nvd7_grctx_init_wwdx_0[] = {  	{ 0x41bf00,   1, 0x04, 0x0a418820 },  	{ 0x41bf04,   1, 0x04, 0x062080e6 },  	{ 0x41bf08,   1, 0x04, 0x020398a4 }, @@ -171,6 +165,18 @@ nvd7_grctx_init_unk[] = {  	{}  }; +static const struct nvc0_graph_pack +nvd7_grctx_pack_ppc[] = { +	{ nvd7_grctx_init_pes_0 }, +	{ nvd7_grctx_init_cbm_0 }, +	{ nvd7_grctx_init_wwdx_0 }, +	{} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ +  static void  nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  { @@ -219,10 +225,11 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  	nv_mask(priv, 0x000260, 0x00000001, 0x00000000); -	for (i = 0; oclass->hub[i]; i++) -		nvc0_graph_mmio(priv, oclass->hub[i]); -	for (i = 0; oclass->gpc[i]; i++) -		nvc0_graph_mmio(priv, oclass->gpc[i]); +	nvc0_graph_mmio(priv, oclass->hub); +	nvc0_graph_mmio(priv, oclass->gpc); +	nvc0_graph_mmio(priv, oclass->zcull); +	nvc0_graph_mmio(priv, oclass->tpc); +	nvc0_graph_mmio(priv, oclass->ppc);  	nv_wr32(priv, 0x404154, 0x00000000); @@ -244,31 +251,6 @@ nvd7_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  	nv_mask(priv, 0x000260, 0x00000001, 0x00000001);  } - -static struct nvc0_graph_init * -nvd7_grctx_init_hub[] = { -	nvc0_grctx_init_base, -	nvd7_grctx_init_unk40xx, -	nvc0_grctx_init_unk44xx, -	nvc0_grctx_init_unk46xx, -	nvc0_grctx_init_unk47xx, -	nvd7_grctx_init_unk58xx, -	nvc0_grctx_init_unk60xx, -	nvd7_grctx_init_unk64xx, -	nvc0_grctx_init_unk78xx, -	nvc0_grctx_init_unk80xx, -	nvd9_grctx_init_rop, -}; - -struct nvc0_graph_init * -nvd7_grctx_init_gpc[] = { -	nvd7_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvd7_grctx_init_tpc, -	nvd7_grctx_init_unk, -	NULL -}; -  struct nouveau_oclass *  nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xd7), @@ -280,11 +262,14 @@ nvd7_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nvd7_grctx_generate_main, -	.mods = nvd7_grctx_generate_mods, -	.unkn = nve4_grctx_generate_unkn, -	.hub  = nvd7_grctx_init_hub, -	.gpc  = nvd7_grctx_init_gpc, -	.icmd = nvd9_grctx_init_icmd, -	.mthd = nvd9_grctx_init_mthd, +	.main  = nvd7_grctx_generate_main, +	.mods  = nvd7_grctx_generate_mods, +	.unkn  = nve4_grctx_generate_unkn, +	.hub   = nvd7_grctx_pack_hub, +	.gpc   = nvd7_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvd7_grctx_pack_tpc, +	.ppc   = nvd7_grctx_pack_ppc, +	.icmd  = nvd9_grctx_pack_icmd, +	.mthd  = nvd9_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c index 818a4751df4..c665fb7e466 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c @@ -22,38 +22,14 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -struct nvc0_graph_init -nvd9_grctx_init_90c0[] = { -	{ 0x002700,   4, 0x40, 0x00000000 }, -	{ 0x002720,   4, 0x40, 0x00000000 }, -	{ 0x002704,   4, 0x40, 0x00000000 }, -	{ 0x002724,   4, 0x40, 0x00000000 }, -	{ 0x002708,   4, 0x40, 0x00000000 }, -	{ 0x002728,   4, 0x40, 0x00000000 }, -	{ 0x00270c,   8, 0x20, 0x00000000 }, -	{ 0x002710,   4, 0x40, 0x00014000 }, -	{ 0x002730,   4, 0x40, 0x00014000 }, -	{ 0x002714,   4, 0x40, 0x00000040 }, -	{ 0x002734,   4, 0x40, 0x00000040 }, -	{ 0x00030c,   1, 0x04, 0x00000001 }, -	{ 0x001944,   1, 0x04, 0x00000000 }, -	{ 0x000758,   1, 0x04, 0x00000100 }, -	{ 0x0002c4,   1, 0x04, 0x00000000 }, -	{ 0x000790,   5, 0x04, 0x00000000 }, -	{ 0x00077c,   1, 0x04, 0x00000000 }, -	{ 0x000204,   3, 0x04, 0x00000000 }, -	{ 0x000214,   1, 0x04, 0x00000000 }, -	{ 0x00024c,   1, 0x04, 0x00000000 }, -	{ 0x000d94,   1, 0x04, 0x00000001 }, -	{ 0x001608,   2, 0x04, 0x00000000 }, -	{ 0x001664,   1, 0x04, 0x00000000 }, -	{} -}; +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ -struct nvc0_graph_init -nvd9_grctx_init_icmd[] = { +static const struct nvc0_graph_init +nvd9_grctx_init_icmd_0[] = {  	{ 0x001000,   1, 0x01, 0x00000004 },  	{ 0x0000a9,   1, 0x01, 0x0000ffff },  	{ 0x000038,   1, 0x01, 0x0fac6881 }, @@ -171,8 +147,7 @@ nvd9_grctx_init_icmd[] = {  	{ 0x000586,   1, 0x01, 0x00000040 },  	{ 0x000582,   2, 0x01, 0x00000080 },  	{ 0x0005c2,   1, 0x01, 0x00000001 }, -	{ 0x000638,   1, 0x01, 0x00000001 }, -	{ 0x000639,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 },  	{ 0x00063a,   1, 0x01, 0x00000002 },  	{ 0x00063b,   2, 0x01, 0x00000001 },  	{ 0x00063d,   1, 0x01, 0x00000002 }, @@ -233,15 +208,13 @@ nvd9_grctx_init_icmd[] = {  	{ 0x000787,   1, 0x01, 0x000000cf },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x000836,   1, 0x01, 0x00000001 },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x00080c,   1, 0x01, 0x00000002 },  	{ 0x00080d,   2, 0x01, 0x00000100 }, @@ -267,14 +240,12 @@ nvd9_grctx_init_icmd[] = {  	{ 0x0006b1,   1, 0x01, 0x00000011 },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x01e100,   1, 0x01, 0x00000001 },  	{ 0x001000,   1, 0x01, 0x00000014 }, @@ -299,18 +270,56 @@ nvd9_grctx_init_icmd[] = {  	{}  }; -struct nvc0_graph_init -nvd9_grctx_init_unk40xx[] = { -	{ 0x404004,  11, 0x04, 0x00000000 }, +const struct nvc0_graph_pack +nvd9_grctx_pack_icmd[] = { +	{ nvd9_grctx_init_icmd_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_grctx_init_90c0_0[] = { +	{ 0x002700,   8, 0x20, 0x00000000 }, +	{ 0x002704,   8, 0x20, 0x00000000 }, +	{ 0x002708,   8, 0x20, 0x00000000 }, +	{ 0x00270c,   8, 0x20, 0x00000000 }, +	{ 0x002710,   8, 0x20, 0x00014000 }, +	{ 0x002714,   8, 0x20, 0x00000040 }, +	{ 0x00030c,   1, 0x04, 0x00000001 }, +	{ 0x001944,   1, 0x04, 0x00000000 }, +	{ 0x000758,   1, 0x04, 0x00000100 }, +	{ 0x0002c4,   1, 0x04, 0x00000000 }, +	{ 0x000790,   5, 0x04, 0x00000000 }, +	{ 0x00077c,   1, 0x04, 0x00000000 }, +	{ 0x000204,   3, 0x04, 0x00000000 }, +	{ 0x000214,   1, 0x04, 0x00000000 }, +	{ 0x00024c,   1, 0x04, 0x00000000 }, +	{ 0x000d94,   1, 0x04, 0x00000001 }, +	{ 0x001608,   2, 0x04, 0x00000000 }, +	{ 0x001664,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_pack +nvd9_grctx_pack_mthd[] = { +	{ nvc1_grctx_init_9097_0, 0x9097 }, +	{ nvc8_grctx_init_9197_0, 0x9197 }, +	{ nvc8_grctx_init_9297_0, 0x9297 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{ nvc0_grctx_init_9039_0, 0x9039 }, +	{ nvd9_grctx_init_90c0_0, 0x90c0 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_grctx_init_fe_0[] = { +	{ 0x404004,  10, 0x04, 0x00000000 },  	{ 0x404044,   1, 0x04, 0x00000000 }, -	{ 0x404094,   1, 0x04, 0x00000000 }, -	{ 0x404098,  12, 0x04, 0x00000000 }, +	{ 0x404094,  13, 0x04, 0x00000000 },  	{ 0x4040c8,   1, 0x04, 0xf0000087 },  	{ 0x4040d0,   6, 0x04, 0x00000000 },  	{ 0x4040e8,   1, 0x04, 0x00001000 },  	{ 0x4040f8,   1, 0x04, 0x00000000 }, -	{ 0x404130,   1, 0x04, 0x00000000 }, -	{ 0x404134,   1, 0x04, 0x00000000 }, +	{ 0x404130,   2, 0x04, 0x00000000 },  	{ 0x404138,   1, 0x04, 0x20000040 },  	{ 0x404150,   1, 0x04, 0x0000002e },  	{ 0x404154,   1, 0x04, 0x00000400 }, @@ -322,8 +331,8 @@ nvd9_grctx_init_unk40xx[] = {  	{}  }; -static struct nvc0_graph_init -nvd9_grctx_init_unk58xx[] = { +static const struct nvc0_graph_init +nvd9_grctx_init_ds_0[] = {  	{ 0x405800,   1, 0x04, 0x0f8000bf },  	{ 0x405830,   1, 0x04, 0x02180218 },  	{ 0x405834,   1, 0x04, 0x08000000 }, @@ -335,8 +344,10 @@ nvd9_grctx_init_unk58xx[] = {  	{}  }; -static struct nvc0_graph_init -nvd9_grctx_init_unk64xx[] = { +static const struct nvc0_graph_init +nvd9_grctx_init_pd_0[] = { +	{ 0x406020,   1, 0x04, 0x000103c1 }, +	{ 0x406028,   4, 0x04, 0x00000001 },  	{ 0x4064a8,   1, 0x04, 0x00000000 },  	{ 0x4064ac,   1, 0x04, 0x00003fff },  	{ 0x4064b4,   3, 0x04, 0x00000000 }, @@ -345,21 +356,34 @@ nvd9_grctx_init_unk64xx[] = {  	{}  }; -struct nvc0_graph_init -nvd9_grctx_init_rop[] = { +const struct nvc0_graph_init +nvd9_grctx_init_be_0[] = {  	{ 0x408800,   1, 0x04, 0x02802a3c },  	{ 0x408804,   1, 0x04, 0x00000040 },  	{ 0x408808,   1, 0x04, 0x1043e005 },  	{ 0x408900,   1, 0x04, 0x3080b801 }, -	{ 0x408904,   1, 0x04, 0x1043e005 }, +	{ 0x408904,   1, 0x04, 0x62000001 },  	{ 0x408908,   1, 0x04, 0x00c8102f },  	{ 0x408980,   1, 0x04, 0x0000011d },  	{}  }; -static struct nvc0_graph_init -nvd9_grctx_init_gpc_0[] = { -	{ 0x418380,   1, 0x04, 0x00000016 }, +static const struct nvc0_graph_pack +nvd9_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nvd9_grctx_init_fe_0 }, +	{ nvc0_grctx_init_pri_0 }, +	{ nvc0_grctx_init_memfmt_0 }, +	{ nvd9_grctx_init_ds_0 }, +	{ nvd9_grctx_init_pd_0 }, +	{ nvc0_grctx_init_rstr2d_0 }, +	{ nvc0_grctx_init_scc_0 }, +	{ nvd9_grctx_init_be_0 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_grctx_init_prop_0[] = {  	{ 0x418400,   1, 0x04, 0x38004e00 },  	{ 0x418404,   1, 0x04, 0x71e0ffff },  	{ 0x41840c,   1, 0x04, 0x00001008 }, @@ -368,11 +392,21 @@ nvd9_grctx_init_gpc_0[] = {  	{ 0x418450,   6, 0x04, 0x00000000 },  	{ 0x418468,   1, 0x04, 0x00000001 },  	{ 0x41846c,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_grctx_init_gpc_unk_1[] = {  	{ 0x418600,   1, 0x04, 0x0000001f },  	{ 0x418684,   1, 0x04, 0x0000000f },  	{ 0x418700,   1, 0x04, 0x00000002 },  	{ 0x418704,   1, 0x04, 0x00000080 },  	{ 0x418708,   3, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_grctx_init_setup_0[] = {  	{ 0x418800,   1, 0x04, 0x7006860a },  	{ 0x418808,   3, 0x04, 0x00000000 },  	{ 0x418828,   1, 0x04, 0x00008442 }, @@ -381,10 +415,11 @@ nvd9_grctx_init_gpc_0[] = {  	{ 0x4188e0,   1, 0x04, 0x01000000 },  	{ 0x4188e8,   5, 0x04, 0x00000000 },  	{ 0x4188fc,   1, 0x04, 0x20100008 }, -	{ 0x41891c,   1, 0x04, 0x00ff00ff }, -	{ 0x418924,   1, 0x04, 0x00000000 }, -	{ 0x418928,   1, 0x04, 0x00ffff00 }, -	{ 0x41892c,   1, 0x04, 0x0000ff00 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_grctx_init_crstr_0[] = {  	{ 0x418b00,   1, 0x04, 0x00000006 },  	{ 0x418b08,   1, 0x04, 0x0a418820 },  	{ 0x418b0c,   1, 0x04, 0x062080e6 }, @@ -393,24 +428,24 @@ nvd9_grctx_init_gpc_0[] = {  	{ 0x418b18,   1, 0x04, 0x0a418820 },  	{ 0x418b1c,   1, 0x04, 0x000000e6 },  	{ 0x418bb8,   1, 0x04, 0x00000103 }, -	{ 0x418c08,   1, 0x04, 0x00000001 }, -	{ 0x418c10,   8, 0x04, 0x00000000 }, -	{ 0x418c6c,   1, 0x04, 0x00000001 }, -	{ 0x418c80,   1, 0x04, 0x20200004 }, -	{ 0x418c8c,   1, 0x04, 0x00000001 }, -	{ 0x419000,   1, 0x04, 0x00000780 }, -	{ 0x419004,   2, 0x04, 0x00000000 }, -	{ 0x419014,   1, 0x04, 0x00000004 },  	{}  }; -static struct nvc0_graph_init -nvd9_grctx_init_tpc[] = { -	{ 0x419818,   1, 0x04, 0x00000000 }, -	{ 0x41983c,   1, 0x04, 0x00038bc7 }, -	{ 0x419848,   1, 0x04, 0x00000000 }, -	{ 0x419864,   1, 0x04, 0x00000129 }, -	{ 0x419888,   1, 0x04, 0x00000000 }, +static const struct nvc0_graph_pack +nvd9_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvd9_grctx_init_prop_0 }, +	{ nvd9_grctx_init_gpc_unk_1 }, +	{ nvd9_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvd9_grctx_init_crstr_0 }, +	{ nvc1_grctx_init_gpm_0 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_grctx_init_tex_0[] = {  	{ 0x419a00,   1, 0x04, 0x000001f0 },  	{ 0x419a04,   1, 0x04, 0x00000001 },  	{ 0x419a08,   1, 0x04, 0x00000023 }, @@ -420,27 +455,22 @@ nvd9_grctx_init_tpc[] = {  	{ 0x419a1c,   1, 0x04, 0x00000000 },  	{ 0x419a20,   1, 0x04, 0x00000800 },  	{ 0x419ac4,   1, 0x04, 0x0017f440 }, -	{ 0x419b00,   1, 0x04, 0x0a418820 }, -	{ 0x419b04,   1, 0x04, 0x062080e6 }, -	{ 0x419b08,   1, 0x04, 0x020398a4 }, -	{ 0x419b0c,   1, 0x04, 0x0e629062 }, -	{ 0x419b10,   1, 0x04, 0x0a418820 }, -	{ 0x419b14,   1, 0x04, 0x000000e6 }, -	{ 0x419bd0,   1, 0x04, 0x00900103 }, -	{ 0x419be0,   1, 0x04, 0x00400001 }, -	{ 0x419be4,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_grctx_init_mpc_0[] = {  	{ 0x419c00,   1, 0x04, 0x0000000a },  	{ 0x419c04,   1, 0x04, 0x00000006 },  	{ 0x419c08,   1, 0x04, 0x00000002 },  	{ 0x419c20,   1, 0x04, 0x00000000 },  	{ 0x419c24,   1, 0x04, 0x00084210 },  	{ 0x419c28,   1, 0x04, 0x3cf3cf3c }, -	{ 0x419cb0,   1, 0x04, 0x00020048 }, -	{ 0x419ce8,   1, 0x04, 0x00000000 }, -	{ 0x419cf4,   1, 0x04, 0x00000183 }, -	{ 0x419d20,   1, 0x04, 0x12180000 }, -	{ 0x419d24,   1, 0x04, 0x00001fff }, -	{ 0x419d44,   1, 0x04, 0x02180218 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_grctx_init_sm_0[] = {  	{ 0x419e04,   3, 0x04, 0x00000000 },  	{ 0x419e10,   1, 0x04, 0x00000002 },  	{ 0x419e44,   1, 0x04, 0x001beff2 }, @@ -453,46 +483,21 @@ nvd9_grctx_init_tpc[] = {  	{}  }; -static struct nvc0_graph_init * -nvd9_grctx_init_hub[] = { -	nvc0_grctx_init_base, -	nvd9_grctx_init_unk40xx, -	nvc0_grctx_init_unk44xx, -	nvc0_grctx_init_unk46xx, -	nvc0_grctx_init_unk47xx, -	nvd9_grctx_init_unk58xx, -	nvc0_grctx_init_unk60xx, -	nvd9_grctx_init_unk64xx, -	nvc0_grctx_init_unk78xx, -	nvc0_grctx_init_unk80xx, -	nvd9_grctx_init_rop, -}; - -struct nvc0_graph_init * -nvd9_grctx_init_gpc[] = { -	nvd9_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvd9_grctx_init_tpc, -	NULL -}; - -struct nvc0_graph_init -nvd9_grctx_init_mthd_magic[] = { -	{ 0x3410, 1, 0x04, 0x80002006 }, +static const struct nvc0_graph_pack +nvd9_grctx_pack_tpc[] = { +	{ nvc1_grctx_init_pe_0 }, +	{ nvd9_grctx_init_tex_0 }, +	{ nvc1_grctx_init_wwdx_0 }, +	{ nvd9_grctx_init_mpc_0 }, +	{ nvc4_grctx_init_l1c_0 }, +	{ nvc1_grctx_init_tpccs_0 }, +	{ nvd9_grctx_init_sm_0 },  	{}  }; -struct nvc0_graph_mthd -nvd9_grctx_init_mthd[] = { -	{ 0x9097, nvc1_grctx_init_9097, }, -	{ 0x9197, nvc8_grctx_init_9197, }, -	{ 0x9297, nvc8_grctx_init_9297, }, -	{ 0x902d, nvc0_grctx_init_902d, }, -	{ 0x9039, nvc0_grctx_init_9039, }, -	{ 0x90c0, nvd9_grctx_init_90c0, }, -	{ 0x902d, nvd9_grctx_init_mthd_magic, }, -	{} -}; +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/  struct nouveau_oclass *  nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) { @@ -505,11 +510,13 @@ nvd9_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nvc0_grctx_generate_main, -	.mods = nvc1_grctx_generate_mods, -	.unkn = nvc1_grctx_generate_unkn, -	.hub  = nvd9_grctx_init_hub, -	.gpc  = nvd9_grctx_init_gpc, -	.icmd = nvd9_grctx_init_icmd, -	.mthd = nvd9_grctx_init_mthd, +	.main  = nvc0_grctx_generate_main, +	.mods  = nvc1_grctx_generate_mods, +	.unkn  = nvc1_grctx_generate_unkn, +	.hub   = nvd9_grctx_pack_hub, +	.gpc   = nvd9_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvd9_grctx_pack_tpc, +	.icmd  = nvd9_grctx_pack_icmd, +	.mthd  = nvd9_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c index e2de73ee5ee..c5b24923858 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c @@ -22,10 +22,14 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -struct nvc0_graph_init -nve4_grctx_init_icmd[] = { +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nve4_grctx_init_icmd_0[] = {  	{ 0x001000,   1, 0x01, 0x00000004 },  	{ 0x000039,   3, 0x01, 0x00000000 },  	{ 0x0000a9,   1, 0x01, 0x0000ffff }, @@ -138,8 +142,7 @@ nve4_grctx_init_icmd[] = {  	{ 0x000586,   1, 0x01, 0x00000040 },  	{ 0x000582,   2, 0x01, 0x00000080 },  	{ 0x0005c2,   1, 0x01, 0x00000001 }, -	{ 0x000638,   1, 0x01, 0x00000001 }, -	{ 0x000639,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 },  	{ 0x00063a,   1, 0x01, 0x00000002 },  	{ 0x00063b,   2, 0x01, 0x00000001 },  	{ 0x00063d,   1, 0x01, 0x00000002 }, @@ -197,15 +200,13 @@ nve4_grctx_init_icmd[] = {  	{ 0x000787,   1, 0x01, 0x000000cf },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x000836,   1, 0x01, 0x00000001 },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x000b07,   1, 0x01, 0x00000002 },  	{ 0x000b08,   2, 0x01, 0x00000100 }, @@ -231,14 +232,12 @@ nve4_grctx_init_icmd[] = {  	{ 0x0006b1,   1, 0x01, 0x00000011 },  	{ 0x00078c,   1, 0x01, 0x00000008 },  	{ 0x000792,   1, 0x01, 0x00000001 }, -	{ 0x000794,   1, 0x01, 0x00000001 }, -	{ 0x000795,   2, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 },  	{ 0x000797,   1, 0x01, 0x000000cf },  	{ 0x00079a,   1, 0x01, 0x00000002 },  	{ 0x000833,   1, 0x01, 0x04444480 },  	{ 0x0007a1,   1, 0x01, 0x00000001 }, -	{ 0x0007a3,   1, 0x01, 0x00000001 }, -	{ 0x0007a4,   2, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 },  	{ 0x000831,   1, 0x01, 0x00000004 },  	{ 0x01e100,   1, 0x01, 0x00000001 },  	{ 0x001000,   1, 0x01, 0x00000008 }, @@ -273,8 +272,14 @@ nve4_grctx_init_icmd[] = {  	{}  }; -struct nvc0_graph_init -nve4_grctx_init_a097[] = { +const struct nvc0_graph_pack +nve4_grctx_pack_icmd[] = { +	{ nve4_grctx_init_icmd_0 }, +	{} +}; + +const struct nvc0_graph_init +nve4_grctx_init_a097_0[] = {  	{ 0x000800,   8, 0x40, 0x00000000 },  	{ 0x000804,   8, 0x40, 0x00000000 },  	{ 0x000808,   8, 0x40, 0x00000400 }, @@ -517,8 +522,7 @@ nve4_grctx_init_a097[] = {  	{ 0x001350,   1, 0x04, 0x00000002 },  	{ 0x001358,   1, 0x04, 0x00000001 },  	{ 0x0012e4,   1, 0x04, 0x00000000 }, -	{ 0x00131c,   1, 0x04, 0x00000000 }, -	{ 0x001320,   3, 0x04, 0x00000000 }, +	{ 0x00131c,   4, 0x04, 0x00000000 },  	{ 0x0019c0,   1, 0x04, 0x00000000 },  	{ 0x001140,   1, 0x04, 0x00000000 },  	{ 0x0019c4,   1, 0x04, 0x00000000 }, @@ -574,19 +578,24 @@ nve4_grctx_init_a097[] = {  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_unk40xx[] = { +static const struct nvc0_graph_pack +nve4_grctx_pack_mthd[] = { +	{ nve4_grctx_init_a097_0, 0xa097 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_fe_0[] = {  	{ 0x404010,   5, 0x04, 0x00000000 },  	{ 0x404024,   1, 0x04, 0x0000e000 },  	{ 0x404028,   1, 0x04, 0x00000000 }, -	{ 0x4040a8,   1, 0x04, 0x00000000 }, -	{ 0x4040ac,   7, 0x04, 0x00000000 }, +	{ 0x4040a8,   8, 0x04, 0x00000000 },  	{ 0x4040c8,   1, 0x04, 0xf800008f },  	{ 0x4040d0,   6, 0x04, 0x00000000 },  	{ 0x4040e8,   1, 0x04, 0x00001000 },  	{ 0x4040f8,   1, 0x04, 0x00000000 }, -	{ 0x404130,   1, 0x04, 0x00000000 }, -	{ 0x404134,   1, 0x04, 0x00000000 }, +	{ 0x404130,   2, 0x04, 0x00000000 },  	{ 0x404138,   1, 0x04, 0x20000040 },  	{ 0x404150,   1, 0x04, 0x0000002e },  	{ 0x404154,   1, 0x04, 0x00000400 }, @@ -597,8 +606,8 @@ nve4_grctx_init_unk40xx[] = {  	{}  }; -struct nvc0_graph_init -nve4_grctx_init_unk46xx[] = { +const struct nvc0_graph_init +nve4_grctx_init_memfmt_0[] = {  	{ 0x404604,   1, 0x04, 0x00000014 },  	{ 0x404608,   1, 0x04, 0x00000000 },  	{ 0x40460c,   1, 0x04, 0x00003fff }, @@ -614,11 +623,6 @@ nve4_grctx_init_unk46xx[] = {  	{ 0x4046a0,   1, 0x04, 0x007f0080 },  	{ 0x4046a4,   8, 0x04, 0x00000000 },  	{ 0x4046c8,   3, 0x04, 0x00000000 }, -	{} -}; - -struct nvc0_graph_init -nve4_grctx_init_unk47xx[] = {  	{ 0x404700,   3, 0x04, 0x00000000 },  	{ 0x404718,   7, 0x04, 0x00000000 },  	{ 0x404734,   1, 0x04, 0x00000100 }, @@ -628,8 +632,8 @@ nve4_grctx_init_unk47xx[] = {  	{}  }; -struct nvc0_graph_init -nve4_grctx_init_unk58xx[] = { +const struct nvc0_graph_init +nve4_grctx_init_ds_0[] = {  	{ 0x405800,   1, 0x04, 0x0f8000bf },  	{ 0x405830,   1, 0x04, 0x02180648 },  	{ 0x405834,   1, 0x04, 0x08000000 }, @@ -641,22 +645,17 @@ nve4_grctx_init_unk58xx[] = {  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_unk5bxx[] = { +static const struct nvc0_graph_init +nve4_grctx_init_cwd_0[] = {  	{ 0x405b00,   1, 0x04, 0x00000000 },  	{ 0x405b10,   1, 0x04, 0x00001000 },  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_unk60xx[] = { +static const struct nvc0_graph_init +nve4_grctx_init_pd_0[] = {  	{ 0x406020,   1, 0x04, 0x004103c1 },  	{ 0x406028,   4, 0x04, 0x00000001 }, -	{} -}; - -static struct nvc0_graph_init -nve4_grctx_init_unk64xx[] = {  	{ 0x4064a8,   1, 0x04, 0x00000000 },  	{ 0x4064ac,   1, 0x04, 0x00003fff },  	{ 0x4064b4,   2, 0x04, 0x00000000 }, @@ -668,14 +667,14 @@ nve4_grctx_init_unk64xx[] = {  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_unk70xx[] = { +static const struct nvc0_graph_init +nve4_grctx_init_sked_0[] = {  	{ 0x407040,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nve4_grctx_init_unk80xx[] = { +const struct nvc0_graph_init +nve4_grctx_init_scc_0[] = {  	{ 0x408000,   2, 0x04, 0x00000000 },  	{ 0x408008,   1, 0x04, 0x00000030 },  	{ 0x40800c,   2, 0x04, 0x00000000 }, @@ -685,8 +684,8 @@ nve4_grctx_init_unk80xx[] = {  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_rop[] = { +static const struct nvc0_graph_init +nve4_grctx_init_be_0[] = {  	{ 0x408800,   1, 0x04, 0x02802a3c },  	{ 0x408804,   1, 0x04, 0x00000040 },  	{ 0x408808,   1, 0x04, 0x1043e005 }, @@ -698,22 +697,24 @@ nve4_grctx_init_rop[] = {  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_gpc_0[] = { -	{ 0x418380,   1, 0x04, 0x00000016 }, -	{ 0x418400,   1, 0x04, 0x38004e00 }, -	{ 0x418404,   1, 0x04, 0x71e0ffff }, -	{ 0x41840c,   1, 0x04, 0x00001008 }, -	{ 0x418410,   1, 0x04, 0x0fff0fff }, -	{ 0x418414,   1, 0x04, 0x02200fff }, -	{ 0x418450,   6, 0x04, 0x00000000 }, -	{ 0x418468,   1, 0x04, 0x00000001 }, -	{ 0x41846c,   2, 0x04, 0x00000000 }, -	{ 0x418600,   1, 0x04, 0x0000001f }, -	{ 0x418684,   1, 0x04, 0x0000000f }, -	{ 0x418700,   1, 0x04, 0x00000002 }, -	{ 0x418704,   1, 0x04, 0x00000080 }, -	{ 0x418708,   3, 0x04, 0x00000000 }, +const struct nvc0_graph_pack +nve4_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nve4_grctx_init_fe_0 }, +	{ nvc0_grctx_init_pri_0 }, +	{ nve4_grctx_init_memfmt_0 }, +	{ nve4_grctx_init_ds_0 }, +	{ nve4_grctx_init_cwd_0 }, +	{ nve4_grctx_init_pd_0 }, +	{ nve4_grctx_init_sked_0 }, +	{ nvc0_grctx_init_rstr2d_0 }, +	{ nve4_grctx_init_scc_0 }, +	{ nve4_grctx_init_be_0 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_setup_0[] = {  	{ 0x418800,   1, 0x04, 0x7006860a },  	{ 0x418808,   3, 0x04, 0x00000000 },  	{ 0x418828,   1, 0x04, 0x00000044 }, @@ -722,35 +723,35 @@ nve4_grctx_init_gpc_0[] = {  	{ 0x4188e0,   1, 0x04, 0x01000000 },  	{ 0x4188e8,   5, 0x04, 0x00000000 },  	{ 0x4188fc,   1, 0x04, 0x20100018 }, -	{ 0x41891c,   1, 0x04, 0x00ff00ff }, -	{ 0x418924,   1, 0x04, 0x00000000 }, -	{ 0x418928,   1, 0x04, 0x00ffff00 }, -	{ 0x41892c,   1, 0x04, 0x0000ff00 }, -	{ 0x418b00,   1, 0x04, 0x00000006 }, -	{ 0x418b08,   1, 0x04, 0x0a418820 }, -	{ 0x418b0c,   1, 0x04, 0x062080e6 }, -	{ 0x418b10,   1, 0x04, 0x020398a4 }, -	{ 0x418b14,   1, 0x04, 0x0e629062 }, -	{ 0x418b18,   1, 0x04, 0x0a418820 }, -	{ 0x418b1c,   1, 0x04, 0x000000e6 }, -	{ 0x418bb8,   1, 0x04, 0x00000103 }, +	{} +}; + +const struct nvc0_graph_init +nve4_grctx_init_gpm_0[] = {  	{ 0x418c08,   1, 0x04, 0x00000001 },  	{ 0x418c10,   8, 0x04, 0x00000000 },  	{ 0x418c40,   1, 0x04, 0xffffffff },  	{ 0x418c6c,   1, 0x04, 0x00000001 },  	{ 0x418c80,   1, 0x04, 0x20200004 },  	{ 0x418c8c,   1, 0x04, 0x00000001 }, -	{ 0x419000,   1, 0x04, 0x00000780 }, -	{ 0x419004,   2, 0x04, 0x00000000 }, -	{ 0x419014,   1, 0x04, 0x00000004 },  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_tpc[] = { -	{ 0x419848,   1, 0x04, 0x00000000 }, -	{ 0x419864,   1, 0x04, 0x00000129 }, -	{ 0x419888,   1, 0x04, 0x00000000 }, +const struct nvc0_graph_pack +nve4_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvd9_grctx_init_prop_0 }, +	{ nvd9_grctx_init_gpc_unk_1 }, +	{ nve4_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvd9_grctx_init_crstr_0 }, +	{ nve4_grctx_init_gpm_0 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_tex_0[] = {  	{ 0x419a00,   1, 0x04, 0x000000f0 },  	{ 0x419a04,   1, 0x04, 0x00000001 },  	{ 0x419a08,   1, 0x04, 0x00000021 }, @@ -761,14 +762,29 @@ nve4_grctx_init_tpc[] = {  	{ 0x419a20,   1, 0x04, 0x00000800 },  	{ 0x419a30,   1, 0x04, 0x00000001 },  	{ 0x419ac4,   1, 0x04, 0x0037f440 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_mpc_0[] = {  	{ 0x419c00,   1, 0x04, 0x0000000a },  	{ 0x419c04,   1, 0x04, 0x80000006 },  	{ 0x419c08,   1, 0x04, 0x00000002 },  	{ 0x419c20,   1, 0x04, 0x00000000 },  	{ 0x419c24,   1, 0x04, 0x00084210 },  	{ 0x419c28,   1, 0x04, 0x3efbefbe }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_l1c_0[] = {  	{ 0x419ce8,   1, 0x04, 0x00000000 },  	{ 0x419cf4,   1, 0x04, 0x00003203 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_sm_0[] = {  	{ 0x419e04,   3, 0x04, 0x00000000 },  	{ 0x419e10,   1, 0x04, 0x00000402 },  	{ 0x419e44,   1, 0x04, 0x0013eff2 }, @@ -782,29 +798,47 @@ nve4_grctx_init_tpc[] = {  	{ 0x419f58,   1, 0x04, 0x00000000 },  	{ 0x419f70,   1, 0x04, 0x00000000 },  	{ 0x419f78,   1, 0x04, 0x0000000b }, -	{ 0x419f7c,   1, 0x04, 0x0000027a }, +	{ 0x419f7c,   1, 0x04, 0x0000027c },  	{}  }; -static struct nvc0_graph_init -nve4_grctx_init_unk[] = { +const struct nvc0_graph_pack +nve4_grctx_pack_tpc[] = { +	{ nvd7_grctx_init_pe_0 }, +	{ nve4_grctx_init_tex_0 }, +	{ nve4_grctx_init_mpc_0 }, +	{ nve4_grctx_init_l1c_0 }, +	{ nve4_grctx_init_sm_0 }, +	{} +}; + +const struct nvc0_graph_init +nve4_grctx_init_pes_0[] = {  	{ 0x41be24,   1, 0x04, 0x00000006 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_grctx_init_cbm_0[] = {  	{ 0x41bec0,   1, 0x04, 0x12180000 },  	{ 0x41bec4,   1, 0x04, 0x00037f7f },  	{ 0x41bee4,   1, 0x04, 0x06480430 }, -	{ 0x41bf00,   1, 0x04, 0x0a418820 }, -	{ 0x41bf04,   1, 0x04, 0x062080e6 }, -	{ 0x41bf08,   1, 0x04, 0x020398a4 }, -	{ 0x41bf0c,   1, 0x04, 0x0e629062 }, -	{ 0x41bf10,   1, 0x04, 0x0a418820 }, -	{ 0x41bf14,   1, 0x04, 0x000000e6 }, -	{ 0x41bfd0,   1, 0x04, 0x00900103 }, -	{ 0x41bfe0,   1, 0x04, 0x00400001 }, -	{ 0x41bfe4,   1, 0x04, 0x00000000 },  	{}  }; -static void +const struct nvc0_graph_pack +nve4_grctx_pack_ppc[] = { +	{ nve4_grctx_init_pes_0 }, +	{ nve4_grctx_init_cbm_0 }, +	{ nvd7_grctx_init_wwdx_0 }, +	{} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ + +void  nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  {  	u32 magic[GPC_MAX][2]; @@ -925,10 +959,11 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  	nv_mask(priv, 0x000260, 0x00000001, 0x00000000); -	for (i = 0; oclass->hub[i]; i++) -		nvc0_graph_mmio(priv, oclass->hub[i]); -	for (i = 0; oclass->gpc[i]; i++) -		nvc0_graph_mmio(priv, oclass->gpc[i]); +	nvc0_graph_mmio(priv, oclass->hub); +	nvc0_graph_mmio(priv, oclass->gpc); +	nvc0_graph_mmio(priv, oclass->zcull); +	nvc0_graph_mmio(priv, oclass->tpc); +	nvc0_graph_mmio(priv, oclass->ppc);  	nv_wr32(priv, 0x404154, 0x00000000); @@ -962,41 +997,6 @@ nve4_grctx_generate_main(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  	nv_mask(priv, 0x41be10, 0x00800000, 0x00800000);  } -static struct nvc0_graph_init * -nve4_grctx_init_hub[] = { -	nvc0_grctx_init_base, -	nve4_grctx_init_unk40xx, -	nvc0_grctx_init_unk44xx, -	nve4_grctx_init_unk46xx, -	nve4_grctx_init_unk47xx, -	nve4_grctx_init_unk58xx, -	nve4_grctx_init_unk5bxx, -	nve4_grctx_init_unk60xx, -	nve4_grctx_init_unk64xx, -	nve4_grctx_init_unk70xx, -	nvc0_grctx_init_unk78xx, -	nve4_grctx_init_unk80xx, -	nve4_grctx_init_rop, -	NULL -}; - -struct nvc0_graph_init * -nve4_grctx_init_gpc[] = { -	nve4_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nve4_grctx_init_tpc, -	nve4_grctx_init_unk, -	NULL -}; - -static struct nvc0_graph_mthd -nve4_grctx_init_mthd[] = { -	{ 0xa097, nve4_grctx_init_a097, }, -	{ 0x902d, nvc0_grctx_init_902d, }, -	{ 0x902d, nvc0_grctx_init_mthd_magic, }, -	{} -}; -  struct nouveau_oclass *  nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xe4), @@ -1008,11 +1008,14 @@ nve4_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nve4_grctx_generate_main, -	.mods = nve4_grctx_generate_mods, -	.unkn = nve4_grctx_generate_unkn, -	.hub  = nve4_grctx_init_hub, -	.gpc  = nve4_grctx_init_gpc, -	.icmd = nve4_grctx_init_icmd, -	.mthd = nve4_grctx_init_mthd, +	.main  = nve4_grctx_generate_main, +	.mods  = nve4_grctx_generate_mods, +	.unkn  = nve4_grctx_generate_unkn, +	.hub   = nve4_grctx_pack_hub, +	.gpc   = nve4_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nve4_grctx_pack_tpc, +	.ppc   = nve4_grctx_pack_ppc, +	.icmd  = nve4_grctx_pack_icmd, +	.mthd  = nve4_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c index dcb2ebb8c29..dec03f04114 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c @@ -22,10 +22,580 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include "nvc0.h" +#include "ctxnvc0.h" -static struct nvc0_graph_init -nvf0_grctx_init_unk40xx[] = { +/******************************************************************************* + * PGRAPH context register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nvf0_grctx_init_icmd_0[] = { +	{ 0x001000,   1, 0x01, 0x00000004 }, +	{ 0x000039,   3, 0x01, 0x00000000 }, +	{ 0x0000a9,   1, 0x01, 0x0000ffff }, +	{ 0x000038,   1, 0x01, 0x0fac6881 }, +	{ 0x00003d,   1, 0x01, 0x00000001 }, +	{ 0x0000e8,   8, 0x01, 0x00000400 }, +	{ 0x000078,   8, 0x01, 0x00000300 }, +	{ 0x000050,   1, 0x01, 0x00000011 }, +	{ 0x000058,   8, 0x01, 0x00000008 }, +	{ 0x000208,   8, 0x01, 0x00000001 }, +	{ 0x000081,   1, 0x01, 0x00000001 }, +	{ 0x000085,   1, 0x01, 0x00000004 }, +	{ 0x000088,   1, 0x01, 0x00000400 }, +	{ 0x000090,   1, 0x01, 0x00000300 }, +	{ 0x000098,   1, 0x01, 0x00001001 }, +	{ 0x0000e3,   1, 0x01, 0x00000001 }, +	{ 0x0000da,   1, 0x01, 0x00000001 }, +	{ 0x0000f8,   1, 0x01, 0x00000003 }, +	{ 0x0000fa,   1, 0x01, 0x00000001 }, +	{ 0x00009f,   4, 0x01, 0x0000ffff }, +	{ 0x0000b1,   1, 0x01, 0x00000001 }, +	{ 0x0000ad,   1, 0x01, 0x0000013e }, +	{ 0x0000e1,   1, 0x01, 0x00000010 }, +	{ 0x000290,  16, 0x01, 0x00000000 }, +	{ 0x0003b0,  16, 0x01, 0x00000000 }, +	{ 0x0002a0,  16, 0x01, 0x00000000 }, +	{ 0x000420,  16, 0x01, 0x00000000 }, +	{ 0x0002b0,  16, 0x01, 0x00000000 }, +	{ 0x000430,  16, 0x01, 0x00000000 }, +	{ 0x0002c0,  16, 0x01, 0x00000000 }, +	{ 0x0004d0,  16, 0x01, 0x00000000 }, +	{ 0x000720,  16, 0x01, 0x00000000 }, +	{ 0x0008c0,  16, 0x01, 0x00000000 }, +	{ 0x000890,  16, 0x01, 0x00000000 }, +	{ 0x0008e0,  16, 0x01, 0x00000000 }, +	{ 0x0008a0,  16, 0x01, 0x00000000 }, +	{ 0x0008f0,  16, 0x01, 0x00000000 }, +	{ 0x00094c,   1, 0x01, 0x000000ff }, +	{ 0x00094d,   1, 0x01, 0xffffffff }, +	{ 0x00094e,   1, 0x01, 0x00000002 }, +	{ 0x0002ec,   1, 0x01, 0x00000001 }, +	{ 0x0002f2,   2, 0x01, 0x00000001 }, +	{ 0x0002f5,   1, 0x01, 0x00000001 }, +	{ 0x0002f7,   1, 0x01, 0x00000001 }, +	{ 0x000303,   1, 0x01, 0x00000001 }, +	{ 0x0002e6,   1, 0x01, 0x00000001 }, +	{ 0x000466,   1, 0x01, 0x00000052 }, +	{ 0x000301,   1, 0x01, 0x3f800000 }, +	{ 0x000304,   1, 0x01, 0x30201000 }, +	{ 0x000305,   1, 0x01, 0x70605040 }, +	{ 0x000306,   1, 0x01, 0xb8a89888 }, +	{ 0x000307,   1, 0x01, 0xf8e8d8c8 }, +	{ 0x00030a,   1, 0x01, 0x00ffff00 }, +	{ 0x00030b,   1, 0x01, 0x0000001a }, +	{ 0x00030c,   1, 0x01, 0x00000001 }, +	{ 0x000318,   1, 0x01, 0x00000001 }, +	{ 0x000340,   1, 0x01, 0x00000000 }, +	{ 0x000375,   1, 0x01, 0x00000001 }, +	{ 0x00037d,   1, 0x01, 0x00000006 }, +	{ 0x0003a0,   1, 0x01, 0x00000002 }, +	{ 0x0003aa,   1, 0x01, 0x00000001 }, +	{ 0x0003a9,   1, 0x01, 0x00000001 }, +	{ 0x000380,   1, 0x01, 0x00000001 }, +	{ 0x000383,   1, 0x01, 0x00000011 }, +	{ 0x000360,   1, 0x01, 0x00000040 }, +	{ 0x000366,   2, 0x01, 0x00000000 }, +	{ 0x000368,   1, 0x01, 0x00000fff }, +	{ 0x000370,   2, 0x01, 0x00000000 }, +	{ 0x000372,   1, 0x01, 0x000fffff }, +	{ 0x00037a,   1, 0x01, 0x00000012 }, +	{ 0x000619,   1, 0x01, 0x00000003 }, +	{ 0x000811,   1, 0x01, 0x00000003 }, +	{ 0x000812,   1, 0x01, 0x00000004 }, +	{ 0x000813,   1, 0x01, 0x00000006 }, +	{ 0x000814,   1, 0x01, 0x00000008 }, +	{ 0x000815,   1, 0x01, 0x0000000b }, +	{ 0x000800,   6, 0x01, 0x00000001 }, +	{ 0x000632,   1, 0x01, 0x00000001 }, +	{ 0x000633,   1, 0x01, 0x00000002 }, +	{ 0x000634,   1, 0x01, 0x00000003 }, +	{ 0x000635,   1, 0x01, 0x00000004 }, +	{ 0x000654,   1, 0x01, 0x3f800000 }, +	{ 0x000657,   1, 0x01, 0x3f800000 }, +	{ 0x000655,   2, 0x01, 0x3f800000 }, +	{ 0x0006cd,   1, 0x01, 0x3f800000 }, +	{ 0x0007f5,   1, 0x01, 0x3f800000 }, +	{ 0x0007dc,   1, 0x01, 0x39291909 }, +	{ 0x0007dd,   1, 0x01, 0x79695949 }, +	{ 0x0007de,   1, 0x01, 0xb9a99989 }, +	{ 0x0007df,   1, 0x01, 0xf9e9d9c9 }, +	{ 0x0007e8,   1, 0x01, 0x00003210 }, +	{ 0x0007e9,   1, 0x01, 0x00007654 }, +	{ 0x0007ea,   1, 0x01, 0x00000098 }, +	{ 0x0007ec,   1, 0x01, 0x39291909 }, +	{ 0x0007ed,   1, 0x01, 0x79695949 }, +	{ 0x0007ee,   1, 0x01, 0xb9a99989 }, +	{ 0x0007ef,   1, 0x01, 0xf9e9d9c9 }, +	{ 0x0007f0,   1, 0x01, 0x00003210 }, +	{ 0x0007f1,   1, 0x01, 0x00007654 }, +	{ 0x0007f2,   1, 0x01, 0x00000098 }, +	{ 0x0005a5,   1, 0x01, 0x00000001 }, +	{ 0x000980, 128, 0x01, 0x00000000 }, +	{ 0x000468,   1, 0x01, 0x00000004 }, +	{ 0x00046c,   1, 0x01, 0x00000001 }, +	{ 0x000470,  96, 0x01, 0x00000000 }, +	{ 0x000510,  16, 0x01, 0x3f800000 }, +	{ 0x000520,   1, 0x01, 0x000002b6 }, +	{ 0x000529,   1, 0x01, 0x00000001 }, +	{ 0x000530,  16, 0x01, 0xffff0000 }, +	{ 0x000585,   1, 0x01, 0x0000003f }, +	{ 0x000576,   1, 0x01, 0x00000003 }, +	{ 0x00057b,   1, 0x01, 0x00000059 }, +	{ 0x000586,   1, 0x01, 0x00000040 }, +	{ 0x000582,   2, 0x01, 0x00000080 }, +	{ 0x0005c2,   1, 0x01, 0x00000001 }, +	{ 0x000638,   2, 0x01, 0x00000001 }, +	{ 0x00063a,   1, 0x01, 0x00000002 }, +	{ 0x00063b,   2, 0x01, 0x00000001 }, +	{ 0x00063d,   1, 0x01, 0x00000002 }, +	{ 0x00063e,   1, 0x01, 0x00000001 }, +	{ 0x0008b8,   8, 0x01, 0x00000001 }, +	{ 0x000900,   8, 0x01, 0x00000001 }, +	{ 0x000908,   8, 0x01, 0x00000002 }, +	{ 0x000910,  16, 0x01, 0x00000001 }, +	{ 0x000920,   8, 0x01, 0x00000002 }, +	{ 0x000928,   8, 0x01, 0x00000001 }, +	{ 0x000662,   1, 0x01, 0x00000001 }, +	{ 0x000648,   9, 0x01, 0x00000001 }, +	{ 0x000658,   1, 0x01, 0x0000000f }, +	{ 0x0007ff,   1, 0x01, 0x0000000a }, +	{ 0x00066a,   1, 0x01, 0x40000000 }, +	{ 0x00066b,   1, 0x01, 0x10000000 }, +	{ 0x00066c,   2, 0x01, 0xffff0000 }, +	{ 0x0007af,   2, 0x01, 0x00000008 }, +	{ 0x0007f6,   1, 0x01, 0x00000001 }, +	{ 0x00080b,   1, 0x01, 0x00000002 }, +	{ 0x0006b2,   1, 0x01, 0x00000055 }, +	{ 0x0007ad,   1, 0x01, 0x00000003 }, +	{ 0x000937,   1, 0x01, 0x00000001 }, +	{ 0x000971,   1, 0x01, 0x00000008 }, +	{ 0x000972,   1, 0x01, 0x00000040 }, +	{ 0x000973,   1, 0x01, 0x0000012c }, +	{ 0x00097c,   1, 0x01, 0x00000040 }, +	{ 0x000979,   1, 0x01, 0x00000003 }, +	{ 0x000975,   1, 0x01, 0x00000020 }, +	{ 0x000976,   1, 0x01, 0x00000001 }, +	{ 0x000977,   1, 0x01, 0x00000020 }, +	{ 0x000978,   1, 0x01, 0x00000001 }, +	{ 0x000957,   1, 0x01, 0x00000003 }, +	{ 0x00095e,   1, 0x01, 0x20164010 }, +	{ 0x00095f,   1, 0x01, 0x00000020 }, +	{ 0x000a0d,   1, 0x01, 0x00000006 }, +	{ 0x00097d,   1, 0x01, 0x00000020 }, +	{ 0x000683,   1, 0x01, 0x00000006 }, +	{ 0x000685,   1, 0x01, 0x003fffff }, +	{ 0x000687,   1, 0x01, 0x003fffff }, +	{ 0x0006a0,   1, 0x01, 0x00000005 }, +	{ 0x000840,   1, 0x01, 0x00400008 }, +	{ 0x000841,   1, 0x01, 0x08000080 }, +	{ 0x000842,   1, 0x01, 0x00400008 }, +	{ 0x000843,   1, 0x01, 0x08000080 }, +	{ 0x0006aa,   1, 0x01, 0x00000001 }, +	{ 0x0006ab,   1, 0x01, 0x00000002 }, +	{ 0x0006ac,   1, 0x01, 0x00000080 }, +	{ 0x0006ad,   2, 0x01, 0x00000100 }, +	{ 0x0006b1,   1, 0x01, 0x00000011 }, +	{ 0x0006bb,   1, 0x01, 0x000000cf }, +	{ 0x0006ce,   1, 0x01, 0x2a712488 }, +	{ 0x000739,   1, 0x01, 0x4085c000 }, +	{ 0x00073a,   1, 0x01, 0x00000080 }, +	{ 0x000786,   1, 0x01, 0x80000100 }, +	{ 0x00073c,   1, 0x01, 0x00010100 }, +	{ 0x00073d,   1, 0x01, 0x02800000 }, +	{ 0x000787,   1, 0x01, 0x000000cf }, +	{ 0x00078c,   1, 0x01, 0x00000008 }, +	{ 0x000792,   1, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 }, +	{ 0x000797,   1, 0x01, 0x000000cf }, +	{ 0x000836,   1, 0x01, 0x00000001 }, +	{ 0x00079a,   1, 0x01, 0x00000002 }, +	{ 0x000833,   1, 0x01, 0x04444480 }, +	{ 0x0007a1,   1, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 }, +	{ 0x000831,   1, 0x01, 0x00000004 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x000a04,   1, 0x01, 0x000000ff }, +	{ 0x000a0b,   1, 0x01, 0x00000040 }, +	{ 0x00097f,   1, 0x01, 0x00000100 }, +	{ 0x000a02,   1, 0x01, 0x00000001 }, +	{ 0x000809,   1, 0x01, 0x00000007 }, +	{ 0x00c221,   1, 0x01, 0x00000040 }, +	{ 0x00c1b0,   8, 0x01, 0x0000000f }, +	{ 0x00c1b8,   1, 0x01, 0x0fac6881 }, +	{ 0x00c1b9,   1, 0x01, 0x00fac688 }, +	{ 0x00c401,   1, 0x01, 0x00000001 }, +	{ 0x00c402,   1, 0x01, 0x00010001 }, +	{ 0x00c403,   2, 0x01, 0x00000001 }, +	{ 0x00c40e,   1, 0x01, 0x00000020 }, +	{ 0x00c500,   1, 0x01, 0x00000003 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000002 }, +	{ 0x0006aa,   1, 0x01, 0x00000001 }, +	{ 0x0006ad,   2, 0x01, 0x00000100 }, +	{ 0x0006b1,   1, 0x01, 0x00000011 }, +	{ 0x00078c,   1, 0x01, 0x00000008 }, +	{ 0x000792,   1, 0x01, 0x00000001 }, +	{ 0x000794,   3, 0x01, 0x00000001 }, +	{ 0x000797,   1, 0x01, 0x000000cf }, +	{ 0x00079a,   1, 0x01, 0x00000002 }, +	{ 0x000833,   1, 0x01, 0x04444480 }, +	{ 0x0007a1,   1, 0x01, 0x00000001 }, +	{ 0x0007a3,   3, 0x01, 0x00000001 }, +	{ 0x000831,   1, 0x01, 0x00000004 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000008 }, +	{ 0x000039,   3, 0x01, 0x00000000 }, +	{ 0x000380,   1, 0x01, 0x00000001 }, +	{ 0x000366,   2, 0x01, 0x00000000 }, +	{ 0x000368,   1, 0x01, 0x00000fff }, +	{ 0x000370,   2, 0x01, 0x00000000 }, +	{ 0x000372,   1, 0x01, 0x000fffff }, +	{ 0x000813,   1, 0x01, 0x00000006 }, +	{ 0x000814,   1, 0x01, 0x00000008 }, +	{ 0x000957,   1, 0x01, 0x00000003 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x000a04,   1, 0x01, 0x000000ff }, +	{ 0x000a0b,   1, 0x01, 0x00000040 }, +	{ 0x00097f,   1, 0x01, 0x00000100 }, +	{ 0x000a02,   1, 0x01, 0x00000001 }, +	{ 0x000809,   1, 0x01, 0x00000007 }, +	{ 0x00c221,   1, 0x01, 0x00000040 }, +	{ 0x00c401,   1, 0x01, 0x00000001 }, +	{ 0x00c402,   1, 0x01, 0x00010001 }, +	{ 0x00c403,   2, 0x01, 0x00000001 }, +	{ 0x00c40e,   1, 0x01, 0x00000020 }, +	{ 0x00c500,   1, 0x01, 0x00000003 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{ 0x001000,   1, 0x01, 0x00000001 }, +	{ 0x000b07,   1, 0x01, 0x00000002 }, +	{ 0x000b08,   2, 0x01, 0x00000100 }, +	{ 0x000b0a,   1, 0x01, 0x00000001 }, +	{ 0x01e100,   1, 0x01, 0x00000001 }, +	{} +}; + +static const struct nvc0_graph_pack +nvf0_grctx_pack_icmd[] = { +	{ nvf0_grctx_init_icmd_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_grctx_init_a197_0[] = { +	{ 0x000800,   8, 0x40, 0x00000000 }, +	{ 0x000804,   8, 0x40, 0x00000000 }, +	{ 0x000808,   8, 0x40, 0x00000400 }, +	{ 0x00080c,   8, 0x40, 0x00000300 }, +	{ 0x000810,   1, 0x04, 0x000000cf }, +	{ 0x000850,   7, 0x40, 0x00000000 }, +	{ 0x000814,   8, 0x40, 0x00000040 }, +	{ 0x000818,   8, 0x40, 0x00000001 }, +	{ 0x00081c,   8, 0x40, 0x00000000 }, +	{ 0x000820,   8, 0x40, 0x00000000 }, +	{ 0x001c00,  16, 0x10, 0x00000000 }, +	{ 0x001c04,  16, 0x10, 0x00000000 }, +	{ 0x001c08,  16, 0x10, 0x00000000 }, +	{ 0x001c0c,  16, 0x10, 0x00000000 }, +	{ 0x001d00,  16, 0x10, 0x00000000 }, +	{ 0x001d04,  16, 0x10, 0x00000000 }, +	{ 0x001d08,  16, 0x10, 0x00000000 }, +	{ 0x001d0c,  16, 0x10, 0x00000000 }, +	{ 0x001f00,  16, 0x08, 0x00000000 }, +	{ 0x001f04,  16, 0x08, 0x00000000 }, +	{ 0x001f80,  16, 0x08, 0x00000000 }, +	{ 0x001f84,  16, 0x08, 0x00000000 }, +	{ 0x002000,   1, 0x04, 0x00000000 }, +	{ 0x002040,   1, 0x04, 0x00000011 }, +	{ 0x002080,   1, 0x04, 0x00000020 }, +	{ 0x0020c0,   1, 0x04, 0x00000030 }, +	{ 0x002100,   1, 0x04, 0x00000040 }, +	{ 0x002140,   1, 0x04, 0x00000051 }, +	{ 0x00200c,   6, 0x40, 0x00000001 }, +	{ 0x002010,   1, 0x04, 0x00000000 }, +	{ 0x002050,   1, 0x04, 0x00000000 }, +	{ 0x002090,   1, 0x04, 0x00000001 }, +	{ 0x0020d0,   1, 0x04, 0x00000002 }, +	{ 0x002110,   1, 0x04, 0x00000003 }, +	{ 0x002150,   1, 0x04, 0x00000004 }, +	{ 0x000380,   4, 0x20, 0x00000000 }, +	{ 0x000384,   4, 0x20, 0x00000000 }, +	{ 0x000388,   4, 0x20, 0x00000000 }, +	{ 0x00038c,   4, 0x20, 0x00000000 }, +	{ 0x000700,   4, 0x10, 0x00000000 }, +	{ 0x000704,   4, 0x10, 0x00000000 }, +	{ 0x000708,   4, 0x10, 0x00000000 }, +	{ 0x002800, 128, 0x04, 0x00000000 }, +	{ 0x000a00,  16, 0x20, 0x00000000 }, +	{ 0x000a04,  16, 0x20, 0x00000000 }, +	{ 0x000a08,  16, 0x20, 0x00000000 }, +	{ 0x000a0c,  16, 0x20, 0x00000000 }, +	{ 0x000a10,  16, 0x20, 0x00000000 }, +	{ 0x000a14,  16, 0x20, 0x00000000 }, +	{ 0x000c00,  16, 0x10, 0x00000000 }, +	{ 0x000c04,  16, 0x10, 0x00000000 }, +	{ 0x000c08,  16, 0x10, 0x00000000 }, +	{ 0x000c0c,  16, 0x10, 0x3f800000 }, +	{ 0x000d00,   8, 0x08, 0xffff0000 }, +	{ 0x000d04,   8, 0x08, 0xffff0000 }, +	{ 0x000e00,  16, 0x10, 0x00000000 }, +	{ 0x000e04,  16, 0x10, 0xffff0000 }, +	{ 0x000e08,  16, 0x10, 0xffff0000 }, +	{ 0x000d40,   4, 0x08, 0x00000000 }, +	{ 0x000d44,   4, 0x08, 0x00000000 }, +	{ 0x001e00,   8, 0x20, 0x00000001 }, +	{ 0x001e04,   8, 0x20, 0x00000001 }, +	{ 0x001e08,   8, 0x20, 0x00000002 }, +	{ 0x001e0c,   8, 0x20, 0x00000001 }, +	{ 0x001e10,   8, 0x20, 0x00000001 }, +	{ 0x001e14,   8, 0x20, 0x00000002 }, +	{ 0x001e18,   8, 0x20, 0x00000001 }, +	{ 0x003400, 128, 0x04, 0x00000000 }, +	{ 0x00030c,   1, 0x04, 0x00000001 }, +	{ 0x001944,   1, 0x04, 0x00000000 }, +	{ 0x001514,   1, 0x04, 0x00000000 }, +	{ 0x000d68,   1, 0x04, 0x0000ffff }, +	{ 0x00121c,   1, 0x04, 0x0fac6881 }, +	{ 0x000fac,   1, 0x04, 0x00000001 }, +	{ 0x001538,   1, 0x04, 0x00000001 }, +	{ 0x000fe0,   2, 0x04, 0x00000000 }, +	{ 0x000fe8,   1, 0x04, 0x00000014 }, +	{ 0x000fec,   1, 0x04, 0x00000040 }, +	{ 0x000ff0,   1, 0x04, 0x00000000 }, +	{ 0x00179c,   1, 0x04, 0x00000000 }, +	{ 0x001228,   1, 0x04, 0x00000400 }, +	{ 0x00122c,   1, 0x04, 0x00000300 }, +	{ 0x001230,   1, 0x04, 0x00010001 }, +	{ 0x0007f8,   1, 0x04, 0x00000000 }, +	{ 0x0015b4,   1, 0x04, 0x00000001 }, +	{ 0x0015cc,   1, 0x04, 0x00000000 }, +	{ 0x001534,   1, 0x04, 0x00000000 }, +	{ 0x000fb0,   1, 0x04, 0x00000000 }, +	{ 0x0015d0,   1, 0x04, 0x00000000 }, +	{ 0x00153c,   1, 0x04, 0x00000000 }, +	{ 0x0016b4,   1, 0x04, 0x00000003 }, +	{ 0x000fbc,   4, 0x04, 0x0000ffff }, +	{ 0x000df8,   2, 0x04, 0x00000000 }, +	{ 0x001948,   1, 0x04, 0x00000000 }, +	{ 0x001970,   1, 0x04, 0x00000001 }, +	{ 0x00161c,   1, 0x04, 0x000009f0 }, +	{ 0x000dcc,   1, 0x04, 0x00000010 }, +	{ 0x00163c,   1, 0x04, 0x00000000 }, +	{ 0x0015e4,   1, 0x04, 0x00000000 }, +	{ 0x001160,  32, 0x04, 0x25e00040 }, +	{ 0x001880,  32, 0x04, 0x00000000 }, +	{ 0x000f84,   2, 0x04, 0x00000000 }, +	{ 0x0017c8,   2, 0x04, 0x00000000 }, +	{ 0x0017d0,   1, 0x04, 0x000000ff }, +	{ 0x0017d4,   1, 0x04, 0xffffffff }, +	{ 0x0017d8,   1, 0x04, 0x00000002 }, +	{ 0x0017dc,   1, 0x04, 0x00000000 }, +	{ 0x0015f4,   2, 0x04, 0x00000000 }, +	{ 0x001434,   2, 0x04, 0x00000000 }, +	{ 0x000d74,   1, 0x04, 0x00000000 }, +	{ 0x000dec,   1, 0x04, 0x00000001 }, +	{ 0x0013a4,   1, 0x04, 0x00000000 }, +	{ 0x001318,   1, 0x04, 0x00000001 }, +	{ 0x001644,   1, 0x04, 0x00000000 }, +	{ 0x000748,   1, 0x04, 0x00000000 }, +	{ 0x000de8,   1, 0x04, 0x00000000 }, +	{ 0x001648,   1, 0x04, 0x00000000 }, +	{ 0x0012a4,   1, 0x04, 0x00000000 }, +	{ 0x001120,   4, 0x04, 0x00000000 }, +	{ 0x001118,   1, 0x04, 0x00000000 }, +	{ 0x00164c,   1, 0x04, 0x00000000 }, +	{ 0x001658,   1, 0x04, 0x00000000 }, +	{ 0x001910,   1, 0x04, 0x00000290 }, +	{ 0x001518,   1, 0x04, 0x00000000 }, +	{ 0x00165c,   1, 0x04, 0x00000001 }, +	{ 0x001520,   1, 0x04, 0x00000000 }, +	{ 0x001604,   1, 0x04, 0x00000000 }, +	{ 0x001570,   1, 0x04, 0x00000000 }, +	{ 0x0013b0,   2, 0x04, 0x3f800000 }, +	{ 0x00020c,   1, 0x04, 0x00000000 }, +	{ 0x001670,   1, 0x04, 0x30201000 }, +	{ 0x001674,   1, 0x04, 0x70605040 }, +	{ 0x001678,   1, 0x04, 0xb8a89888 }, +	{ 0x00167c,   1, 0x04, 0xf8e8d8c8 }, +	{ 0x00166c,   1, 0x04, 0x00000000 }, +	{ 0x001680,   1, 0x04, 0x00ffff00 }, +	{ 0x0012d0,   1, 0x04, 0x00000003 }, +	{ 0x0012d4,   1, 0x04, 0x00000002 }, +	{ 0x001684,   2, 0x04, 0x00000000 }, +	{ 0x000dac,   2, 0x04, 0x00001b02 }, +	{ 0x000db4,   1, 0x04, 0x00000000 }, +	{ 0x00168c,   1, 0x04, 0x00000000 }, +	{ 0x0015bc,   1, 0x04, 0x00000000 }, +	{ 0x00156c,   1, 0x04, 0x00000000 }, +	{ 0x00187c,   1, 0x04, 0x00000000 }, +	{ 0x001110,   1, 0x04, 0x00000001 }, +	{ 0x000dc0,   3, 0x04, 0x00000000 }, +	{ 0x001234,   1, 0x04, 0x00000000 }, +	{ 0x001690,   1, 0x04, 0x00000000 }, +	{ 0x0012ac,   1, 0x04, 0x00000001 }, +	{ 0x0002c4,   1, 0x04, 0x00000000 }, +	{ 0x000790,   5, 0x04, 0x00000000 }, +	{ 0x00077c,   1, 0x04, 0x00000000 }, +	{ 0x001000,   1, 0x04, 0x00000010 }, +	{ 0x0010fc,   1, 0x04, 0x00000000 }, +	{ 0x001290,   1, 0x04, 0x00000000 }, +	{ 0x000218,   1, 0x04, 0x00000010 }, +	{ 0x0012d8,   1, 0x04, 0x00000000 }, +	{ 0x0012dc,   1, 0x04, 0x00000010 }, +	{ 0x000d94,   1, 0x04, 0x00000001 }, +	{ 0x00155c,   2, 0x04, 0x00000000 }, +	{ 0x001564,   1, 0x04, 0x00000fff }, +	{ 0x001574,   2, 0x04, 0x00000000 }, +	{ 0x00157c,   1, 0x04, 0x000fffff }, +	{ 0x001354,   1, 0x04, 0x00000000 }, +	{ 0x001610,   1, 0x04, 0x00000012 }, +	{ 0x001608,   2, 0x04, 0x00000000 }, +	{ 0x00260c,   1, 0x04, 0x00000000 }, +	{ 0x0007ac,   1, 0x04, 0x00000000 }, +	{ 0x00162c,   1, 0x04, 0x00000003 }, +	{ 0x000210,   1, 0x04, 0x00000000 }, +	{ 0x000320,   1, 0x04, 0x00000000 }, +	{ 0x000324,   6, 0x04, 0x3f800000 }, +	{ 0x000750,   1, 0x04, 0x00000000 }, +	{ 0x000760,   1, 0x04, 0x39291909 }, +	{ 0x000764,   1, 0x04, 0x79695949 }, +	{ 0x000768,   1, 0x04, 0xb9a99989 }, +	{ 0x00076c,   1, 0x04, 0xf9e9d9c9 }, +	{ 0x000770,   1, 0x04, 0x30201000 }, +	{ 0x000774,   1, 0x04, 0x70605040 }, +	{ 0x000778,   1, 0x04, 0x00009080 }, +	{ 0x000780,   1, 0x04, 0x39291909 }, +	{ 0x000784,   1, 0x04, 0x79695949 }, +	{ 0x000788,   1, 0x04, 0xb9a99989 }, +	{ 0x00078c,   1, 0x04, 0xf9e9d9c9 }, +	{ 0x0007d0,   1, 0x04, 0x30201000 }, +	{ 0x0007d4,   1, 0x04, 0x70605040 }, +	{ 0x0007d8,   1, 0x04, 0x00009080 }, +	{ 0x00037c,   1, 0x04, 0x00000001 }, +	{ 0x000740,   2, 0x04, 0x00000000 }, +	{ 0x002600,   1, 0x04, 0x00000000 }, +	{ 0x001918,   1, 0x04, 0x00000000 }, +	{ 0x00191c,   1, 0x04, 0x00000900 }, +	{ 0x001920,   1, 0x04, 0x00000405 }, +	{ 0x001308,   1, 0x04, 0x00000001 }, +	{ 0x001924,   1, 0x04, 0x00000000 }, +	{ 0x0013ac,   1, 0x04, 0x00000000 }, +	{ 0x00192c,   1, 0x04, 0x00000001 }, +	{ 0x00193c,   1, 0x04, 0x00002c1c }, +	{ 0x000d7c,   1, 0x04, 0x00000000 }, +	{ 0x000f8c,   1, 0x04, 0x00000000 }, +	{ 0x0002c0,   1, 0x04, 0x00000001 }, +	{ 0x001510,   1, 0x04, 0x00000000 }, +	{ 0x001940,   1, 0x04, 0x00000000 }, +	{ 0x000ff4,   2, 0x04, 0x00000000 }, +	{ 0x00194c,   2, 0x04, 0x00000000 }, +	{ 0x001968,   1, 0x04, 0x00000000 }, +	{ 0x001590,   1, 0x04, 0x0000003f }, +	{ 0x0007e8,   4, 0x04, 0x00000000 }, +	{ 0x00196c,   1, 0x04, 0x00000011 }, +	{ 0x0002e4,   1, 0x04, 0x0000b001 }, +	{ 0x00036c,   2, 0x04, 0x00000000 }, +	{ 0x00197c,   1, 0x04, 0x00000000 }, +	{ 0x000fcc,   2, 0x04, 0x00000000 }, +	{ 0x0002d8,   1, 0x04, 0x00000040 }, +	{ 0x001980,   1, 0x04, 0x00000080 }, +	{ 0x001504,   1, 0x04, 0x00000080 }, +	{ 0x001984,   1, 0x04, 0x00000000 }, +	{ 0x000300,   1, 0x04, 0x00000001 }, +	{ 0x0013a8,   1, 0x04, 0x00000000 }, +	{ 0x0012ec,   1, 0x04, 0x00000000 }, +	{ 0x001310,   1, 0x04, 0x00000000 }, +	{ 0x001314,   1, 0x04, 0x00000001 }, +	{ 0x001380,   1, 0x04, 0x00000000 }, +	{ 0x001384,   4, 0x04, 0x00000001 }, +	{ 0x001394,   1, 0x04, 0x00000000 }, +	{ 0x00139c,   1, 0x04, 0x00000000 }, +	{ 0x001398,   1, 0x04, 0x00000000 }, +	{ 0x001594,   1, 0x04, 0x00000000 }, +	{ 0x001598,   4, 0x04, 0x00000001 }, +	{ 0x000f54,   3, 0x04, 0x00000000 }, +	{ 0x0019bc,   1, 0x04, 0x00000000 }, +	{ 0x000f9c,   2, 0x04, 0x00000000 }, +	{ 0x0012cc,   1, 0x04, 0x00000000 }, +	{ 0x0012e8,   1, 0x04, 0x00000000 }, +	{ 0x00130c,   1, 0x04, 0x00000001 }, +	{ 0x001360,   8, 0x04, 0x00000000 }, +	{ 0x00133c,   2, 0x04, 0x00000001 }, +	{ 0x001344,   1, 0x04, 0x00000002 }, +	{ 0x001348,   2, 0x04, 0x00000001 }, +	{ 0x001350,   1, 0x04, 0x00000002 }, +	{ 0x001358,   1, 0x04, 0x00000001 }, +	{ 0x0012e4,   1, 0x04, 0x00000000 }, +	{ 0x00131c,   4, 0x04, 0x00000000 }, +	{ 0x0019c0,   1, 0x04, 0x00000000 }, +	{ 0x001140,   1, 0x04, 0x00000000 }, +	{ 0x0019c4,   1, 0x04, 0x00000000 }, +	{ 0x0019c8,   1, 0x04, 0x00001500 }, +	{ 0x00135c,   1, 0x04, 0x00000000 }, +	{ 0x000f90,   1, 0x04, 0x00000000 }, +	{ 0x0019e0,   8, 0x04, 0x00000001 }, +	{ 0x0019cc,   1, 0x04, 0x00000001 }, +	{ 0x0015b8,   1, 0x04, 0x00000000 }, +	{ 0x001a00,   1, 0x04, 0x00001111 }, +	{ 0x001a04,   7, 0x04, 0x00000000 }, +	{ 0x000d6c,   2, 0x04, 0xffff0000 }, +	{ 0x0010f8,   1, 0x04, 0x00001010 }, +	{ 0x000d80,   5, 0x04, 0x00000000 }, +	{ 0x000da0,   1, 0x04, 0x00000000 }, +	{ 0x0007a4,   2, 0x04, 0x00000000 }, +	{ 0x001508,   1, 0x04, 0x80000000 }, +	{ 0x00150c,   1, 0x04, 0x40000000 }, +	{ 0x001668,   1, 0x04, 0x00000000 }, +	{ 0x000318,   2, 0x04, 0x00000008 }, +	{ 0x000d9c,   1, 0x04, 0x00000001 }, +	{ 0x000ddc,   1, 0x04, 0x00000002 }, +	{ 0x000374,   1, 0x04, 0x00000000 }, +	{ 0x000378,   1, 0x04, 0x00000020 }, +	{ 0x0007dc,   1, 0x04, 0x00000000 }, +	{ 0x00074c,   1, 0x04, 0x00000055 }, +	{ 0x001420,   1, 0x04, 0x00000003 }, +	{ 0x0017bc,   2, 0x04, 0x00000000 }, +	{ 0x0017c4,   1, 0x04, 0x00000001 }, +	{ 0x001008,   1, 0x04, 0x00000008 }, +	{ 0x00100c,   1, 0x04, 0x00000040 }, +	{ 0x001010,   1, 0x04, 0x0000012c }, +	{ 0x000d60,   1, 0x04, 0x00000040 }, +	{ 0x00075c,   1, 0x04, 0x00000003 }, +	{ 0x001018,   1, 0x04, 0x00000020 }, +	{ 0x00101c,   1, 0x04, 0x00000001 }, +	{ 0x001020,   1, 0x04, 0x00000020 }, +	{ 0x001024,   1, 0x04, 0x00000001 }, +	{ 0x001444,   3, 0x04, 0x00000000 }, +	{ 0x000360,   1, 0x04, 0x20164010 }, +	{ 0x000364,   1, 0x04, 0x00000020 }, +	{ 0x000368,   1, 0x04, 0x00000000 }, +	{ 0x000de4,   1, 0x04, 0x00000000 }, +	{ 0x000204,   1, 0x04, 0x00000006 }, +	{ 0x000208,   1, 0x04, 0x00000000 }, +	{ 0x0002cc,   2, 0x04, 0x003fffff }, +	{ 0x001220,   1, 0x04, 0x00000005 }, +	{ 0x000fdc,   1, 0x04, 0x00000000 }, +	{ 0x000f98,   1, 0x04, 0x00400008 }, +	{ 0x001284,   1, 0x04, 0x08000080 }, +	{ 0x001450,   1, 0x04, 0x00400008 }, +	{ 0x001454,   1, 0x04, 0x08000080 }, +	{ 0x000214,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_pack +nvf0_grctx_pack_mthd[] = { +	{ nvf0_grctx_init_a197_0, 0xa197 }, +	{ nvc0_grctx_init_902d_0, 0x902d }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_grctx_init_fe_0[] = {  	{ 0x404004,   8, 0x04, 0x00000000 },  	{ 0x404024,   1, 0x04, 0x0000e000 },  	{ 0x404028,   8, 0x04, 0x00000000 }, @@ -50,8 +620,8 @@ nvf0_grctx_init_unk40xx[] = {  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_unk44xx[] = { +const struct nvc0_graph_init +nvf0_grctx_init_pri_0[] = {  	{ 0x404404,  12, 0x04, 0x00000000 },  	{ 0x404438,   1, 0x04, 0x00000000 },  	{ 0x404460,   2, 0x04, 0x00000000 }, @@ -62,23 +632,18 @@ nvf0_grctx_init_unk44xx[] = {  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_unk5bxx[] = { +const struct nvc0_graph_init +nvf0_grctx_init_cwd_0[] = {  	{ 0x405b00,   1, 0x04, 0x00000000 },  	{ 0x405b10,   1, 0x04, 0x00001000 },  	{ 0x405b20,   1, 0x04, 0x04000000 },  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_unk60xx[] = { +static const struct nvc0_graph_init +nvf0_grctx_init_pd_0[] = {  	{ 0x406020,   1, 0x04, 0x034103c1 },  	{ 0x406028,   4, 0x04, 0x00000001 }, -	{} -}; - -static struct nvc0_graph_init -nvf0_grctx_init_unk64xx[] = {  	{ 0x4064a8,   1, 0x04, 0x00000000 },  	{ 0x4064ac,   1, 0x04, 0x00003fff },  	{ 0x4064b0,   3, 0x04, 0x00000000 }, @@ -90,8 +655,8 @@ nvf0_grctx_init_unk64xx[] = {  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_unk88xx[] = { +static const struct nvc0_graph_init +nvf0_grctx_init_be_0[] = {  	{ 0x408800,   1, 0x04, 0x12802a3c },  	{ 0x408804,   1, 0x04, 0x00000040 },  	{ 0x408808,   1, 0x04, 0x1003e005 }, @@ -103,22 +668,23 @@ nvf0_grctx_init_unk88xx[] = {  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_gpc_0[] = { -	{ 0x418380,   1, 0x04, 0x00000016 }, -	{ 0x418400,   1, 0x04, 0x38004e00 }, -	{ 0x418404,   1, 0x04, 0x71e0ffff }, -	{ 0x41840c,   1, 0x04, 0x00001008 }, -	{ 0x418410,   1, 0x04, 0x0fff0fff }, -	{ 0x418414,   1, 0x04, 0x02200fff }, -	{ 0x418450,   6, 0x04, 0x00000000 }, -	{ 0x418468,   1, 0x04, 0x00000001 }, -	{ 0x41846c,   2, 0x04, 0x00000000 }, -	{ 0x418600,   1, 0x04, 0x0000001f }, -	{ 0x418684,   1, 0x04, 0x0000000f }, -	{ 0x418700,   1, 0x04, 0x00000002 }, -	{ 0x418704,   1, 0x04, 0x00000080 }, -	{ 0x418708,   3, 0x04, 0x00000000 }, +static const struct nvc0_graph_pack +nvf0_grctx_pack_hub[] = { +	{ nvc0_grctx_init_main_0 }, +	{ nvf0_grctx_init_fe_0 }, +	{ nvf0_grctx_init_pri_0 }, +	{ nve4_grctx_init_memfmt_0 }, +	{ nve4_grctx_init_ds_0 }, +	{ nvf0_grctx_init_cwd_0 }, +	{ nvf0_grctx_init_pd_0 }, +	{ nvc0_grctx_init_rstr2d_0 }, +	{ nve4_grctx_init_scc_0 }, +	{ nvf0_grctx_init_be_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_grctx_init_setup_0[] = {  	{ 0x418800,   1, 0x04, 0x7006860a },  	{ 0x418808,   1, 0x04, 0x00000000 },  	{ 0x41880c,   1, 0x04, 0x00000030 }, @@ -129,36 +695,31 @@ nvf0_grctx_init_gpc_0[] = {  	{ 0x4188e0,   1, 0x04, 0x01000000 },  	{ 0x4188e8,   5, 0x04, 0x00000000 },  	{ 0x4188fc,   1, 0x04, 0x20100018 }, -	{ 0x41891c,   1, 0x04, 0x00ff00ff }, -	{ 0x418924,   1, 0x04, 0x00000000 }, -	{ 0x418928,   1, 0x04, 0x00ffff00 }, -	{ 0x41892c,   1, 0x04, 0x0000ff00 }, -	{ 0x418b00,   1, 0x04, 0x00000006 }, -	{ 0x418b08,   1, 0x04, 0x0a418820 }, -	{ 0x418b0c,   1, 0x04, 0x062080e6 }, -	{ 0x418b10,   1, 0x04, 0x020398a4 }, -	{ 0x418b14,   1, 0x04, 0x0e629062 }, -	{ 0x418b18,   1, 0x04, 0x0a418820 }, -	{ 0x418b1c,   1, 0x04, 0x000000e6 }, -	{ 0x418bb8,   1, 0x04, 0x00000103 }, -	{ 0x418c08,   1, 0x04, 0x00000001 }, -	{ 0x418c10,   8, 0x04, 0x00000000 }, -	{ 0x418c40,   1, 0x04, 0xffffffff }, -	{ 0x418c6c,   1, 0x04, 0x00000001 }, -	{ 0x418c80,   1, 0x04, 0x20200004 }, -	{ 0x418c8c,   1, 0x04, 0x00000001 }, +	{} +}; + +const struct nvc0_graph_init +nvf0_grctx_init_gpc_unk_2[] = {  	{ 0x418d24,   1, 0x04, 0x00000000 }, -	{ 0x419000,   1, 0x04, 0x00000780 }, -	{ 0x419004,   2, 0x04, 0x00000000 }, -	{ 0x419014,   1, 0x04, 0x00000004 },  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_tpc[] = { -	{ 0x419848,   1, 0x04, 0x00000000 }, -	{ 0x419864,   1, 0x04, 0x00000129 }, -	{ 0x419888,   1, 0x04, 0x00000000 }, +static const struct nvc0_graph_pack +nvf0_grctx_pack_gpc[] = { +	{ nvc0_grctx_init_gpc_unk_0 }, +	{ nvd9_grctx_init_prop_0 }, +	{ nvd9_grctx_init_gpc_unk_1 }, +	{ nvf0_grctx_init_setup_0 }, +	{ nvc0_grctx_init_zcull_0 }, +	{ nvd9_grctx_init_crstr_0 }, +	{ nve4_grctx_init_gpm_0 }, +	{ nvf0_grctx_init_gpc_unk_2 }, +	{ nvc0_grctx_init_gcc_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_grctx_init_tex_0[] = {  	{ 0x419a00,   1, 0x04, 0x000000f0 },  	{ 0x419a04,   1, 0x04, 0x00000001 },  	{ 0x419a08,   1, 0x04, 0x00000021 }, @@ -169,14 +730,29 @@ nvf0_grctx_init_tpc[] = {  	{ 0x419a20,   1, 0x04, 0x00020800 },  	{ 0x419a30,   1, 0x04, 0x00000001 },  	{ 0x419ac4,   1, 0x04, 0x0037f440 }, +	{} +}; + +const struct nvc0_graph_init +nvf0_grctx_init_mpc_0[] = {  	{ 0x419c00,   1, 0x04, 0x0000001a },  	{ 0x419c04,   1, 0x04, 0x80000006 },  	{ 0x419c08,   1, 0x04, 0x00000002 },  	{ 0x419c20,   1, 0x04, 0x00000000 },  	{ 0x419c24,   1, 0x04, 0x00084210 },  	{ 0x419c28,   1, 0x04, 0x3efbefbe }, +	{} +}; + +const struct nvc0_graph_init +nvf0_grctx_init_l1c_0[] = {  	{ 0x419ce8,   1, 0x04, 0x00000000 },  	{ 0x419cf4,   1, 0x04, 0x00000203 }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_grctx_init_sm_0[] = {  	{ 0x419e04,   1, 0x04, 0x00000000 },  	{ 0x419e08,   1, 0x04, 0x0000001d },  	{ 0x419e0c,   1, 0x04, 0x00000000 }, @@ -189,8 +765,8 @@ nvf0_grctx_init_tpc[] = {  	{ 0x419e5c,   3, 0x04, 0x00000000 },  	{ 0x419e68,   1, 0x04, 0x00000002 },  	{ 0x419e6c,  12, 0x04, 0x00000000 }, -	{ 0x419eac,   1, 0x04, 0x00001fcf }, -	{ 0x419eb0,   1, 0x04, 0x0db00da0 }, +	{ 0x419eac,   1, 0x04, 0x00001f8f }, +	{ 0x419eb0,   1, 0x04, 0x0db00d2f },  	{ 0x419eb8,   1, 0x04, 0x00000000 },  	{ 0x419ec8,   1, 0x04, 0x0001304f },  	{ 0x419f30,   4, 0x04, 0x00000000 }, @@ -203,24 +779,36 @@ nvf0_grctx_init_tpc[] = {  	{}  }; -static struct nvc0_graph_init -nvf0_grctx_init_unk[] = { -	{ 0x41be24,   1, 0x04, 0x00000006 }, +static const struct nvc0_graph_pack +nvf0_grctx_pack_tpc[] = { +	{ nvd7_grctx_init_pe_0 }, +	{ nvf0_grctx_init_tex_0 }, +	{ nvf0_grctx_init_mpc_0 }, +	{ nvf0_grctx_init_l1c_0 }, +	{ nvf0_grctx_init_sm_0 }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_grctx_init_cbm_0[] = {  	{ 0x41bec0,   1, 0x04, 0x10000000 },  	{ 0x41bec4,   1, 0x04, 0x00037f7f },  	{ 0x41bee4,   1, 0x04, 0x00000000 }, -	{ 0x41bf00,   1, 0x04, 0x0a418820 }, -	{ 0x41bf04,   1, 0x04, 0x062080e6 }, -	{ 0x41bf08,   1, 0x04, 0x020398a4 }, -	{ 0x41bf0c,   1, 0x04, 0x0e629062 }, -	{ 0x41bf10,   1, 0x04, 0x0a418820 }, -	{ 0x41bf14,   1, 0x04, 0x000000e6 }, -	{ 0x41bfd0,   1, 0x04, 0x00900103 }, -	{ 0x41bfe0,   1, 0x04, 0x00400001 }, -	{ 0x41bfe4,   1, 0x04, 0x00000000 },  	{}  }; +static const struct nvc0_graph_pack +nvf0_grctx_pack_ppc[] = { +	{ nve4_grctx_init_pes_0 }, +	{ nvf0_grctx_init_cbm_0 }, +	{ nvd7_grctx_init_wwdx_0 }, +	{} +}; + +/******************************************************************************* + * PGRAPH context implementation + ******************************************************************************/ +  static void  nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  { @@ -254,7 +842,7 @@ nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  		u16 magic3 = 0x0648;  		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;  		magic[gpc][1]  = 0x00000000 | (magic1 << 16); -		offset += 0x0324 * (priv->tpc_nr[gpc] - 1);; +		offset += 0x0324 * (priv->tpc_nr[gpc] - 1);  		magic[gpc][2]  = 0x10000000 | (magic2 << 16) | offset;  		magic[gpc][3]  = 0x00000000 | (magic3 << 16);  		offset += 0x0324; @@ -273,40 +861,6 @@ nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)  	mmio_list(0x17e920, 0x00090a05, 0, 0);  } -static struct nvc0_graph_init * -nvf0_grctx_init_hub[] = { -	nvc0_grctx_init_base, -	nvf0_grctx_init_unk40xx, -	nvf0_grctx_init_unk44xx, -	nve4_grctx_init_unk46xx, -	nve4_grctx_init_unk47xx, -	nve4_grctx_init_unk58xx, -	nvf0_grctx_init_unk5bxx, -	nvf0_grctx_init_unk60xx, -	nvf0_grctx_init_unk64xx, -	nve4_grctx_init_unk80xx, -	nvf0_grctx_init_unk88xx, -	nvd9_grctx_init_rop, -	NULL -}; - -struct nvc0_graph_init * -nvf0_grctx_init_gpc[] = { -	nvf0_grctx_init_gpc_0, -	nvc0_grctx_init_gpc_1, -	nvf0_grctx_init_tpc, -	nvf0_grctx_init_unk, -	NULL -}; - -static struct nvc0_graph_mthd -nvf0_grctx_init_mthd[] = { -	{ 0xa197, nvc1_grctx_init_9097, }, -	{ 0x902d, nvc0_grctx_init_902d, }, -	{ 0x902d, nvc0_grctx_init_mthd_magic, }, -	{} -}; -  struct nouveau_oclass *  nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {  	.base.handle = NV_ENGCTX(GR, 0xf0), @@ -318,11 +872,14 @@ nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {  		.rd32 = _nouveau_graph_context_rd32,  		.wr32 = _nouveau_graph_context_wr32,  	}, -	.main = nve4_grctx_generate_main, -	.mods = nvf0_grctx_generate_mods, -	.unkn = nve4_grctx_generate_unkn, -	.hub  = nvf0_grctx_init_hub, -	.gpc  = nvf0_grctx_init_gpc, -	.icmd = nvc0_grctx_init_icmd, -	.mthd = nvf0_grctx_init_mthd, +	.main  = nve4_grctx_generate_main, +	.mods  = nvf0_grctx_generate_mods, +	.unkn  = nve4_grctx_generate_unkn, +	.hub   = nvf0_grctx_pack_hub, +	.gpc   = nvf0_grctx_pack_gpc, +	.zcull = nvc0_grctx_pack_zcull, +	.tpc   = nvf0_grctx_pack_tpc, +	.ppc   = nvf0_grctx_pack_ppc, +	.icmd  = nvf0_grctx_pack_icmd, +	.mthd  = nvf0_grctx_pack_mthd,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc index 5d24b6de16c..e37d8106ae1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/com.fuc @@ -38,7 +38,7 @@ queue_put:  	cmpu b32 $r8 $r9  	bra ne #queue_put_next  		mov $r15 E_CMD_OVERFLOW -		call #error +		call(error)  		ret  	// store cmd/data on queue @@ -92,18 +92,16 @@ queue_get_done:  // Out: $r15 value  //  nv_rd32: -	mov $r11 0x728 -	shl b32 $r11 6  	mov b32 $r12 $r14  	bset $r12 31			// MMIO_CTRL_PENDING -	iowr I[$r11 + 0x000] $r12	// MMIO_CTRL +	nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)  	nv_rd32_wait: -		iord $r12 I[$r11 + 0x000] +		nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)  		xbit $r12 $r12 31  		bra ne #nv_rd32_wait  	mov $r10 6			// DONE_MMIO_RD -	call #wait_doneo -	iord $r15 I[$r11 + 0x100]	// MMIO_RDVAL +	call(wait_doneo) +	nv_iord($r15, NV_PGRAPH_FECS_MMIO_RDVAL, 0)  	ret  // nv_wr32 - write 32-bit value to nv register @@ -112,37 +110,17 @@ nv_rd32:  //      $r15 value  //  nv_wr32: -	mov $r11 0x728 -	shl b32 $r11 6 -	iowr I[$r11 + 0x200] $r15	// MMIO_WRVAL +	nv_iowr(NV_PGRAPH_FECS_MMIO_WRVAL, 0, $r15)  	mov b32 $r12 $r14  	bset $r12 31			// MMIO_CTRL_PENDING  	bset $r12 30			// MMIO_CTRL_WRITE -	iowr I[$r11 + 0x000] $r12	// MMIO_CTRL +	nv_iowr(NV_PGRAPH_FECS_MMIO_CTRL, 0, $r12)  	nv_wr32_wait: -		iord $r12 I[$r11 + 0x000] +		nv_iord($r12, NV_PGRAPH_FECS_MMIO_CTRL, 0)  		xbit $r12 $r12 31  		bra ne #nv_wr32_wait  	ret -// (re)set watchdog timer -// -// In : $r15 timeout -// -watchdog_reset: -	mov $r8 0x430 -	shl b32 $r8 6 -	bset $r15 31 -	iowr I[$r8 + 0x000] $r15 -	ret - -// clear watchdog timer -watchdog_clear: -	mov $r8 0x430 -	shl b32 $r8 6 -	iowr I[$r8 + 0x000] $r0 -	ret -  // wait_donez - wait on FUC_DONE bit to become clear  //  // In : $r10 bit to wait on @@ -163,13 +141,9 @@ wait_donez:  //  wait_doneo:  	trace_set(T_WAIT); -	mov $r8 0x818 -	shl b32 $r8 6 -	iowr I[$r8 + 0x000] $r10 +	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(6), 0, $r10)  	wait_doneo_e: -		mov $r8 0x400 -		shl b32 $r8 6 -		iord $r8 I[$r8 + 0x000] +		nv_iord($r8, NV_PGRAPH_FECS_SIGNAL, 0)  		xbit $r8 $r8 $r10  		bra e #wait_doneo_e  	trace_clr(T_WAIT) @@ -209,21 +183,18 @@ mmctx_size:  //  mmctx_xfer:  	trace_set(T_MMCTX) -	mov $r8 0x710 -	shl b32 $r8 6  	clear b32 $r9  	or $r11 $r11  	bra e #mmctx_base_disabled -		iowr I[$r8 + 0x000] $r11	// MMCTX_BASE +		nv_iowr(NV_PGRAPH_FECS_MMCTX_BASE, 0, $r11)  		bset $r9 0			// BASE_EN  	mmctx_base_disabled:  	or $r14 $r14  	bra e #mmctx_multi_disabled -		iowr I[$r8 + 0x200] $r14 	// MMCTX_MULTI_STRIDE -		iowr I[$r8 + 0x300] $r15 	// MMCTX_MULTI_MASK +		nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE, 0, $r14) +		nv_iowr(NV_PGRAPH_FECS_MMCTX_MULTI_MASK, 0, $r15)  		bset $r9 1			// MULTI_EN  	mmctx_multi_disabled: -	add b32 $r8 0x100  	xbit $r11 $r10 0  	shl b32 $r11 16			// DIR @@ -231,20 +202,20 @@ mmctx_xfer:  	xbit $r14 $r10 1  	shl b32 $r14 17  	or $r11 $r14			// START_TRIGGER -	iowr I[$r8 + 0x000] $r11	// MMCTX_CTRL +	nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)  	// loop over the mmio list, and send requests to the hw  	mmctx_exec_loop:  		// wait for space in mmctx queue  		mmctx_wait_free: -			iord $r14 I[$r8 + 0x000] // MMCTX_CTRL +			nv_iord($r14, NV_PGRAPH_FECS_MMCTX_CTRL, 0)  			and $r14 0x1f  			bra e #mmctx_wait_free  		// queue up an entry  		ld b32 $r14 D[$r12]  		or $r14 $r9 -		iowr I[$r8 + 0x300] $r14 +		nv_iowr(NV_PGRAPH_FECS_MMCTX_QUEUE, 0, $r14)  		add b32 $r12 4  		cmpu b32 $r12 $r13  		bra ne #mmctx_exec_loop @@ -253,22 +224,22 @@ mmctx_xfer:  	bra ne #mmctx_stop  		// wait for queue to empty  		mmctx_fini_wait: -			iord $r11 I[$r8 + 0x000]	// MMCTX_CTRL +			nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)  			and $r11 0x1f  			cmpu b32 $r11 0x10  			bra ne #mmctx_fini_wait -		mov $r10 2				// DONE_MMCTX -		call #wait_donez +		mov $r10 5			// DONE_MMCTX +		call(wait_donez)  		bra #mmctx_done  	mmctx_stop:  		xbit $r11 $r10 0  		shl b32 $r11 16			// DIR  		bset $r11 12			// QLIMIT = 0x10  		bset $r11 18			// STOP_TRIGGER -		iowr I[$r8 + 0x000] $r11	// MMCTX_CTRL +		nv_iowr(NV_PGRAPH_FECS_MMCTX_CTRL, 0, $r11)  		mmctx_stop_wait:  			// wait for STOP_TRIGGER to clear -			iord $r11 I[$r8 + 0x000] // MMCTX_CTRL +			nv_iord($r11, NV_PGRAPH_FECS_MMCTX_CTRL, 0)  			xbit $r11 $r11 18  			bra ne #mmctx_stop_wait  	mmctx_done: @@ -280,28 +251,24 @@ mmctx_xfer:  strand_wait:  	push $r10  	mov $r10 2 -	call #wait_donez +	call(wait_donez)  	pop $r10  	ret  // unknown - call before issuing strand commands  //  strand_pre: -	mov $r8 0x4afc -	sethi $r8 0x20000 -	mov $r9 0xc -	iowr I[$r8] $r9 -	call #strand_wait +	mov $r9 NV_PGRAPH_FECS_STRAND_CMD_ENABLE +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9) +	call(strand_wait)  	ret  // unknown - call after issuing strand commands  //  strand_post: -	mov $r8 0x4afc -	sethi $r8 0x20000 -	mov $r9 0xd -	iowr I[$r8] $r9 -	call #strand_wait +	mov $r9 NV_PGRAPH_FECS_STRAND_CMD_DISABLE +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r9) +	call(strand_wait)  	ret  // Selects strand set?! @@ -309,18 +276,14 @@ strand_post:  // In: $r14 id  //  strand_set: -	mov $r10 0x4ffc -	sethi $r10 0x20000 -	sub b32 $r11 $r10 0x500  	mov $r12 0xf -	iowr I[$r10 + 0x000] $r12		// 0x93c = 0xf -	mov $r12 0xb -	iowr I[$r11 + 0x000] $r12		// 0x928 = 0xb -	call #strand_wait -	iowr I[$r10 + 0x000] $r14		// 0x93c = <id> -	mov $r12 0xa -	iowr I[$r11 + 0x000] $r12		// 0x928 = 0xa -	call #strand_wait +	nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r12) +	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12) +	nv_iowr(NV_PGRAPH_FECS_STRAND_FILTER, 0x3f, $r14) +	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12) +	call(strand_wait)  	ret  // Initialise strand context data @@ -332,30 +295,27 @@ strand_set:  //  strand_ctx_init:  	trace_set(T_STRINIT) -	call #strand_pre +	call(strand_pre)  	mov $r14 3 -	call #strand_set -	mov $r10 0x46fc -	sethi $r10 0x20000 -	add b32 $r11 $r10 0x400 -	iowr I[$r10 + 0x100] $r0	// STRAND_FIRST_GENE = 0 -	mov $r12 1 -	iowr I[$r11 + 0x000] $r12	// STRAND_CMD = LATCH_FIRST_GENE -	call #strand_wait +	call(strand_set) + +	clear b32 $r12 +	nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r12) +	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_SEEK +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12) +	call(strand_wait)  	sub b32 $r12 $r0 1 -	iowr I[$r10 + 0x000] $r12	// STRAND_GENE_CNT = 0xffffffff -	mov $r12 2 -	iowr I[$r11 + 0x000] $r12	// STRAND_CMD = LATCH_GENE_CNT -	call #strand_wait -	call #strand_post +	nv_iowr(NV_PGRAPH_FECS_STRAND_DATA, 0x3f, $r12) +	mov $r12 NV_PGRAPH_FECS_STRAND_CMD_GET_INFO +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r12) +	call(strand_wait) +	call(strand_post)  	// read the size of each strand, poke the context offset of  	// each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry  	// about it later then. -	mov $r8 0x880 -	shl b32 $r8 6 -	iord $r9 I[$r8 + 0x000]		// STRANDS -	add b32 $r8 0x2200 +	nv_mkio($r8, NV_PGRAPH_FECS_STRAND_SAVE_SWBASE, 0x00) +	nv_iord($r9, NV_PGRAPH_FECS_STRANDS_CNT, 0x00)  	shr b32 $r14 $r15 8  	ctx_init_strand_loop:  		iowr I[$r8 + 0x000] $r14	// STRAND_SAVE_SWBASE diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc index 5547c1b3f4f..7445f12b1d9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpc.fuc @@ -54,16 +54,13 @@ mmio_list_base:  #ifdef INCLUDE_CODE  // reports an exception to the host  // -// In: $r15 error code (see nvc0.fuc) +// In: $r15 error code (see os.h)  //  error:  	push $r14 -	mov $r14 -0x67ec 	// 0x9814 -	sethi $r14 0x400000 -	call #nv_wr32		// HUB_CTXCTL_CC_SCRATCH[5] = error code -	add b32 $r14 0x41c +	nv_wr32(NV_PGRAPH_FECS_CC_SCRATCH_VAL(5), $r15)  	mov $r15 1 -	call #nv_wr32		// HUB_CTXCTL_INTR_UP_SET +	nv_wr32(NV_PGRAPH_FECS_INTR_UP_SET, $r15)  	pop $r14  	ret @@ -81,49 +78,48 @@ error:  //  init:  	clear b32 $r0 -	mov $sp $r0 + +	// setup stack +	nv_iord($r1, NV_PGRAPH_GPCX_GPCCS_CAPS, 0) +	extr $r1 $r1 9:17 +	shl b32 $r1 8 +	mov $sp $r1  	// enable fifo access -	mov $r1 0x1200 -	mov $r2 2 -	iowr I[$r1 + 0x000] $r2		// FIFO_ENABLE +	mov $r2 NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_ACCESS, 0, $r2)  	// setup i0 handler, and route all interrupts to it  	mov $r1 #ih  	mov $iv0 $r1 -	mov $r1 0x400 -	iowr I[$r1 + 0x300] $r0		// INTR_DISPATCH +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE, 0, $r0)  	// enable fifo interrupt -	mov $r2 4 -	iowr I[$r1 + 0x000] $r2		// INTR_EN_SET +	mov $r2 NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET, 0, $r2)  	// enable interrupts  	bset $flags ie0  	// figure out which GPC we are, and how many TPCs we have -	mov $r1 0x608 -	shl b32 $r1 6 -	iord $r2 I[$r1 + 0x000]		// UNITS +	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_UNITS, 0)  	mov $r3 1  	and $r2 0x1f  	shl b32 $r3 $r2  	sub b32 $r3 1  	st b32 D[$r0 + #tpc_count] $r2  	st b32 D[$r0 + #tpc_mask] $r3 -	add b32 $r1 0x400 -	iord $r2 I[$r1 + 0x000]		// MYINDEX +	nv_iord($r2, NV_PGRAPH_GPCX_GPCCS_MYINDEX, 0)  	st b32 D[$r0 + #gpc_id] $r2  #if NV_PGRAPH_GPCX_UNK__SIZE > 0  	// figure out which, and how many, UNKs are actually present -	mov $r14 0x0c30 -	sethi $r14 0x500000 +	imm32($r14, 0x500c30)  	clear b32 $r2  	clear b32 $r3  	clear b32 $r4  	init_unk_loop: -		call #nv_rd32 +		call(nv_rd32)  		cmp b32 $r15 0  		bra z #init_unk_next  			mov $r15 1 @@ -146,23 +142,21 @@ init:  	// set mmctx base addresses now so we don't have to do it later,  	// they don't currently ever change -	mov $r4 0x700 -	shl b32 $r4 6  	shr b32 $r5 $r2 8 -	iowr I[$r4 + 0x000] $r5		// MMCTX_SAVE_SWBASE -	iowr I[$r4 + 0x100] $r5		// MMCTX_LOAD_SWBASE +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE, 0, $r5) +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE, 0, $r5)  	// calculate GPC mmio context size  	ld b32 $r14 D[$r0 + #gpc_mmio_list_head]  	ld b32 $r15 D[$r0 + #gpc_mmio_list_tail] -	call #mmctx_size +	call(mmctx_size)  	add b32 $r2 $r15  	add b32 $r3 $r15  	// calculate per-TPC mmio context size  	ld b32 $r14 D[$r0 + #tpc_mmio_list_head]  	ld b32 $r15 D[$r0 + #tpc_mmio_list_tail] -	call #mmctx_size +	call(mmctx_size)  	ld b32 $r14 D[$r0 + #tpc_count]  	mulu $r14 $r15  	add b32 $r2 $r14 @@ -172,7 +166,7 @@ init:  	// calculate per-UNK mmio context size  	ld b32 $r14 D[$r0 + #unk_mmio_list_head]  	ld b32 $r15 D[$r0 + #unk_mmio_list_tail] -	call #mmctx_size +	call(mmctx_size)  	ld b32 $r14 D[$r0 + #unk_count]  	mulu $r14 $r15  	add b32 $r2 $r14 @@ -180,9 +174,8 @@ init:  #endif  	// round up base/size to 256 byte boundary (for strand SWBASE) -	add b32 $r4 0x1300  	shr b32 $r3 2 -	iowr I[$r4 + 0x000] $r3		// MMCTX_LOAD_COUNT, wtf for?!? +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT, 0, $r3) // wtf for?!  	shr b32 $r2 8  	shr b32 $r3 6  	add b32 $r2 1 @@ -192,7 +185,7 @@ init:  	// calculate size of strand context data  	mov b32 $r15 $r2 -	call #strand_ctx_init +	call(strand_ctx_init)  	add b32 $r3 $r15  	// save context size, and tell HUB we're done @@ -208,7 +201,7 @@ main:  	bset $flags $p0  	sleep $p0  	mov $r13 #cmd_queue -	call #queue_get +	call(queue_get)  	bra $p1 #main  	// 0x0000-0x0003 are all context transfers @@ -224,13 +217,13 @@ main:  		or $r1 $r14  		mov $flags $r1  		// transfer context data -		call #ctx_xfer +		call(ctx_xfer)  		bra #main  	main_not_ctx_xfer:  	shl b32 $r15 $r14 16  	or $r15 E_BAD_COMMAND -	call #error +	call(error)  	bra #main  // interrupt handler @@ -247,22 +240,20 @@ ih:  	clear b32 $r0  	// incoming fifo command? -	iord $r10 I[$r0 + 0x200]	// INTR -	and $r11 $r10 0x00000004 +	nv_iord($r10, NV_PGRAPH_GPCX_GPCCS_INTR, 0) +	and $r11 $r10 NV_PGRAPH_GPCX_GPCCS_INTR_FIFO  	bra e #ih_no_fifo  		// queue incoming fifo command for later processing -		mov $r11 0x1900  		mov $r13 #cmd_queue -		iord $r14 I[$r11 + 0x100]	// FIFO_CMD -		iord $r15 I[$r11 + 0x000]	// FIFO_DATA -		call #queue_put -		add b32 $r11 0x400 +		nv_iord($r14, NV_PGRAPH_GPCX_GPCCS_FIFO_CMD, 0) +		nv_iord($r15, NV_PGRAPH_GPCX_GPCCS_FIFO_DATA, 0) +		call(queue_put)  		mov $r14 1 -		iowr I[$r11 + 0x000] $r14	// FIFO_ACK +		nv_iowr(NV_PGRAPH_GPCX_GPCCS_FIFO_ACK, 0, $r14)  	// ack, and wake up main()  	ih_no_fifo: -	iowr I[$r0 + 0x100] $r10	// INTR_ACK +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_INTR_ACK, 0, $r10)  	pop $r15  	pop $r14 @@ -283,9 +274,7 @@ hub_barrier_done:  	mov $r15 1  	ld b32 $r14 D[$r0 + #gpc_id]  	shl b32 $r15 $r14 -	mov $r14 -0x6be8 	// 0x409418 - HUB_BAR_SET -	sethi $r14 0x400000 -	call #nv_wr32 +	nv_wr32(0x409418, $r15)	// 0x409418 - HUB_BAR_SET  	ret  // Disables various things, waits a bit, and re-enables them.. @@ -295,16 +284,15 @@ hub_barrier_done:  // funny things happen.  //  ctx_redswitch: -	mov $r14 0x614 -	shl b32 $r14 6 -	mov $r15 0x020 -	iowr I[$r14] $r15	// GPC_RED_SWITCH = POWER -	mov $r15 8 +	mov $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15) +	mov $r14 8  	ctx_redswitch_delay: -		sub b32 $r15 1 +		sub b32 $r14 1  		bra ne #ctx_redswitch_delay -	mov $r15 0xa20 -	iowr I[$r14] $r15	// GPC_RED_SWITCH = UNK11, ENABLE, POWER +	or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11 +	or $r15 NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_RED_SWITCH, 0, $r15)  	ret  // Transfer GPC context data between GPU and storage area @@ -317,46 +305,37 @@ ctx_redswitch:  //  ctx_xfer:  	// set context base address -	mov $r1 0xa04 -	shl b32 $r1 6 -	iowr I[$r1 + 0x000] $r15// MEM_BASE +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_MEM_BASE, 0, $r15)  	bra not $p1 #ctx_xfer_not_load -		call #ctx_redswitch +		call(ctx_redswitch)  	ctx_xfer_not_load:  	// strands -	mov $r1 0x4afc -	sethi $r1 0x20000 -	mov $r2 0xc -	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0c -	call #strand_wait -	mov $r2 0x47fc -	sethi $r2 0x20000 -	iowr I[$r2] $r0		// STRAND_FIRST_GENE(0x3f) = 0x00 -	xbit $r2 $flags $p1 -	add b32 $r2 3 -	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) +	call(strand_pre) +	clear b32 $r2 +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT, 0x3f, $r2) +	xbit $r2 $flags $p1	// SAVE/LOAD +	add b32 $r2 NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE +	nv_iowr(NV_PGRAPH_GPCX_GPCCS_STRAND_CMD, 0x3f, $r2)  	// mmio context  	xbit $r10 $flags $p1	// direction  	or $r10 2		// first -	mov $r11 0x0000 -	sethi $r11 0x500000 +	imm32($r11,0x500000)  	ld b32 $r12 D[$r0 + #gpc_id]  	shl b32 $r12 15  	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn  	ld b32 $r12 D[$r0 + #gpc_mmio_list_head]  	ld b32 $r13 D[$r0 + #gpc_mmio_list_tail]  	mov $r14 0		// not multi -	call #mmctx_xfer +	call(mmctx_xfer)  	// per-TPC mmio context  	xbit $r10 $flags $p1	// direction  #if !NV_PGRAPH_GPCX_UNK__SIZE  	or $r10 4		// last  #endif -	mov $r11 0x4000 -	sethi $r11 0x500000	// base = NV_PGRAPH_GPC0_TPC0 +	imm32($r11, 0x504000)  	ld b32 $r12 D[$r0 + #gpc_id]  	shl b32 $r12 15  	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_TPC0 @@ -364,14 +343,13 @@ ctx_xfer:  	ld b32 $r13 D[$r0 + #tpc_mmio_list_tail]  	ld b32 $r15 D[$r0 + #tpc_mask]  	mov $r14 0x800		// stride = 0x800 -	call #mmctx_xfer +	call(mmctx_xfer)  #if NV_PGRAPH_GPCX_UNK__SIZE > 0  	// per-UNK mmio context  	xbit $r10 $flags $p1	// direction  	or $r10 4		// last -	mov $r11 0x3000 -	sethi $r11 0x500000	// base = NV_PGRAPH_GPC0_UNK0 +	imm32($r11, 0x503000)  	ld b32 $r12 D[$r0 + #gpc_id]  	shl b32 $r12 15  	add b32 $r11 $r12	// base = NV_PGRAPH_GPCn_UNK0 @@ -379,11 +357,11 @@ ctx_xfer:  	ld b32 $r13 D[$r0 + #unk_mmio_list_tail]  	ld b32 $r15 D[$r0 + #unk_mask]  	mov $r14 0x200		// stride = 0x200 -	call #mmctx_xfer +	call(mmctx_xfer)  #endif  	// wait for strands to finish -	call #strand_wait +	call(strand_wait)  	// if load, or a save without a load following, do some  	// unknown stuff that's done after finishing a block of @@ -391,14 +369,10 @@ ctx_xfer:  	bra $p1 #ctx_xfer_post  	bra not $p2 #ctx_xfer_done  	ctx_xfer_post: -		mov $r1 0x4afc -		sethi $r1 0x20000 -		mov $r2 0xd -		iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0d -		call #strand_wait +		call(strand_post)  	// mark completion in HUB's barrier  	ctx_xfer_done: -	call #hub_barrier_done +	call(hub_barrier_done)  	ret  #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5 new file mode 100644 index 00000000000..e730603891d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5 @@ -0,0 +1,42 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000002 + +#define CHIPSET GK208 +#include "macros.fuc" + +.section #gm107_grgpc_data +#define INCLUDE_DATA +#include "com.fuc" +#include "gpc.fuc" +#undef INCLUDE_DATA + +.section #gm107_grgpc_code +#define INCLUDE_CODE +bra #init +#include "com.fuc" +#include "gpc.fuc" +.align 256 +#undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h new file mode 100644 index 00000000000..6d53b67dd3c --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcgm107.fuc5.h @@ -0,0 +1,473 @@ +uint32_t gm107_grgpc_data[] = { +/* 0x0000: gpc_mmio_list_head */ +	0x0000006c, +/* 0x0004: gpc_mmio_list_tail */ +/* 0x0004: tpc_mmio_list_head */ +	0x0000006c, +/* 0x0008: tpc_mmio_list_tail */ +/* 0x0008: unk_mmio_list_head */ +	0x0000006c, +/* 0x000c: unk_mmio_list_tail */ +	0x0000006c, +/* 0x0010: gpc_id */ +	0x00000000, +/* 0x0014: tpc_count */ +	0x00000000, +/* 0x0018: tpc_mask */ +	0x00000000, +/* 0x001c: unk_count */ +	0x00000000, +/* 0x0020: unk_mask */ +	0x00000000, +/* 0x0024: cmd_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; + +uint32_t gm107_grgpc_code[] = { +	0x03140ef5, +/* 0x0004: queue_put */ +	0x9800d898, +	0x86f001d9, +	0xf489a408, +	0x020f0b1b, +	0x0002f87e, +/* 0x001a: queue_put_next */ +	0x98c400f8, +	0x0384b607, +	0xb6008dbb, +	0x8eb50880, +	0x018fb500, +	0xf00190b6, +	0xd9b50f94, +/* 0x0037: queue_get */ +	0xf400f801, +	0xd8980131, +	0x01d99800, +	0x0bf489a4, +	0x0789c421, +	0xbb0394b6, +	0x90b6009d, +	0x009e9808, +	0xb6019f98, +	0x84f00180, +	0x00d8b50f, +/* 0x0063: queue_get_done */ +	0xf80132f4, +/* 0x0065: nv_rd32 */ +	0xf0ecb200, +	0x00801fc9, +	0x0cf601ca, +/* 0x0073: nv_rd32_wait */ +	0x8c04bd00, +	0xcf01ca00, +	0xccc800cc, +	0xf61bf41f, +	0xec7e060a, +	0x008f0000, +	0xffcf01cb, +/* 0x008f: nv_wr32 */ +	0x8000f800, +	0xf601cc00, +	0x04bd000f, +	0xc9f0ecb2, +	0x1ec9f01f, +	0x01ca0080, +	0xbd000cf6, +/* 0x00a9: nv_wr32_wait */ +	0xca008c04, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f61b, +/* 0x00b8: wait_donez */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x00cf: wait_donez_ne */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf61bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x00ec: wait_doneo */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x0103: wait_doneo_e */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf60bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x0120: mmctx_size */ +/* 0x0122: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0x1bf4efa4, +	0xf89fb2ec, +/* 0x013d: mmctx_xfer */ +	0xf094bd00, +	0x00800199, +	0x09f60237, +	0xbd04bd00, +	0x05bbfd94, +	0x800f0bf4, +	0xf601c400, +	0x04bd000b, +/* 0x015f: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0xc6008018, +	0x000ef601, +	0x008004bd, +	0x0ff601c7, +	0xf004bd00, +/* 0x017a: mmctx_multi_disabled */ +	0xabc80199, +	0x10b4b600, +	0xc80cb9f0, +	0xe4b601ae, +	0x05befd11, +	0x01c50080, +	0xbd000bf6, +/* 0x0195: mmctx_exec_loop */ +/* 0x0195: mmctx_wait_free */ +	0xc5008e04, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f60b, +	0x05e9fd00, +	0x01c80080, +	0xbd000ef6, +	0x04c0b604, +	0x1bf4cda4, +	0x02abc8df, +/* 0x01bf: mmctx_fini_wait */ +	0x8b1c1bf4, +	0xcf01c500, +	0xb4f000bb, +	0x10b4b01f, +	0x0af31bf4, +	0x00b87e05, +	0x250ef400, +/* 0x01d8: mmctx_stop */ +	0xb600abc8, +	0xb9f010b4, +	0x12b9f00c, +	0x01c50080, +	0xbd000bf6, +/* 0x01ed: mmctx_stop_wait */ +	0xc5008b04, +	0x00bbcf01, +	0xf412bbc8, +/* 0x01fa: mmctx_done */ +	0x94bdf61b, +	0x800199f0, +	0xf6021700, +	0x04bd0009, +/* 0x020a: strand_wait */ +	0xa0f900f8, +	0xb87e020a, +	0xa0fc0000, +/* 0x0216: strand_pre */ +	0x0c0900f8, +	0x024afc80, +	0xbd0009f6, +	0x020a7e04, +/* 0x0227: strand_post */ +	0x0900f800, +	0x4afc800d, +	0x0009f602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0238: strand_set */ +	0xfc800f0c, +	0x0cf6024f, +	0x0c04bd00, +	0x4afc800b, +	0x000cf602, +	0xfc8004bd, +	0x0ef6024f, +	0x0c04bd00, +	0x4afc800a, +	0x000cf602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0268: strand_ctx_init */ +	0x99f094bd, +	0x37008003, +	0x0009f602, +	0x167e04bd, +	0x030e0002, +	0x0002387e, +	0xfc80c4bd, +	0x0cf60247, +	0x0c04bd00, +	0x4afc8001, +	0x000cf602, +	0x0a7e04bd, +	0x0c920002, +	0x46fc8001, +	0x000cf602, +	0x020c04bd, +	0x024afc80, +	0xbd000cf6, +	0x020a7e04, +	0x02277e00, +	0x42008800, +	0x20008902, +	0x0099cf02, +/* 0x02c7: ctx_init_strand_loop */ +	0xf608fe95, +	0x8ef6008e, +	0x808acf40, +	0xb606a5b6, +	0xeabb01a0, +	0x0480b600, +	0xf40192b6, +	0xe4b6e81b, +	0xf2efbc08, +	0x99f094bd, +	0x17008003, +	0x0009f602, +	0x00f804bd, +/* 0x02f8: error */ +	0xffb2e0f9, +	0x4098148e, +	0x00008f7e, +	0xffb2010f, +	0x409c1c8e, +	0x00008f7e, +	0x00f8e0fc, +/* 0x0314: init */ +	0x004104bd, +	0x0011cf42, +	0x010911e7, +	0xfe0814b6, +	0x02020014, +	0xf6120040, +	0x04bd0002, +	0xfe047241, +	0x00400010, +	0x0000f607, +	0x040204bd, +	0xf6040040, +	0x04bd0002, +	0x821031f4, +	0xcf018200, +	0x01030022, +	0xbb1f24f0, +	0x32b60432, +	0x0502b501, +	0x820603b5, +	0xcf018600, +	0x02b50022, +	0x0c308e04, +	0xbd24bd50, +/* 0x0377: init_unk_loop */ +	0x7e44bd34, +	0xb0000065, +	0x0bf400f6, +	0xbb010f0e, +	0x4ffd04f2, +	0x0130b605, +/* 0x038c: init_unk_next */ +	0xb60120b6, +	0x26b004e0, +	0xe21bf402, +/* 0x0398: init_unk_done */ +	0xb50703b5, +	0x00820804, +	0x22cf0201, +	0x9534bd00, +	0x00800825, +	0x05f601c0, +	0x8004bd00, +	0xf601c100, +	0x04bd0005, +	0x98000e98, +	0x207e010f, +	0x2fbb0001, +	0x003fbb00, +	0x98010e98, +	0x207e020f, +	0x0e980001, +	0x00effd05, +	0xbb002ebb, +	0x0e98003e, +	0x030f9802, +	0x0001207e, +	0xfd070e98, +	0x2ebb00ef, +	0x003ebb00, +	0x800235b6, +	0xf601d300, +	0x04bd0003, +	0xb60825b6, +	0x20b60635, +	0x0130b601, +	0xb60824b6, +	0x2fb20834, +	0x0002687e, +	0x80003fbb, +	0xf6020100, +	0x04bd0003, +	0x29f024bd, +	0x3000801f, +	0x0002f602, +/* 0x0436: main */ +	0x31f404bd, +	0x0028f400, +	0x377e240d, +	0x01f40000, +	0x04e4b0f4, +	0xfe1d18f4, +	0x06020181, +	0x12fd20bd, +	0x01e4b604, +	0xfe051efd, +	0x097e0018, +	0x0ef40005, +/* 0x0465: main_not_ctx_xfer */ +	0x10ef94d4, +	0x7e01f5f0, +	0xf40002f8, +/* 0x0472: ih */ +	0x80f9c70e, +	0xf90188fe, +	0xf990f980, +	0xf9b0f9a0, +	0xf9e0f9d0, +	0x4a04bdf0, +	0xaacf0200, +	0x04abc400, +	0x0d1f0bf4, +	0x1a004e24, +	0x4f00eecf, +	0xffcf1900, +	0x00047e00, +	0x40010e00, +	0x0ef61d00, +/* 0x04af: ih_no_fifo */ +	0x4004bd00, +	0x0af60100, +	0xfc04bd00, +	0xfce0fcf0, +	0xfcb0fcd0, +	0xfc90fca0, +	0x0088fe80, +	0x32f480fc, +/* 0x04cf: hub_barrier_done */ +	0x0f01f800, +	0x040e9801, +	0xb204febb, +	0x94188eff, +	0x008f7e40, +/* 0x04e3: ctx_redswitch */ +	0x0f00f800, +	0x85008020, +	0x000ff601, +	0x080e04bd, +/* 0x04f0: ctx_redswitch_delay */ +	0xf401e2b6, +	0xf5f1fd1b, +	0xf5f10800, +	0x00800200, +	0x0ff60185, +	0xf804bd00, +/* 0x0509: ctx_xfer */ +	0x81008000, +	0x000ff602, +	0x11f404bd, +	0x04e37e07, +/* 0x0519: ctx_xfer_not_load */ +	0x02167e00, +	0x8024bd00, +	0xf60247fc, +	0x04bd0002, +	0xb6012cf0, +	0xfc800320, +	0x02f6024a, +	0xf004bd00, +	0xa5f001ac, +	0x00008b02, +	0x040c9850, +	0xbb0fc4b6, +	0x0c9800bc, +	0x010d9800, +	0x3d7e000e, +	0xacf00001, +	0x40008b01, +	0x040c9850, +	0xbb0fc4b6, +	0x0c9800bc, +	0x020d9801, +	0x4e060f98, +	0x3d7e0800, +	0xacf00001, +	0x04a5f001, +	0x5030008b, +	0xb6040c98, +	0xbcbb0fc4, +	0x020c9800, +	0x98030d98, +	0x004e080f, +	0x013d7e02, +	0x020a7e00, +	0x0601f400, +/* 0x05a3: ctx_xfer_post */ +	0x7e0712f4, +/* 0x05a7: ctx_xfer_done */ +	0x7e000227, +	0xf80004cf, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 new file mode 100644 index 00000000000..bd30262d635 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5 @@ -0,0 +1,42 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#define NV_PGRAPH_GPCX_UNK__SIZE                                     0x00000001 + +#define CHIPSET GK208 +#include "macros.fuc" + +.section #nv108_grgpc_data +#define INCLUDE_DATA +#include "com.fuc" +#include "gpc.fuc" +#undef INCLUDE_DATA + +.section #nv108_grgpc_code +#define INCLUDE_CODE +bra #init +#include "com.fuc" +#include "gpc.fuc" +.align 256 +#undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h new file mode 100644 index 00000000000..31922707794 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnv108.fuc5.h @@ -0,0 +1,473 @@ +uint32_t nv108_grgpc_data[] = { +/* 0x0000: gpc_mmio_list_head */ +	0x0000006c, +/* 0x0004: gpc_mmio_list_tail */ +/* 0x0004: tpc_mmio_list_head */ +	0x0000006c, +/* 0x0008: tpc_mmio_list_tail */ +/* 0x0008: unk_mmio_list_head */ +	0x0000006c, +/* 0x000c: unk_mmio_list_tail */ +	0x0000006c, +/* 0x0010: gpc_id */ +	0x00000000, +/* 0x0014: tpc_count */ +	0x00000000, +/* 0x0018: tpc_mask */ +	0x00000000, +/* 0x001c: unk_count */ +	0x00000000, +/* 0x0020: unk_mask */ +	0x00000000, +/* 0x0024: cmd_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; + +uint32_t nv108_grgpc_code[] = { +	0x03140ef5, +/* 0x0004: queue_put */ +	0x9800d898, +	0x86f001d9, +	0xf489a408, +	0x020f0b1b, +	0x0002f87e, +/* 0x001a: queue_put_next */ +	0x98c400f8, +	0x0384b607, +	0xb6008dbb, +	0x8eb50880, +	0x018fb500, +	0xf00190b6, +	0xd9b50f94, +/* 0x0037: queue_get */ +	0xf400f801, +	0xd8980131, +	0x01d99800, +	0x0bf489a4, +	0x0789c421, +	0xbb0394b6, +	0x90b6009d, +	0x009e9808, +	0xb6019f98, +	0x84f00180, +	0x00d8b50f, +/* 0x0063: queue_get_done */ +	0xf80132f4, +/* 0x0065: nv_rd32 */ +	0xf0ecb200, +	0x00801fc9, +	0x0cf601ca, +/* 0x0073: nv_rd32_wait */ +	0x8c04bd00, +	0xcf01ca00, +	0xccc800cc, +	0xf61bf41f, +	0xec7e060a, +	0x008f0000, +	0xffcf01cb, +/* 0x008f: nv_wr32 */ +	0x8000f800, +	0xf601cc00, +	0x04bd000f, +	0xc9f0ecb2, +	0x1ec9f01f, +	0x01ca0080, +	0xbd000cf6, +/* 0x00a9: nv_wr32_wait */ +	0xca008c04, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f61b, +/* 0x00b8: wait_donez */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x00cf: wait_donez_ne */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf61bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x00ec: wait_doneo */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x0103: wait_doneo_e */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf60bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x0120: mmctx_size */ +/* 0x0122: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0x1bf4efa4, +	0xf89fb2ec, +/* 0x013d: mmctx_xfer */ +	0xf094bd00, +	0x00800199, +	0x09f60237, +	0xbd04bd00, +	0x05bbfd94, +	0x800f0bf4, +	0xf601c400, +	0x04bd000b, +/* 0x015f: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0xc6008018, +	0x000ef601, +	0x008004bd, +	0x0ff601c7, +	0xf004bd00, +/* 0x017a: mmctx_multi_disabled */ +	0xabc80199, +	0x10b4b600, +	0xc80cb9f0, +	0xe4b601ae, +	0x05befd11, +	0x01c50080, +	0xbd000bf6, +/* 0x0195: mmctx_exec_loop */ +/* 0x0195: mmctx_wait_free */ +	0xc5008e04, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f60b, +	0x05e9fd00, +	0x01c80080, +	0xbd000ef6, +	0x04c0b604, +	0x1bf4cda4, +	0x02abc8df, +/* 0x01bf: mmctx_fini_wait */ +	0x8b1c1bf4, +	0xcf01c500, +	0xb4f000bb, +	0x10b4b01f, +	0x0af31bf4, +	0x00b87e05, +	0x250ef400, +/* 0x01d8: mmctx_stop */ +	0xb600abc8, +	0xb9f010b4, +	0x12b9f00c, +	0x01c50080, +	0xbd000bf6, +/* 0x01ed: mmctx_stop_wait */ +	0xc5008b04, +	0x00bbcf01, +	0xf412bbc8, +/* 0x01fa: mmctx_done */ +	0x94bdf61b, +	0x800199f0, +	0xf6021700, +	0x04bd0009, +/* 0x020a: strand_wait */ +	0xa0f900f8, +	0xb87e020a, +	0xa0fc0000, +/* 0x0216: strand_pre */ +	0x0c0900f8, +	0x024afc80, +	0xbd0009f6, +	0x020a7e04, +/* 0x0227: strand_post */ +	0x0900f800, +	0x4afc800d, +	0x0009f602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0238: strand_set */ +	0xfc800f0c, +	0x0cf6024f, +	0x0c04bd00, +	0x4afc800b, +	0x000cf602, +	0xfc8004bd, +	0x0ef6024f, +	0x0c04bd00, +	0x4afc800a, +	0x000cf602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0268: strand_ctx_init */ +	0x99f094bd, +	0x37008003, +	0x0009f602, +	0x167e04bd, +	0x030e0002, +	0x0002387e, +	0xfc80c4bd, +	0x0cf60247, +	0x0c04bd00, +	0x4afc8001, +	0x000cf602, +	0x0a7e04bd, +	0x0c920002, +	0x46fc8001, +	0x000cf602, +	0x020c04bd, +	0x024afc80, +	0xbd000cf6, +	0x020a7e04, +	0x02277e00, +	0x42008800, +	0x20008902, +	0x0099cf02, +/* 0x02c7: ctx_init_strand_loop */ +	0xf608fe95, +	0x8ef6008e, +	0x808acf40, +	0xb606a5b6, +	0xeabb01a0, +	0x0480b600, +	0xf40192b6, +	0xe4b6e81b, +	0xf2efbc08, +	0x99f094bd, +	0x17008003, +	0x0009f602, +	0x00f804bd, +/* 0x02f8: error */ +	0xffb2e0f9, +	0x4098148e, +	0x00008f7e, +	0xffb2010f, +	0x409c1c8e, +	0x00008f7e, +	0x00f8e0fc, +/* 0x0314: init */ +	0x004104bd, +	0x0011cf42, +	0x010911e7, +	0xfe0814b6, +	0x02020014, +	0xf6120040, +	0x04bd0002, +	0xfe047241, +	0x00400010, +	0x0000f607, +	0x040204bd, +	0xf6040040, +	0x04bd0002, +	0x821031f4, +	0xcf018200, +	0x01030022, +	0xbb1f24f0, +	0x32b60432, +	0x0502b501, +	0x820603b5, +	0xcf018600, +	0x02b50022, +	0x0c308e04, +	0xbd24bd50, +/* 0x0377: init_unk_loop */ +	0x7e44bd34, +	0xb0000065, +	0x0bf400f6, +	0xbb010f0e, +	0x4ffd04f2, +	0x0130b605, +/* 0x038c: init_unk_next */ +	0xb60120b6, +	0x26b004e0, +	0xe21bf401, +/* 0x0398: init_unk_done */ +	0xb50703b5, +	0x00820804, +	0x22cf0201, +	0x9534bd00, +	0x00800825, +	0x05f601c0, +	0x8004bd00, +	0xf601c100, +	0x04bd0005, +	0x98000e98, +	0x207e010f, +	0x2fbb0001, +	0x003fbb00, +	0x98010e98, +	0x207e020f, +	0x0e980001, +	0x00effd05, +	0xbb002ebb, +	0x0e98003e, +	0x030f9802, +	0x0001207e, +	0xfd070e98, +	0x2ebb00ef, +	0x003ebb00, +	0x800235b6, +	0xf601d300, +	0x04bd0003, +	0xb60825b6, +	0x20b60635, +	0x0130b601, +	0xb60824b6, +	0x2fb20834, +	0x0002687e, +	0x80003fbb, +	0xf6020100, +	0x04bd0003, +	0x29f024bd, +	0x3000801f, +	0x0002f602, +/* 0x0436: main */ +	0x31f404bd, +	0x0028f400, +	0x377e240d, +	0x01f40000, +	0x04e4b0f4, +	0xfe1d18f4, +	0x06020181, +	0x12fd20bd, +	0x01e4b604, +	0xfe051efd, +	0x097e0018, +	0x0ef40005, +/* 0x0465: main_not_ctx_xfer */ +	0x10ef94d4, +	0x7e01f5f0, +	0xf40002f8, +/* 0x0472: ih */ +	0x80f9c70e, +	0xf90188fe, +	0xf990f980, +	0xf9b0f9a0, +	0xf9e0f9d0, +	0x4a04bdf0, +	0xaacf0200, +	0x04abc400, +	0x0d1f0bf4, +	0x1a004e24, +	0x4f00eecf, +	0xffcf1900, +	0x00047e00, +	0x40010e00, +	0x0ef61d00, +/* 0x04af: ih_no_fifo */ +	0x4004bd00, +	0x0af60100, +	0xfc04bd00, +	0xfce0fcf0, +	0xfcb0fcd0, +	0xfc90fca0, +	0x0088fe80, +	0x32f480fc, +/* 0x04cf: hub_barrier_done */ +	0x0f01f800, +	0x040e9801, +	0xb204febb, +	0x94188eff, +	0x008f7e40, +/* 0x04e3: ctx_redswitch */ +	0x0f00f800, +	0x85008020, +	0x000ff601, +	0x080e04bd, +/* 0x04f0: ctx_redswitch_delay */ +	0xf401e2b6, +	0xf5f1fd1b, +	0xf5f10800, +	0x00800200, +	0x0ff60185, +	0xf804bd00, +/* 0x0509: ctx_xfer */ +	0x81008000, +	0x000ff602, +	0x11f404bd, +	0x04e37e07, +/* 0x0519: ctx_xfer_not_load */ +	0x02167e00, +	0x8024bd00, +	0xf60247fc, +	0x04bd0002, +	0xb6012cf0, +	0xfc800320, +	0x02f6024a, +	0xf004bd00, +	0xa5f001ac, +	0x00008b02, +	0x040c9850, +	0xbb0fc4b6, +	0x0c9800bc, +	0x010d9800, +	0x3d7e000e, +	0xacf00001, +	0x40008b01, +	0x040c9850, +	0xbb0fc4b6, +	0x0c9800bc, +	0x020d9801, +	0x4e060f98, +	0x3d7e0800, +	0xacf00001, +	0x04a5f001, +	0x5030008b, +	0xb6040c98, +	0xbcbb0fc4, +	0x020c9800, +	0x98030d98, +	0x004e080f, +	0x013d7e02, +	0x020a7e00, +	0x0601f400, +/* 0x05a3: ctx_xfer_post */ +	0x7e0712f4, +/* 0x05a7: ctx_xfer_done */ +	0x7e000227, +	0xf80004cf, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h index f2b0dea8011..325cc7b7b2f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc.h @@ -37,14 +37,14 @@ uint32_t nvc0_grgpc_data[] = {  };  uint32_t nvc0_grgpc_code[] = { -	0x03180ef5, +	0x03a10ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -68,184 +68,214 @@ uint32_t nvc0_grgpc_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f00f00, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f00f,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf00f0007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f00f00, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -259,59 +289,75 @@ uint32_t nvc0_grgpc_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0xe0f900f8, -	0x9814e7f1, -	0xf440e3f0, -	0xe0b78d21, -	0xf7f0041c, -	0x8d21f401, -	0x00f8e0fc, -/* 0x0318: init */ -	0x04fe04bd, -	0x0017f100, -	0x0227f012, -	0xf10012d0, -	0xfe042617, -	0x17f10010, -	0x10d00400, -	0x0427f0c0, -	0xf40012d0, -	0x17f11031, -	0x14b60608, -	0x0012cf06, -	0xf00137f0, -	0x32bb1f24, -	0x0132b604, -	0x80050280, -	0x10b70603, -	0x12cf0400, +	0xf102ffb9, +	0xf09814e7, +	0x21f440e3, +	0x01f7f09d, +	0xf102ffb9, +	0xf09c1ce7, +	0x21f440e3, +	0xf8e0fc9d, +/* 0x03a1: init */ +	0xf104bd00, +	0xf0420017, +	0x11cf0013, +	0x0911e700, +	0x0814b601, +	0xf00014fe, +	0x07f10227, +	0x03f01200, +	0x0002d000, +	0x17f104bd, +	0x10fe04e6, +	0x0007f100, +	0x0003f007, +	0xbd0000d0, +	0x0427f004, +	0x040007f1, +	0xd00003f0, +	0x04bd0002, +	0xf11031f4, +	0xf0820027, +	0x22cf0123, +	0x0137f000, +	0xbb1f24f0, +	0x32b60432, +	0x05028001, +	0xf1060380, +	0xf0860027, +	0x22cf0123,  	0x04028000,  	0x010027f1,  	0xcf0223f0,  	0x34bd0022, -	0x070047f1, -	0x950644b6, -	0x45d00825, -	0x4045d000, -	0x98000e98, -	0x21f5010f, -	0x2fbb0147, -	0x003fbb00, -	0x98010e98, -	0x21f5020f, -	0x0e980147, -	0x00effd05, -	0xbb002ebb, -	0x40b7003e, -	0x35b61300, -	0x0043d002, +	0xf1082595, +	0xf0c00007, +	0x05d00103, +	0xf104bd00, +	0xf0c10007, +	0x05d00103, +	0x9804bd00, +	0x0f98000e, +	0x5021f501, +	0x002fbb01, +	0x98003fbb, +	0x0f98010e, +	0x5021f502, +	0x050e9801, +	0xbb00effd, +	0x3ebb002e, +	0x0235b600, +	0xd30007f1, +	0xd00103f0, +	0x04bd0003,  	0xb60825b6,  	0x20b60635,  	0x0130b601,  	0xb60824b6,  	0x2fb90834, -	0x7121f502, +	0xd321f502,  	0x003fbb02,  	0x010007f1,  	0xd00203f0, @@ -320,7 +366,7 @@ uint32_t nvc0_grgpc_code[] = {  	0x0007f11f,  	0x0203f008,  	0xbd0002d0, -/* 0x03e9: main */ +/* 0x04a9: main */  	0x0031f404,  	0xf00028f4,  	0x21f41cd7, @@ -332,74 +378,87 @@ uint32_t nvc0_grgpc_code[] = {  	0x01e4b604,  	0xfe051efd,  	0x21f50018, -	0x0ef404ad, -/* 0x0419: main_not_ctx_xfer */ +	0x0ef4059e, +/* 0x04d9: main_not_ctx_xfer */  	0x10ef94d3,  	0xf501f5f0, -	0xf402fe21, -/* 0x0426: ih */ +	0xf4037e21, +/* 0x04e6: ih */  	0x80f9c60e,  	0xf90188fe,  	0xf990f980,  	0xf9b0f9a0,  	0xf9e0f9d0, -	0xcf04bdf0, -	0xabc4800a, -	0x1d0bf404, -	0x1900b7f1, -	0xcf1cd7f0, -	0xbfcf40be, -	0x0421f400, -	0x0400b0b7, -	0xd001e7f0, -/* 0x045e: ih_no_fifo */ -	0x0ad000be, -	0xfcf0fc40, -	0xfcd0fce0, -	0xfca0fcb0, -	0xfe80fc90, -	0x80fc0088, -	0xf80032f4, -/* 0x0479: hub_barrier_done */ -	0x01f7f001, -	0xbb040e98, -	0xe7f104fe, -	0xe3f09418, -	0x8d21f440, -/* 0x048e: ctx_redswitch */ -	0xe7f100f8, -	0xe4b60614, -	0x20f7f006, -	0xf000efd0, -/* 0x049e: ctx_redswitch_delay */ -	0xf2b608f7, +	0xf104bdf0, +	0xf00200a7, +	0xaacf00a3, +	0x04abc400, +	0xf02c0bf4, +	0xe7f11cd7, +	0xe3f01a00, +	0x00eecf00, +	0x1900f7f1, +	0xcf00f3f0, +	0x21f400ff, +	0x01e7f004, +	0x1d0007f1, +	0xd00003f0, +	0x04bd000e, +/* 0x0534: ih_no_fifo */ +	0x010007f1, +	0xd00003f0, +	0x04bd000a, +	0xe0fcf0fc, +	0xb0fcd0fc, +	0x90fca0fc, +	0x88fe80fc, +	0xf480fc00, +	0x01f80032, +/* 0x0558: hub_barrier_done */ +	0x9801f7f0, +	0xfebb040e, +	0x02ffb904, +	0x9418e7f1, +	0xf440e3f0, +	0x00f89d21, +/* 0x0570: ctx_redswitch */ +	0xf120f7f0, +	0xf0850007, +	0x0fd00103, +	0xf004bd00, +/* 0x0582: ctx_redswitch_delay */ +	0xe2b608e7,  	0xfd1bf401, -	0x0a20f7f1, -	0xf800efd0, -/* 0x04ad: ctx_xfer */ -	0x0417f100, -	0x0614b60a, -	0xf4001fd0, -	0x21f50711, -/* 0x04be: ctx_xfer_not_load */ -	0x17f1048e, -	0x13f04afc, -	0x0c27f002, -	0xf50012d0, -	0xf1021521, -	0xf047fc27, -	0x20d00223, -	0x012cf000, -	0xd00320b6, -	0xacf00012, -	0x02a5f001, -	0xf000b7f0, +	0x0800f5f1, +	0x0200f5f1, +	0x850007f1, +	0xd00103f0, +	0x04bd000f, +/* 0x059e: ctx_xfer */ +	0x07f100f8, +	0x03f08100, +	0x000fd002, +	0x11f404bd, +	0x7021f507, +/* 0x05b1: ctx_xfer_not_load */ +	0x6a21f505, +	0xf124bd02, +	0xf047fc07, +	0x02d00203, +	0xf004bd00, +	0x20b6012c, +	0xfc07f103, +	0x0203f04a, +	0xbd0002d0, +	0x01acf004, +	0xf102a5f0, +	0xf00000b7,  	0x0c9850b3,  	0x0fc4b604,  	0x9800bcbb,  	0x0d98000c,  	0x00e7f001, -	0x016621f5, +	0x016f21f5,  	0xf001acf0,  	0xb7f104a5,  	0xb3f04000, @@ -409,17 +468,20 @@ uint32_t nvc0_grgpc_code[] = {  	0x020d9801,  	0xf1060f98,  	0xf50800e7, -	0xf5016621, -	0xf4021521, +	0xf5016f21, +	0xf4025e21,  	0x12f40601, -/* 0x0535: ctx_xfer_post */ -	0xfc17f114, -	0x0213f04a, -	0xd00d27f0, -	0x21f50012, -/* 0x0546: ctx_xfer_done */ -	0x21f50215, -	0x00f80479, +/* 0x0629: ctx_xfer_post */ +	0x7f21f507, +/* 0x062d: ctx_xfer_done */ +	0x5821f502, +	0x0000f805, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h index dd346c2a162..d1504a4059c 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvd7.fuc.h @@ -41,14 +41,14 @@ uint32_t nvd7_grgpc_data[] = {  };  uint32_t nvd7_grgpc_code[] = { -	0x03180ef5, +	0x03a10ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -72,184 +72,214 @@ uint32_t nvd7_grgpc_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f00f00, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f00f,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf00f0007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f00f00, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -263,81 +293,97 @@ uint32_t nvd7_grgpc_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0xe0f900f8, -	0x9814e7f1, -	0xf440e3f0, -	0xe0b78d21, -	0xf7f0041c, -	0x8d21f401, -	0x00f8e0fc, -/* 0x0318: init */ -	0x04fe04bd, -	0x0017f100, -	0x0227f012, -	0xf10012d0, -	0xfe047017, -	0x17f10010, -	0x10d00400, -	0x0427f0c0, -	0xf40012d0, -	0x17f11031, -	0x14b60608, -	0x0012cf06, -	0xf00137f0, -	0x32bb1f24, -	0x0132b604, -	0x80050280, -	0x10b70603, -	0x12cf0400, +	0xf102ffb9, +	0xf09814e7, +	0x21f440e3, +	0x01f7f09d, +	0xf102ffb9, +	0xf09c1ce7, +	0x21f440e3, +	0xf8e0fc9d, +/* 0x03a1: init */ +	0xf104bd00, +	0xf0420017, +	0x11cf0013, +	0x0911e700, +	0x0814b601, +	0xf00014fe, +	0x07f10227, +	0x03f01200, +	0x0002d000, +	0x17f104bd, +	0x10fe0530, +	0x0007f100, +	0x0003f007, +	0xbd0000d0, +	0x0427f004, +	0x040007f1, +	0xd00003f0, +	0x04bd0002, +	0xf11031f4, +	0xf0820027, +	0x22cf0123, +	0x0137f000, +	0xbb1f24f0, +	0x32b60432, +	0x05028001, +	0xf1060380, +	0xf0860027, +	0x22cf0123,  	0x04028000,  	0x0c30e7f1,  	0xbd50e3f0,  	0xbd34bd24, -/* 0x0371: init_unk_loop */ +/* 0x0421: init_unk_loop */  	0x6821f444,  	0xf400f6b0,  	0xf7f00f0b,  	0x04f2bb01,  	0xb6054ffd, -/* 0x0386: init_unk_next */ +/* 0x0436: init_unk_next */  	0x20b60130,  	0x04e0b601,  	0xf40126b0, -/* 0x0392: init_unk_done */ +/* 0x0442: init_unk_done */  	0x0380e21b,  	0x08048007,  	0x010027f1,  	0xcf0223f0,  	0x34bd0022, -	0x070047f1, -	0x950644b6, -	0x45d00825, -	0x4045d000, -	0x98000e98, -	0x21f5010f, -	0x2fbb0147, -	0x003fbb00, -	0x98010e98, -	0x21f5020f, -	0x0e980147, -	0x00effd05, -	0xbb002ebb, -	0x0e98003e, -	0x030f9802, -	0x014721f5, -	0xfd070e98, -	0x2ebb00ef, -	0x003ebb00, -	0x130040b7, -	0xd00235b6, -	0x25b60043, +	0xf1082595, +	0xf0c00007, +	0x05d00103, +	0xf104bd00, +	0xf0c10007, +	0x05d00103, +	0x9804bd00, +	0x0f98000e, +	0x5021f501, +	0x002fbb01, +	0x98003fbb, +	0x0f98010e, +	0x5021f502, +	0x050e9801, +	0xbb00effd, +	0x3ebb002e, +	0x020e9800, +	0xf5030f98, +	0x98015021, +	0xeffd070e, +	0x002ebb00, +	0xb6003ebb, +	0x07f10235, +	0x03f0d300, +	0x0003d001, +	0x25b604bd,  	0x0635b608,  	0xb60120b6,  	0x24b60130,  	0x0834b608,  	0xf5022fb9, -	0xbb027121, +	0xbb02d321,  	0x07f1003f,  	0x03f00100,  	0x0003d002, @@ -345,7 +391,7 @@ uint32_t nvd7_grgpc_code[] = {  	0xf11f29f0,  	0xf0080007,  	0x02d00203, -/* 0x0433: main */ +/* 0x04f3: main */  	0xf404bd00,  	0x28f40031,  	0x24d7f000, @@ -357,75 +403,88 @@ uint32_t nvd7_grgpc_code[] = {  	0xb60412fd,  	0x1efd01e4,  	0x0018fe05, -	0x04f721f5, -/* 0x0463: main_not_ctx_xfer */ +	0x05e821f5, +/* 0x0523: main_not_ctx_xfer */  	0x94d30ef4,  	0xf5f010ef, -	0xfe21f501, -	0xc60ef402, -/* 0x0470: ih */ +	0x7e21f501, +	0xc60ef403, +/* 0x0530: ih */  	0x88fe80f9,  	0xf980f901,  	0xf9a0f990,  	0xf9d0f9b0,  	0xbdf0f9e0, -	0x800acf04, -	0xf404abc4, -	0xb7f11d0b, -	0xd7f01900, -	0x40becf24, -	0xf400bfcf, -	0xb0b70421, -	0xe7f00400, -	0x00bed001, -/* 0x04a8: ih_no_fifo */ -	0xfc400ad0, -	0xfce0fcf0, -	0xfcb0fcd0, -	0xfc90fca0, -	0x0088fe80, -	0x32f480fc, -/* 0x04c3: hub_barrier_done */ -	0xf001f800, -	0x0e9801f7, -	0x04febb04, -	0x9418e7f1, -	0xf440e3f0, -	0x00f88d21, -/* 0x04d8: ctx_redswitch */ -	0x0614e7f1, -	0xf006e4b6, -	0xefd020f7, -	0x08f7f000, -/* 0x04e8: ctx_redswitch_delay */ -	0xf401f2b6, -	0xf7f1fd1b, -	0xefd00a20, -/* 0x04f7: ctx_xfer */ -	0xf100f800, -	0xb60a0417, -	0x1fd00614, -	0x0711f400, -	0x04d821f5, -/* 0x0508: ctx_xfer_not_load */ -	0x4afc17f1, -	0xf00213f0, -	0x12d00c27, -	0x1521f500, -	0xfc27f102, -	0x0223f047, -	0xf00020d0, -	0x20b6012c, -	0x0012d003, -	0xf001acf0, -	0xb7f002a5, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x24d7f02c, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00, +	0xf00421f4, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x057e: ih_no_fifo */ +	0x07f104bd, +	0x03f00100, +	0x000ad000, +	0xf0fc04bd, +	0xd0fce0fc, +	0xa0fcb0fc, +	0x80fc90fc, +	0xfc0088fe, +	0x0032f480, +/* 0x05a2: hub_barrier_done */ +	0xf7f001f8, +	0x040e9801, +	0xb904febb, +	0xe7f102ff, +	0xe3f09418, +	0x9d21f440, +/* 0x05ba: ctx_redswitch */ +	0xf7f000f8, +	0x0007f120, +	0x0103f085, +	0xbd000fd0, +	0x08e7f004, +/* 0x05cc: ctx_redswitch_delay */ +	0xf401e2b6, +	0xf5f1fd1b, +	0xf5f10800, +	0x07f10200, +	0x03f08500, +	0x000fd001, +	0x00f804bd, +/* 0x05e8: ctx_xfer */ +	0x810007f1, +	0xd00203f0, +	0x04bd000f, +	0xf50711f4, +/* 0x05fb: ctx_xfer_not_load */ +	0xf505ba21, +	0xbd026a21, +	0xfc07f124, +	0x0203f047, +	0xbd0002d0, +	0x012cf004, +	0xf10320b6, +	0xf04afc07, +	0x02d00203, +	0xf004bd00, +	0xa5f001ac, +	0x00b7f102,  	0x50b3f000,  	0xb6040c98,  	0xbcbb0fc4,  	0x000c9800,  	0xf0010d98,  	0x21f500e7, -	0xacf00166, +	0xacf0016f,  	0x00b7f101,  	0x50b3f040,  	0xb6040c98, @@ -434,7 +493,7 @@ uint32_t nvd7_grgpc_code[] = {  	0x98020d98,  	0xe7f1060f,  	0x21f50800, -	0xacf00166, +	0xacf0016f,  	0x04a5f001,  	0x3000b7f1,  	0x9850b3f0, @@ -443,18 +502,21 @@ uint32_t nvd7_grgpc_code[] = {  	0x98020c98,  	0x0f98030d,  	0x00e7f108, -	0x6621f502, -	0x1521f501, +	0x6f21f502, +	0x5e21f501,  	0x0601f402, -/* 0x05a3: ctx_xfer_post */ -	0xf11412f4, -	0xf04afc17, -	0x27f00213, -	0x0012d00d, -	0x021521f5, -/* 0x05b4: ctx_xfer_done */ -	0x04c321f5, -	0x000000f8, +/* 0x0697: ctx_xfer_post */ +	0xf50712f4, +/* 0x069b: ctx_xfer_done */ +	0xf5027f21, +	0xf805a221, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h index 7ff5ef6b080..855b220378f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnve0.fuc.h @@ -41,14 +41,14 @@ uint32_t nve0_grgpc_data[] = {  };  uint32_t nve0_grgpc_code[] = { -	0x03180ef5, +	0x03a10ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -72,184 +72,214 @@ uint32_t nve0_grgpc_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f00f00, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f00f,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf00f0007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f00f00, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -263,81 +293,97 @@ uint32_t nve0_grgpc_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0xe0f900f8, -	0x9814e7f1, -	0xf440e3f0, -	0xe0b78d21, -	0xf7f0041c, -	0x8d21f401, -	0x00f8e0fc, -/* 0x0318: init */ -	0x04fe04bd, -	0x0017f100, -	0x0227f012, -	0xf10012d0, -	0xfe047017, -	0x17f10010, -	0x10d00400, -	0x0427f0c0, -	0xf40012d0, -	0x17f11031, -	0x14b60608, -	0x0012cf06, -	0xf00137f0, -	0x32bb1f24, -	0x0132b604, -	0x80050280, -	0x10b70603, -	0x12cf0400, +	0xf102ffb9, +	0xf09814e7, +	0x21f440e3, +	0x01f7f09d, +	0xf102ffb9, +	0xf09c1ce7, +	0x21f440e3, +	0xf8e0fc9d, +/* 0x03a1: init */ +	0xf104bd00, +	0xf0420017, +	0x11cf0013, +	0x0911e700, +	0x0814b601, +	0xf00014fe, +	0x07f10227, +	0x03f01200, +	0x0002d000, +	0x17f104bd, +	0x10fe0530, +	0x0007f100, +	0x0003f007, +	0xbd0000d0, +	0x0427f004, +	0x040007f1, +	0xd00003f0, +	0x04bd0002, +	0xf11031f4, +	0xf0820027, +	0x22cf0123, +	0x0137f000, +	0xbb1f24f0, +	0x32b60432, +	0x05028001, +	0xf1060380, +	0xf0860027, +	0x22cf0123,  	0x04028000,  	0x0c30e7f1,  	0xbd50e3f0,  	0xbd34bd24, -/* 0x0371: init_unk_loop */ +/* 0x0421: init_unk_loop */  	0x6821f444,  	0xf400f6b0,  	0xf7f00f0b,  	0x04f2bb01,  	0xb6054ffd, -/* 0x0386: init_unk_next */ +/* 0x0436: init_unk_next */  	0x20b60130,  	0x04e0b601,  	0xf40126b0, -/* 0x0392: init_unk_done */ +/* 0x0442: init_unk_done */  	0x0380e21b,  	0x08048007,  	0x010027f1,  	0xcf0223f0,  	0x34bd0022, -	0x070047f1, -	0x950644b6, -	0x45d00825, -	0x4045d000, -	0x98000e98, -	0x21f5010f, -	0x2fbb0147, -	0x003fbb00, -	0x98010e98, -	0x21f5020f, -	0x0e980147, -	0x00effd05, -	0xbb002ebb, -	0x0e98003e, -	0x030f9802, -	0x014721f5, -	0xfd070e98, -	0x2ebb00ef, -	0x003ebb00, -	0x130040b7, -	0xd00235b6, -	0x25b60043, +	0xf1082595, +	0xf0c00007, +	0x05d00103, +	0xf104bd00, +	0xf0c10007, +	0x05d00103, +	0x9804bd00, +	0x0f98000e, +	0x5021f501, +	0x002fbb01, +	0x98003fbb, +	0x0f98010e, +	0x5021f502, +	0x050e9801, +	0xbb00effd, +	0x3ebb002e, +	0x020e9800, +	0xf5030f98, +	0x98015021, +	0xeffd070e, +	0x002ebb00, +	0xb6003ebb, +	0x07f10235, +	0x03f0d300, +	0x0003d001, +	0x25b604bd,  	0x0635b608,  	0xb60120b6,  	0x24b60130,  	0x0834b608,  	0xf5022fb9, -	0xbb027121, +	0xbb02d321,  	0x07f1003f,  	0x03f00100,  	0x0003d002, @@ -345,7 +391,7 @@ uint32_t nve0_grgpc_code[] = {  	0xf11f29f0,  	0xf0080007,  	0x02d00203, -/* 0x0433: main */ +/* 0x04f3: main */  	0xf404bd00,  	0x28f40031,  	0x24d7f000, @@ -357,75 +403,88 @@ uint32_t nve0_grgpc_code[] = {  	0xb60412fd,  	0x1efd01e4,  	0x0018fe05, -	0x04f721f5, -/* 0x0463: main_not_ctx_xfer */ +	0x05e821f5, +/* 0x0523: main_not_ctx_xfer */  	0x94d30ef4,  	0xf5f010ef, -	0xfe21f501, -	0xc60ef402, -/* 0x0470: ih */ +	0x7e21f501, +	0xc60ef403, +/* 0x0530: ih */  	0x88fe80f9,  	0xf980f901,  	0xf9a0f990,  	0xf9d0f9b0,  	0xbdf0f9e0, -	0x800acf04, -	0xf404abc4, -	0xb7f11d0b, -	0xd7f01900, -	0x40becf24, -	0xf400bfcf, -	0xb0b70421, -	0xe7f00400, -	0x00bed001, -/* 0x04a8: ih_no_fifo */ -	0xfc400ad0, -	0xfce0fcf0, -	0xfcb0fcd0, -	0xfc90fca0, -	0x0088fe80, -	0x32f480fc, -/* 0x04c3: hub_barrier_done */ -	0xf001f800, -	0x0e9801f7, -	0x04febb04, -	0x9418e7f1, -	0xf440e3f0, -	0x00f88d21, -/* 0x04d8: ctx_redswitch */ -	0x0614e7f1, -	0xf006e4b6, -	0xefd020f7, -	0x08f7f000, -/* 0x04e8: ctx_redswitch_delay */ -	0xf401f2b6, -	0xf7f1fd1b, -	0xefd00a20, -/* 0x04f7: ctx_xfer */ -	0xf100f800, -	0xb60a0417, -	0x1fd00614, -	0x0711f400, -	0x04d821f5, -/* 0x0508: ctx_xfer_not_load */ -	0x4afc17f1, -	0xf00213f0, -	0x12d00c27, -	0x1521f500, -	0xfc27f102, -	0x0223f047, -	0xf00020d0, -	0x20b6012c, -	0x0012d003, -	0xf001acf0, -	0xb7f002a5, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x24d7f02c, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00, +	0xf00421f4, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x057e: ih_no_fifo */ +	0x07f104bd, +	0x03f00100, +	0x000ad000, +	0xf0fc04bd, +	0xd0fce0fc, +	0xa0fcb0fc, +	0x80fc90fc, +	0xfc0088fe, +	0x0032f480, +/* 0x05a2: hub_barrier_done */ +	0xf7f001f8, +	0x040e9801, +	0xb904febb, +	0xe7f102ff, +	0xe3f09418, +	0x9d21f440, +/* 0x05ba: ctx_redswitch */ +	0xf7f000f8, +	0x0007f120, +	0x0103f085, +	0xbd000fd0, +	0x08e7f004, +/* 0x05cc: ctx_redswitch_delay */ +	0xf401e2b6, +	0xf5f1fd1b, +	0xf5f10800, +	0x07f10200, +	0x03f08500, +	0x000fd001, +	0x00f804bd, +/* 0x05e8: ctx_xfer */ +	0x810007f1, +	0xd00203f0, +	0x04bd000f, +	0xf50711f4, +/* 0x05fb: ctx_xfer_not_load */ +	0xf505ba21, +	0xbd026a21, +	0xfc07f124, +	0x0203f047, +	0xbd0002d0, +	0x012cf004, +	0xf10320b6, +	0xf04afc07, +	0x02d00203, +	0xf004bd00, +	0xa5f001ac, +	0x00b7f102,  	0x50b3f000,  	0xb6040c98,  	0xbcbb0fc4,  	0x000c9800,  	0xf0010d98,  	0x21f500e7, -	0xacf00166, +	0xacf0016f,  	0x00b7f101,  	0x50b3f040,  	0xb6040c98, @@ -434,7 +493,7 @@ uint32_t nve0_grgpc_code[] = {  	0x98020d98,  	0xe7f1060f,  	0x21f50800, -	0xacf00166, +	0xacf0016f,  	0x04a5f001,  	0x3000b7f1,  	0x9850b3f0, @@ -443,18 +502,21 @@ uint32_t nve0_grgpc_code[] = {  	0x98020c98,  	0x0f98030d,  	0x00e7f108, -	0x6621f502, -	0x1521f501, +	0x6f21f502, +	0x5e21f501,  	0x0601f402, -/* 0x05a3: ctx_xfer_post */ -	0xf11412f4, -	0xf04afc17, -	0x27f00213, -	0x0012d00d, -	0x021521f5, -/* 0x05b4: ctx_xfer_done */ -	0x04c321f5, -	0x000000f8, +/* 0x0697: ctx_xfer_post */ +	0xf50712f4, +/* 0x069b: ctx_xfer_done */ +	0xf5027f21, +	0xf805a221, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h index f870507be88..1b803197d28 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvf0.fuc.h @@ -41,14 +41,14 @@ uint32_t nvf0_grgpc_data[] = {  };  uint32_t nvf0_grgpc_code[] = { -	0x03180ef5, +	0x03a10ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -72,184 +72,214 @@ uint32_t nvf0_grgpc_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f03700, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f037, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f03700, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f037,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf0370007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x370007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f03700, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x370007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -263,81 +293,97 @@ uint32_t nvf0_grgpc_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0xe0f900f8, -	0x9814e7f1, -	0xf440e3f0, -	0xe0b78d21, -	0xf7f0041c, -	0x8d21f401, -	0x00f8e0fc, -/* 0x0318: init */ -	0x04fe04bd, -	0x0017f100, -	0x0227f012, -	0xf10012d0, -	0xfe047017, -	0x17f10010, -	0x10d00400, -	0x0427f0c0, -	0xf40012d0, -	0x17f11031, -	0x14b60608, -	0x0012cf06, -	0xf00137f0, -	0x32bb1f24, -	0x0132b604, -	0x80050280, -	0x10b70603, -	0x12cf0400, +	0xf102ffb9, +	0xf09814e7, +	0x21f440e3, +	0x01f7f09d, +	0xf102ffb9, +	0xf09c1ce7, +	0x21f440e3, +	0xf8e0fc9d, +/* 0x03a1: init */ +	0xf104bd00, +	0xf0420017, +	0x11cf0013, +	0x0911e700, +	0x0814b601, +	0xf00014fe, +	0x07f10227, +	0x03f01200, +	0x0002d000, +	0x17f104bd, +	0x10fe0530, +	0x0007f100, +	0x0003f007, +	0xbd0000d0, +	0x0427f004, +	0x040007f1, +	0xd00003f0, +	0x04bd0002, +	0xf11031f4, +	0xf0820027, +	0x22cf0123, +	0x0137f000, +	0xbb1f24f0, +	0x32b60432, +	0x05028001, +	0xf1060380, +	0xf0860027, +	0x22cf0123,  	0x04028000,  	0x0c30e7f1,  	0xbd50e3f0,  	0xbd34bd24, -/* 0x0371: init_unk_loop */ +/* 0x0421: init_unk_loop */  	0x6821f444,  	0xf400f6b0,  	0xf7f00f0b,  	0x04f2bb01,  	0xb6054ffd, -/* 0x0386: init_unk_next */ +/* 0x0436: init_unk_next */  	0x20b60130,  	0x04e0b601,  	0xf40226b0, -/* 0x0392: init_unk_done */ +/* 0x0442: init_unk_done */  	0x0380e21b,  	0x08048007,  	0x010027f1,  	0xcf0223f0,  	0x34bd0022, -	0x070047f1, -	0x950644b6, -	0x45d00825, -	0x4045d000, -	0x98000e98, -	0x21f5010f, -	0x2fbb0147, -	0x003fbb00, -	0x98010e98, -	0x21f5020f, -	0x0e980147, -	0x00effd05, -	0xbb002ebb, -	0x0e98003e, -	0x030f9802, -	0x014721f5, -	0xfd070e98, -	0x2ebb00ef, -	0x003ebb00, -	0x130040b7, -	0xd00235b6, -	0x25b60043, +	0xf1082595, +	0xf0c00007, +	0x05d00103, +	0xf104bd00, +	0xf0c10007, +	0x05d00103, +	0x9804bd00, +	0x0f98000e, +	0x5021f501, +	0x002fbb01, +	0x98003fbb, +	0x0f98010e, +	0x5021f502, +	0x050e9801, +	0xbb00effd, +	0x3ebb002e, +	0x020e9800, +	0xf5030f98, +	0x98015021, +	0xeffd070e, +	0x002ebb00, +	0xb6003ebb, +	0x07f10235, +	0x03f0d300, +	0x0003d001, +	0x25b604bd,  	0x0635b608,  	0xb60120b6,  	0x24b60130,  	0x0834b608,  	0xf5022fb9, -	0xbb027121, +	0xbb02d321,  	0x07f1003f,  	0x03f00100,  	0x0003d002, @@ -345,7 +391,7 @@ uint32_t nvf0_grgpc_code[] = {  	0xf11f29f0,  	0xf0300007,  	0x02d00203, -/* 0x0433: main */ +/* 0x04f3: main */  	0xf404bd00,  	0x28f40031,  	0x24d7f000, @@ -357,75 +403,88 @@ uint32_t nvf0_grgpc_code[] = {  	0xb60412fd,  	0x1efd01e4,  	0x0018fe05, -	0x04f721f5, -/* 0x0463: main_not_ctx_xfer */ +	0x05e821f5, +/* 0x0523: main_not_ctx_xfer */  	0x94d30ef4,  	0xf5f010ef, -	0xfe21f501, -	0xc60ef402, -/* 0x0470: ih */ +	0x7e21f501, +	0xc60ef403, +/* 0x0530: ih */  	0x88fe80f9,  	0xf980f901,  	0xf9a0f990,  	0xf9d0f9b0,  	0xbdf0f9e0, -	0x800acf04, -	0xf404abc4, -	0xb7f11d0b, -	0xd7f01900, -	0x40becf24, -	0xf400bfcf, -	0xb0b70421, -	0xe7f00400, -	0x00bed001, -/* 0x04a8: ih_no_fifo */ -	0xfc400ad0, -	0xfce0fcf0, -	0xfcb0fcd0, -	0xfc90fca0, -	0x0088fe80, -	0x32f480fc, -/* 0x04c3: hub_barrier_done */ -	0xf001f800, -	0x0e9801f7, -	0x04febb04, -	0x9418e7f1, -	0xf440e3f0, -	0x00f88d21, -/* 0x04d8: ctx_redswitch */ -	0x0614e7f1, -	0xf006e4b6, -	0xefd020f7, -	0x08f7f000, -/* 0x04e8: ctx_redswitch_delay */ -	0xf401f2b6, -	0xf7f1fd1b, -	0xefd00a20, -/* 0x04f7: ctx_xfer */ -	0xf100f800, -	0xb60a0417, -	0x1fd00614, -	0x0711f400, -	0x04d821f5, -/* 0x0508: ctx_xfer_not_load */ -	0x4afc17f1, -	0xf00213f0, -	0x12d00c27, -	0x1521f500, -	0xfc27f102, -	0x0223f047, -	0xf00020d0, -	0x20b6012c, -	0x0012d003, -	0xf001acf0, -	0xb7f002a5, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x24d7f02c, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00, +	0xf00421f4, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x057e: ih_no_fifo */ +	0x07f104bd, +	0x03f00100, +	0x000ad000, +	0xf0fc04bd, +	0xd0fce0fc, +	0xa0fcb0fc, +	0x80fc90fc, +	0xfc0088fe, +	0x0032f480, +/* 0x05a2: hub_barrier_done */ +	0xf7f001f8, +	0x040e9801, +	0xb904febb, +	0xe7f102ff, +	0xe3f09418, +	0x9d21f440, +/* 0x05ba: ctx_redswitch */ +	0xf7f000f8, +	0x0007f120, +	0x0103f085, +	0xbd000fd0, +	0x08e7f004, +/* 0x05cc: ctx_redswitch_delay */ +	0xf401e2b6, +	0xf5f1fd1b, +	0xf5f10800, +	0x07f10200, +	0x03f08500, +	0x000fd001, +	0x00f804bd, +/* 0x05e8: ctx_xfer */ +	0x810007f1, +	0xd00203f0, +	0x04bd000f, +	0xf50711f4, +/* 0x05fb: ctx_xfer_not_load */ +	0xf505ba21, +	0xbd026a21, +	0xfc07f124, +	0x0203f047, +	0xbd0002d0, +	0x012cf004, +	0xf10320b6, +	0xf04afc07, +	0x02d00203, +	0xf004bd00, +	0xa5f001ac, +	0x00b7f102,  	0x50b3f000,  	0xb6040c98,  	0xbcbb0fc4,  	0x000c9800,  	0xf0010d98,  	0x21f500e7, -	0xacf00166, +	0xacf0016f,  	0x00b7f101,  	0x50b3f040,  	0xb6040c98, @@ -434,7 +493,7 @@ uint32_t nvf0_grgpc_code[] = {  	0x98020d98,  	0xe7f1060f,  	0x21f50800, -	0xacf00166, +	0xacf0016f,  	0x04a5f001,  	0x3000b7f1,  	0x9850b3f0, @@ -443,18 +502,21 @@ uint32_t nvf0_grgpc_code[] = {  	0x98020c98,  	0x0f98030d,  	0x00e7f108, -	0x6621f502, -	0x1521f501, +	0x6f21f502, +	0x5e21f501,  	0x0601f402, -/* 0x05a3: ctx_xfer_post */ -	0xf11412f4, -	0xf04afc17, -	0x27f00213, -	0x0012d00d, -	0x021521f5, -/* 0x05b4: ctx_xfer_done */ -	0x04c321f5, -	0x000000f8, +/* 0x0697: ctx_xfer_post */ +	0xf50712f4, +/* 0x069b: ctx_xfer_done */ +	0xf5027f21, +	0xf805a221, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc index b82d2ae8991..b4ad18bf5a2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hub.fuc @@ -49,7 +49,7 @@ hub_mmio_list_next:  #ifdef INCLUDE_CODE  // reports an exception to the host  // -// In: $r15 error code (see nvc0.fuc) +// In: $r15 error code (see os.h)  //  error:  	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(5), 0, $r15) @@ -68,60 +68,57 @@ error:  //  init:  	clear b32 $r0 -	mov $sp $r0  	mov $xdbase $r0 +	// setup stack +	nv_iord($r1, NV_PGRAPH_FECS_CAPS, 0) +	extr $r1 $r1 9:17 +	shl b32 $r1 8 +	mov $sp $r1 +  	// enable fifo access -	mov $r1 0x1200 -	mov $r2 2 -	iowr I[$r1 + 0x000] $r2	// FIFO_ENABLE +	mov $r2 NV_PGRAPH_FECS_ACCESS_FIFO +	nv_iowr(NV_PGRAPH_FECS_ACCESS, 0, $r2)  	// setup i0 handler, and route all interrupts to it  	mov $r1 #ih  	mov $iv0 $r1 -	mov $r1 0x400 -	iowr I[$r1 + 0x300] $r0	// INTR_DISPATCH -	// route HUB_CHANNEL_SWITCH to fuc interrupt 8 -	mov $r3 0x404 -	shl b32 $r3 6 -	mov $r2 0x2003		// { HUB_CHANNEL_SWITCH, ZERO } -> intr 8 -	iowr I[$r3 + 0x000] $r2 +	clear b32 $r2 +	nv_iowr(NV_PGRAPH_FECS_INTR_ROUTE, 0, $r2) + +	// route HUB_CHSW_PULSE to fuc interrupt 8 +	mov $r2 0x2003		// { HUB_CHSW_PULSE, ZERO } -> intr 8 +	nv_iowr(NV_PGRAPH_FECS_IROUTE, 0, $r2)  	// not sure what these are, route them because NVIDIA does, and  	// the IRQ handler will signal the host if we ever get one.. we  	// may find out if/why we need to handle these if so..  	// -	mov $r2 0x2004 -	iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9 -	mov $r2 0x200b -	iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10 -	mov $r2 0x200c -	iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15 +	mov $r2 0x2004		// { 0x04, ZERO } -> intr 9 +	nv_iowr(NV_PGRAPH_FECS_IROUTE, 1, $r2) +	mov $r2 0x200b		// { HUB_FIRMWARE_MTHD, ZERO } -> intr 10 +	nv_iowr(NV_PGRAPH_FECS_IROUTE, 2, $r2) +	mov $r2 0x200c		// { 0x0c, ZERO } -> intr 15 +	nv_iowr(NV_PGRAPH_FECS_IROUTE, 7, $r2)  	// enable all INTR_UP interrupts -	mov $r2 0xc24 -	shl b32 $r2 6 -	not b32 $r3 $r0 -	iowr I[$r2] $r3 +	sub b32 $r3 $r0 1 +	nv_iowr(NV_PGRAPH_FECS_INTR_UP_EN, 0, $r3) -	// enable fifo, ctxsw, 9, 10, 15 interrupts -	mov $r2 -0x78fc		// 0x8704 -	sethi $r2 0 -	iowr I[$r1 + 0x000] $r2	// INTR_EN_SET +	// enable fifo, ctxsw, 9, fwmthd, 15 interrupts +	imm32($r2, 0x8704) +	nv_iowr(NV_PGRAPH_FECS_INTR_EN_SET, 0, $r2)  	// fifo level triggered, rest edge -	sub b32 $r1 0x100 -	mov $r2 4 -	iowr I[$r1] $r2 +	mov $r2 NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL +	nv_iowr(NV_PGRAPH_FECS_INTR_MODE, 0, $r2)  	// enable interrupts  	bset $flags ie0  	// fetch enabled GPC/ROP counts -	mov $r14 -0x69fc	// 0x409604 -	sethi $r14 0x400000 -	call #nv_rd32 +	nv_rd32($r14, 0x409604)  	extr $r1 $r15 16:20  	st b32 D[$r0 + #rop_count] $r1  	and $r15 0x1f @@ -131,37 +128,40 @@ init:  	mov $r1 1  	shl b32 $r1 $r15  	sub b32 $r1 1 -	mov $r2 0x40c -	shl b32 $r2 6 -	iowr I[$r2 + 0x000] $r1 -	iowr I[$r2 + 0x100] $r1 +	nv_iowr(NV_PGRAPH_FECS_BAR_MASK0, 0, $r1) +	nv_iowr(NV_PGRAPH_FECS_BAR_MASK1, 0, $r1)  	// context size calculation, reserve first 256 bytes for use by fuc  	mov $r1 256 +	// +	mov $r15 2 +	call(ctx_4170s) +	call(ctx_4170w) +	mov $r15 0x10 +	call(ctx_86c) +  	// calculate size of mmio context data  	ld b32 $r14 D[$r0 + #hub_mmio_list_head]  	ld b32 $r15 D[$r0 + #hub_mmio_list_tail] -	call #mmctx_size +	call(mmctx_size)  	// set mmctx base addresses now so we don't have to do it later,  	// they don't (currently) ever change -	mov $r3 0x700 -	shl b32 $r3 6  	shr b32 $r4 $r1 8 -	iowr I[$r3 + 0x000] $r4		// MMCTX_SAVE_SWBASE -	iowr I[$r3 + 0x100] $r4		// MMCTX_LOAD_SWBASE +	nv_iowr(NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE, 0, $r4) +	nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE, 0, $r4)  	add b32 $r3 0x1300  	add b32 $r1 $r15  	shr b32 $r15 2 -	iowr I[$r3 + 0x000] $r15	// MMCTX_LOAD_COUNT, wtf for?!? +	nv_iowr(NV_PGRAPH_FECS_MMCTX_LOAD_COUNT, 0, $r15) // wtf??  	// strands, base offset needs to be aligned to 256 bytes  	shr b32 $r1 8  	add b32 $r1 1  	shl b32 $r1 8  	mov b32 $r15 $r1 -	call #strand_ctx_init +	call(strand_ctx_init)  	add b32 $r1 $r15  	// initialise each GPC in sequence by passing in the offset of its @@ -173,30 +173,29 @@ init:  	// in GPCn_CC_SCRATCH[1]  	//  	ld b32 $r3 D[$r0 + #gpc_count] -	mov $r4 0x2000 -	sethi $r4 0x500000 +	imm32($r4, 0x502000)  	init_gpc:  		// setup, and start GPC ucode running  		add b32 $r14 $r4 0x804  		mov b32 $r15 $r1 -		call #nv_wr32			// CC_SCRATCH[1] = ctx offset +		call(nv_wr32)			// CC_SCRATCH[1] = ctx offset  		add b32 $r14 $r4 0x10c  		clear b32 $r15 -		call #nv_wr32 +		call(nv_wr32)  		add b32 $r14 $r4 0x104 -		call #nv_wr32			// ENTRY +		call(nv_wr32)			// ENTRY  		add b32 $r14 $r4 0x100  		mov $r15 2			// CTRL_START_TRIGGER -		call #nv_wr32			// CTRL +		call(nv_wr32)			// CTRL  		// wait for it to complete, and adjust context size  		add b32 $r14 $r4 0x800  		init_gpc_wait: -			call #nv_rd32 +			call(nv_rd32)  			xbit $r15 $r15 31  			bra e #init_gpc_wait  		add b32 $r14 $r4 0x804 -		call #nv_rd32 +		call(nv_rd32)  		add b32 $r1 $r15  		// next! @@ -204,6 +203,12 @@ init:  		sub b32 $r3 1  		bra ne #init_gpc +	// +	mov $r15 0 +	call(ctx_86c) +	mov $r15 0 +	call(ctx_4170s) +  	// save context size, and tell host we're ready  	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(1), 0, $r1)  	clear b32 $r1 @@ -218,17 +223,15 @@ main:  	bset $flags $p0  	sleep $p0  	mov $r13 #cmd_queue -	call #queue_get +	call(queue_get)  	bra $p1 #main  	// context switch, requested by GPU?  	cmpu b32 $r14 0x4001  	bra ne #main_not_ctx_switch  		trace_set(T_AUTO) -		mov $r1 0xb00 -		shl b32 $r1 6 -		iord $r2 I[$r1 + 0x100]		// CHAN_NEXT -		iord $r1 I[$r1 + 0x000]		// CHAN_CUR +		nv_iord($r1, NV_PGRAPH_FECS_CHAN_ADDR, 0) +		nv_iord($r2, NV_PGRAPH_FECS_CHAN_NEXT, 0)  		xbit $r3 $r1 31  		bra e #chsw_no_prev @@ -239,12 +242,12 @@ main:  				trace_set(T_SAVE)  				bclr $flags $p1  				bset $flags $p2 -				call #ctx_xfer +				call(ctx_xfer)  				trace_clr(T_SAVE);  				pop $r2  				trace_set(T_LOAD);  				bset $flags $p1 -				call #ctx_xfer +				call(ctx_xfer)  				trace_clr(T_LOAD);  				bra #chsw_done  			chsw_prev_no_next: @@ -252,25 +255,21 @@ main:  				mov b32 $r2 $r1  				bclr $flags $p1  				bclr $flags $p2 -				call #ctx_xfer +				call(ctx_xfer)  				pop $r2 -				mov $r1 0xb00 -				shl b32 $r1 6 -				iowr I[$r1] $r2 +				nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)  				bra #chsw_done  		chsw_no_prev:  			xbit $r3 $r2 31  			bra e #chsw_done  				bset $flags $p1  				bclr $flags $p2 -				call #ctx_xfer +				call(ctx_xfer)  		// ack the context switch request  		chsw_done: -		mov $r1 0xb0c -		shl b32 $r1 6 -		mov $r2 1 -		iowr I[$r1 + 0x000] $r2		// 0x409b0c +		mov $r2 NV_PGRAPH_FECS_CHSW_ACK +		nv_iowr(NV_PGRAPH_FECS_CHSW, 0, $r2)  		trace_clr(T_AUTO)  		bra #main @@ -279,7 +278,7 @@ main:  	cmpu b32 $r14 0x0001  	bra ne #main_not_ctx_chan  		mov b32 $r2 $r15 -		call #ctx_chan +		call(ctx_chan)  		bra #main_done  	// request to store current channel context? @@ -289,14 +288,14 @@ main:  		trace_set(T_SAVE)  		bclr $flags $p1  		bclr $flags $p2 -		call #ctx_xfer +		call(ctx_xfer)  		trace_clr(T_SAVE)  		bra #main_done  	main_not_ctx_save:  		shl b32 $r15 $r14 16  		or $r15 E_BAD_COMMAND -		call #error +		call(error)  		bra #main  	main_done: @@ -319,41 +318,58 @@ ih:  	clear b32 $r0  	// incoming fifo command? -	iord $r10 I[$r0 + 0x200]	// INTR -	and $r11 $r10 0x00000004 +	nv_iord($r10, NV_PGRAPH_FECS_INTR, 0) +	and $r11 $r10 NV_PGRAPH_FECS_INTR_FIFO  	bra e #ih_no_fifo  		// queue incoming fifo command for later processing -		mov $r11 0x1900  		mov $r13 #cmd_queue -		iord $r14 I[$r11 + 0x100]	// FIFO_CMD -		iord $r15 I[$r11 + 0x000]	// FIFO_DATA -		call #queue_put +		nv_iord($r14, NV_PGRAPH_FECS_FIFO_CMD, 0) +		nv_iord($r15, NV_PGRAPH_FECS_FIFO_DATA, 0) +		call(queue_put)  		add b32 $r11 0x400  		mov $r14 1 -		iowr I[$r11 + 0x000] $r14	// FIFO_ACK +		nv_iowr(NV_PGRAPH_FECS_FIFO_ACK, 0, $r14)  	// context switch request?  	ih_no_fifo: -	and $r11 $r10 0x00000100 +	and $r11 $r10 NV_PGRAPH_FECS_INTR_CHSW  	bra e #ih_no_ctxsw  		// enqueue a context switch for later processing  		mov $r13 #cmd_queue  		mov $r14 0x4001 -		call #queue_put +		call(queue_put) -	// anything we didn't handle, bring it to the host's attention +	// firmware method?  	ih_no_ctxsw: -	mov $r11 0x104 +	and $r11 $r10 NV_PGRAPH_FECS_INTR_FWMTHD +	bra e #ih_no_fwmthd +		// none we handle; report to host and ack +		nv_rd32($r15, NV_PGRAPH_TRAPPED_DATA_LO) +		nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(4), 0, $r15) +		nv_rd32($r15, NV_PGRAPH_TRAPPED_ADDR) +		nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(3), 0, $r15) +		extr $r14 $r15 16:18 +		shl b32 $r14 $r14 2 +		imm32($r15, NV_PGRAPH_FE_OBJECT_TABLE(0)) +		add b32 $r14 $r15 +		call(nv_rd32) +		nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_VAL(2), 0, $r15) +		mov $r15 E_BAD_FWMTHD +		call(error) +		mov $r11 0x100 +		nv_wr32(0x400144, $r11) + +	// anything we didn't handle, bring it to the host's attention +	ih_no_fwmthd: +	mov $r11 0x504 // FIFO | CHSW | FWMTHD  	not b32 $r11  	and $r11 $r10 $r11  	bra e #ih_no_other -		mov $r10 0xc1c -		shl b32 $r10 6 -		iowr I[$r10] $r11	// INTR_UP_SET +		nv_iowr(NV_PGRAPH_FECS_INTR_UP_SET, 0, $r11)  	// ack, and wake up main()  	ih_no_other: -	iowr I[$r0 + 0x100] $r10	// INTR_ACK +	nv_iowr(NV_PGRAPH_FECS_INTR_ACK, 0, $r10)  	pop $r15  	pop $r14 @@ -370,12 +386,10 @@ ih:  #if CHIPSET < GK100  // Not real sure, but, MEM_CMD 7 will hang forever if this isn't done  ctx_4160s: -	mov $r14 0x4160 -	sethi $r14 0x400000  	mov $r15 1 -	call #nv_wr32 +	nv_wr32(0x404160, $r15)  	ctx_4160s_wait: -		call #nv_rd32 +		nv_rd32($r15, 0x404160)  		xbit $r15 $r15 4  		bra e #ctx_4160s_wait  	ret @@ -384,10 +398,8 @@ ctx_4160s:  // to hang with STATUS=0x00000007 until it's cleared.. fbcon can  // still function with it set however...  ctx_4160c: -	mov $r14 0x4160 -	sethi $r14 0x400000  	clear b32 $r15 -	call #nv_wr32 +	nv_wr32(0x404160, $r15)  	ret  #endif @@ -396,18 +408,14 @@ ctx_4160c:  // In: $r15 value to set 0x404170 to  //  ctx_4170s: -	mov $r14 0x4170 -	sethi $r14 0x400000  	or $r15 0x10 -	call #nv_wr32 +	nv_wr32(0x404170, $r15)  	ret  // Waits for a ctx_4170s() call to complete  //  ctx_4170w: -	mov $r14 0x4170 -	sethi $r14 0x400000 -	call #nv_rd32 +	nv_rd32($r15, 0x404170)  	and $r15 0x10  	bra ne #ctx_4170w  	ret @@ -419,16 +427,18 @@ ctx_4170w:  // funny things happen.  //  ctx_redswitch: -	mov $r14 0x614 -	shl b32 $r14 6 -	mov $r15 0x270 -	iowr I[$r14] $r15	// HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL +	mov $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC +	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP +	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC +	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN +	nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)  	mov $r15 8  	ctx_redswitch_delay:  		sub b32 $r15 1  		bra ne #ctx_redswitch_delay -	mov $r15 0x770 -	iowr I[$r14] $r15	// HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL +	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP +	or  $r14 NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN +	nv_iowr(NV_PGRAPH_FECS_RED_SWITCH, 0, $r14)  	ret  // Not a clue what this is for, except that unless the value is 0x10, the @@ -437,15 +447,18 @@ ctx_redswitch:  // In: $r15 value to set to (0x00/0x10 are used)  //  ctx_86c: -	mov $r14 0x86c -	shl b32 $r14 6 -	iowr I[$r14] $r15	// HUB(0x86c) = val -	mov $r14 -0x75ec -	sethi $r14 0x400000 -	call #nv_wr32		// ROP(0xa14) = val -	mov $r14 -0x5794 -	sethi $r14 0x410000 -	call #nv_wr32		// GPC(0x86c) = val +	nv_iowr(NV_PGRAPH_FECS_UNK86C, 0, $r15) +	nv_wr32(0x408a14, $r15) +	nv_wr32(NV_PGRAPH_GPCX_GPCCS_UNK86C, $r15) +	ret + +// In: $r15 NV_PGRAPH_FECS_MEM_CMD_* +ctx_mem: +	nv_iowr(NV_PGRAPH_FECS_MEM_CMD, 0, $r15) +	ctx_mem_wait: +		nv_iord($r15, NV_PGRAPH_FECS_MEM_CMD, 0) +		or $r15 $r15 +		bra ne #ctx_mem_wait  	ret  // ctx_load - load's a channel's ctxctl data, and selects its vm @@ -457,23 +470,14 @@ ctx_load:  	// switch to channel, somewhat magic in parts..  	mov $r10 12		// DONE_UNK12 -	call #wait_donez -	mov $r1 0xa24 -	shl b32 $r1 6 -	iowr I[$r1 + 0x000] $r0	// 0x409a24 -	mov $r3 0xb00 -	shl b32 $r3 6 -	iowr I[$r3 + 0x100] $r2	// CHAN_NEXT -	mov $r1 0xa0c -	shl b32 $r1 6 -	mov $r4 7 -	iowr I[$r1 + 0x000] $r2 // MEM_CHAN -	iowr I[$r1 + 0x100] $r4	// MEM_CMD -	ctx_chan_wait_0: -		iord $r4 I[$r1 + 0x100] -		and $r4 0x1f -		bra ne #ctx_chan_wait_0 -	iowr I[$r3 + 0x000] $r2	// CHAN_CUR +	call(wait_donez) +	clear b32 $r15 +	nv_iowr(0x409a24, 0, $r15) +	nv_iowr(NV_PGRAPH_FECS_CHAN_NEXT, 0, $r2) +	nv_iowr(NV_PGRAPH_FECS_MEM_CHAN, 0, $r2) +	mov $r15 NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN +	call(ctx_mem) +	nv_iowr(NV_PGRAPH_FECS_CHAN_ADDR, 0, $r2)  	// load channel header, fetch PGRAPH context pointer  	mov $xtargets $r0 @@ -482,14 +486,10 @@ ctx_load:  	add b32 $r2 2  	trace_set(T_LCHAN) -	mov $r1 0xa04 -	shl b32 $r1 6 -	iowr I[$r1 + 0x000] $r2		// MEM_BASE -	mov $r1 0xa20 -	shl b32 $r1 6 -	mov $r2 0x0002 -	sethi $r2 0x80000000 -	iowr I[$r1 + 0x000] $r2		// MEM_TARGET = vram +	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r2) +	imm32($r2, NV_PGRAPH_FECS_MEM_TARGET_UNK31) +	or  $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM +	nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)  	mov $r1 0x10			// chan + 0x0210  	mov $r2 #xfer_data  	sethi $r2 0x00020000		// 16 bytes @@ -507,13 +507,9 @@ ctx_load:  	// set transfer base to start of context, and fetch context header  	trace_set(T_LCTXH) -	mov $r2 0xa04 -	shl b32 $r2 6 -	iowr I[$r2 + 0x000] $r1		// MEM_BASE -	mov $r2 1 -	mov $r1 0xa20 -	shl b32 $r1 6 -	iowr I[$r1 + 0x000] $r2		// MEM_TARGET = vm +	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r1) +	mov $r2 NV_PGRAPH_FECS_MEM_TARGET_AS_VM +	nv_iowr(NV_PGRAPH_FECS_MEM_TARGET, 0, $r2)  	mov $r1 #chan_data  	sethi $r1 0x00060000		// 256 bytes  	xdld $r0 $r1 @@ -532,21 +528,15 @@ ctx_load:  //  ctx_chan:  #if CHIPSET < GK100 -	call #ctx_4160s +	call(ctx_4160s)  #endif -	call #ctx_load +	call(ctx_load)  	mov $r10 12			// DONE_UNK12 -	call #wait_donez -	mov $r1 0xa10 -	shl b32 $r1 6 -	mov $r2 5 -	iowr I[$r1 + 0x000] $r2		// MEM_CMD = 5 (???) -	ctx_chan_wait: -		iord $r2 I[$r1 + 0x000] -		or $r2 $r2 -		bra ne #ctx_chan_wait +	call(wait_donez) +	mov $r15 5 // MEM_CMD 5 ??? +	call(ctx_mem)  #if CHIPSET < GK100 -	call #ctx_4160c +	call(ctx_4160c)  #endif  	ret @@ -562,9 +552,7 @@ ctx_chan:  ctx_mmio_exec:  	// set transfer base to be the mmio list  	ld b32 $r3 D[$r0 + #chan_mmio_address] -	mov $r2 0xa04 -	shl b32 $r2 6 -	iowr I[$r2 + 0x000] $r3		// MEM_BASE +	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)  	clear b32 $r3  	ctx_mmio_loop: @@ -580,7 +568,7 @@ ctx_mmio_exec:  		ctx_mmio_pull:  		ld b32 $r14 D[$r4 + #xfer_data + 0x00]  		ld b32 $r15 D[$r4 + #xfer_data + 0x04] -		call #nv_wr32 +		call(nv_wr32)  		// next!  		add b32 $r3 8 @@ -590,7 +578,7 @@ ctx_mmio_exec:  	// set transfer base back to the current context  	ctx_mmio_done:  	ld b32 $r3 D[$r0 + #ctx_current] -	iowr I[$r2 + 0x000] $r3		// MEM_BASE +	nv_iowr(NV_PGRAPH_FECS_MEM_BASE, 0, $r3)  	// disable the mmio list now, we don't need/want to execute it again  	st b32 D[$r0 + #chan_mmio_count] $r0 @@ -610,12 +598,10 @@ ctx_mmio_exec:  //  ctx_xfer:  	// according to mwk, some kind of wait for idle -	mov $r15 0xc00 -	shl b32 $r15 6  	mov $r14 4 -	iowr I[$r15 + 0x200] $r14 +	nv_iowr(0x409c08, 0, $r14)  	ctx_xfer_idle: -		iord $r14 I[$r15 + 0x000] +		nv_iord($r14, 0x409c00, 0)  		and $r14 0x2000  		bra ne #ctx_xfer_idle @@ -623,50 +609,42 @@ ctx_xfer:  	bra $p2 #ctx_xfer_pre_load  	ctx_xfer_pre:  		mov $r15 0x10 -		call #ctx_86c +		call(ctx_86c)  #if CHIPSET < GK100 -		call #ctx_4160s +		call(ctx_4160s)  #endif  		bra not $p1 #ctx_xfer_exec  	ctx_xfer_pre_load:  		mov $r15 2 -		call #ctx_4170s -		call #ctx_4170w -		call #ctx_redswitch +		call(ctx_4170s) +		call(ctx_4170w) +		call(ctx_redswitch)  		clear b32 $r15 -		call #ctx_4170s -		call #ctx_load +		call(ctx_4170s) +		call(ctx_load)  	// fetch context pointer, and initiate xfer on all GPCs  	ctx_xfer_exec:  	ld b32 $r1 D[$r0 + #ctx_current] -	mov $r2 0x414 -	shl b32 $r2 6 -	iowr I[$r2 + 0x000] $r0	// BAR_STATUS = reset -	mov $r14 -0x5b00 -	sethi $r14 0x410000 -	mov b32 $r15 $r1 -	call #nv_wr32		// GPC_BCAST_WRCMD_DATA = ctx pointer -	add b32 $r14 4 + +	clear b32 $r2 +	nv_iowr(NV_PGRAPH_FECS_BAR, 0, $r2) + +	nv_wr32(0x41a500, $r1)	// GPC_BCAST_WRCMD_DATA = ctx pointer  	xbit $r15 $flags $p1  	xbit $r2 $flags $p2  	shl b32 $r2 1  	or $r15 $r2 -	call #nv_wr32		// GPC_BCAST_WRCMD_CMD = GPC_XFER(type) +	nv_wr32(0x41a504, $r15)	// GPC_BCAST_WRCMD_CMD = GPC_XFER(type)  	// strands -	mov $r1 0x4afc -	sethi $r1 0x20000 -	mov $r2 0xc -	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x0c -	call #strand_wait -	mov $r2 0x47fc -	sethi $r2 0x20000 -	iowr I[$r2] $r0		// STRAND_FIRST_GENE(0x3f) = 0x00 -	xbit $r2 $flags $p1 -	add b32 $r2 3 -	iowr I[$r1] $r2		// STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) +	call(strand_pre) +	clear b32 $r2 +	nv_iowr(NV_PGRAPH_FECS_STRAND_SELECT, 0x3f, $r2) +	xbit $r2 $flags $p1	// SAVE/LOAD +	add b32 $r2 NV_PGRAPH_FECS_STRAND_CMD_SAVE +	nv_iowr(NV_PGRAPH_FECS_STRAND_CMD, 0x3f, $r2)  	// mmio context  	xbit $r10 $flags $p1	// direction @@ -675,48 +653,42 @@ ctx_xfer:  	ld b32 $r12 D[$r0 + #hub_mmio_list_head]  	ld b32 $r13 D[$r0 + #hub_mmio_list_tail]  	mov $r14 0		// not multi -	call #mmctx_xfer +	call(mmctx_xfer)  	// wait for GPCs to all complete  	mov $r10 8		// DONE_BAR -	call #wait_doneo +	call(wait_doneo)  	// wait for strand xfer to complete -	call #strand_wait +	call(strand_wait)  	// post-op  	bra $p1 #ctx_xfer_post  		mov $r10 12		// DONE_UNK12 -		call #wait_donez -		mov $r1 0xa10 -		shl b32 $r1 6 -		mov $r2 5 -		iowr I[$r1] $r2		// MEM_CMD -		ctx_xfer_post_save_wait: -			iord $r2 I[$r1] -			or $r2 $r2 -			bra ne #ctx_xfer_post_save_wait +		call(wait_donez) +		mov $r15 5 // MEM_CMD 5 ??? +		call(ctx_mem)  	bra $p2 #ctx_xfer_done  	ctx_xfer_post:  		mov $r15 2 -		call #ctx_4170s +		call(ctx_4170s)  		clear b32 $r15 -		call #ctx_86c -		call #strand_post -		call #ctx_4170w +		call(ctx_86c) +		call(strand_post) +		call(ctx_4170w)  		clear b32 $r15 -		call #ctx_4170s +		call(ctx_4170s)  		bra not $p1 #ctx_xfer_no_post_mmio  		ld b32 $r1 D[$r0 + #chan_mmio_count]  		or $r1 $r1  		bra e #ctx_xfer_no_post_mmio -			call #ctx_mmio_exec +			call(ctx_mmio_exec)  		ctx_xfer_no_post_mmio:  #if CHIPSET < GK100 -		call #ctx_4160c +		call(ctx_4160c)  #endif  	ctx_xfer_done: diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5 new file mode 100644 index 00000000000..27591b3086a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5 @@ -0,0 +1,40 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#define CHIPSET GK208 +#include "macros.fuc" + +.section #gm107_grhub_data +#define INCLUDE_DATA +#include "com.fuc" +#include "hub.fuc" +#undef INCLUDE_DATA + +.section #gm107_grhub_code +#define INCLUDE_CODE +bra #init +#include "com.fuc" +#include "hub.fuc" +.align 256 +#undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h new file mode 100644 index 00000000000..5f953c5c20b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubgm107.fuc5.h @@ -0,0 +1,916 @@ +uint32_t gm107_grhub_data[] = { +/* 0x0000: hub_mmio_list_head */ +	0x00000300, +/* 0x0004: hub_mmio_list_tail */ +	0x00000304, +/* 0x0008: gpc_count */ +	0x00000000, +/* 0x000c: rop_count */ +	0x00000000, +/* 0x0010: cmd_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0058: ctx_current */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0100: chan_data */ +/* 0x0100: chan_mmio_count */ +	0x00000000, +/* 0x0104: chan_mmio_address */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0200: xfer_data */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0300: hub_mmio_list_base */ +	0x0417e91c, +}; + +uint32_t gm107_grhub_code[] = { +	0x030e0ef5, +/* 0x0004: queue_put */ +	0x9800d898, +	0x86f001d9, +	0xf489a408, +	0x020f0b1b, +	0x0002f87e, +/* 0x001a: queue_put_next */ +	0x98c400f8, +	0x0384b607, +	0xb6008dbb, +	0x8eb50880, +	0x018fb500, +	0xf00190b6, +	0xd9b50f94, +/* 0x0037: queue_get */ +	0xf400f801, +	0xd8980131, +	0x01d99800, +	0x0bf489a4, +	0x0789c421, +	0xbb0394b6, +	0x90b6009d, +	0x009e9808, +	0xb6019f98, +	0x84f00180, +	0x00d8b50f, +/* 0x0063: queue_get_done */ +	0xf80132f4, +/* 0x0065: nv_rd32 */ +	0xf0ecb200, +	0x00801fc9, +	0x0cf601ca, +/* 0x0073: nv_rd32_wait */ +	0x8c04bd00, +	0xcf01ca00, +	0xccc800cc, +	0xf61bf41f, +	0xec7e060a, +	0x008f0000, +	0xffcf01cb, +/* 0x008f: nv_wr32 */ +	0x8000f800, +	0xf601cc00, +	0x04bd000f, +	0xc9f0ecb2, +	0x1ec9f01f, +	0x01ca0080, +	0xbd000cf6, +/* 0x00a9: nv_wr32_wait */ +	0xca008c04, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f61b, +/* 0x00b8: wait_donez */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x00cf: wait_donez_ne */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf61bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x00ec: wait_doneo */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x0103: wait_doneo_e */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf60bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x0120: mmctx_size */ +/* 0x0122: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0x1bf4efa4, +	0xf89fb2ec, +/* 0x013d: mmctx_xfer */ +	0xf094bd00, +	0x00800199, +	0x09f60237, +	0xbd04bd00, +	0x05bbfd94, +	0x800f0bf4, +	0xf601c400, +	0x04bd000b, +/* 0x015f: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0xc6008018, +	0x000ef601, +	0x008004bd, +	0x0ff601c7, +	0xf004bd00, +/* 0x017a: mmctx_multi_disabled */ +	0xabc80199, +	0x10b4b600, +	0xc80cb9f0, +	0xe4b601ae, +	0x05befd11, +	0x01c50080, +	0xbd000bf6, +/* 0x0195: mmctx_exec_loop */ +/* 0x0195: mmctx_wait_free */ +	0xc5008e04, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f60b, +	0x05e9fd00, +	0x01c80080, +	0xbd000ef6, +	0x04c0b604, +	0x1bf4cda4, +	0x02abc8df, +/* 0x01bf: mmctx_fini_wait */ +	0x8b1c1bf4, +	0xcf01c500, +	0xb4f000bb, +	0x10b4b01f, +	0x0af31bf4, +	0x00b87e05, +	0x250ef400, +/* 0x01d8: mmctx_stop */ +	0xb600abc8, +	0xb9f010b4, +	0x12b9f00c, +	0x01c50080, +	0xbd000bf6, +/* 0x01ed: mmctx_stop_wait */ +	0xc5008b04, +	0x00bbcf01, +	0xf412bbc8, +/* 0x01fa: mmctx_done */ +	0x94bdf61b, +	0x800199f0, +	0xf6021700, +	0x04bd0009, +/* 0x020a: strand_wait */ +	0xa0f900f8, +	0xb87e020a, +	0xa0fc0000, +/* 0x0216: strand_pre */ +	0x0c0900f8, +	0x024afc80, +	0xbd0009f6, +	0x020a7e04, +/* 0x0227: strand_post */ +	0x0900f800, +	0x4afc800d, +	0x0009f602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0238: strand_set */ +	0xfc800f0c, +	0x0cf6024f, +	0x0c04bd00, +	0x4afc800b, +	0x000cf602, +	0xfc8004bd, +	0x0ef6024f, +	0x0c04bd00, +	0x4afc800a, +	0x000cf602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0268: strand_ctx_init */ +	0x99f094bd, +	0x37008003, +	0x0009f602, +	0x167e04bd, +	0x030e0002, +	0x0002387e, +	0xfc80c4bd, +	0x0cf60247, +	0x0c04bd00, +	0x4afc8001, +	0x000cf602, +	0x0a7e04bd, +	0x0c920002, +	0x46fc8001, +	0x000cf602, +	0x020c04bd, +	0x024afc80, +	0xbd000cf6, +	0x020a7e04, +	0x02277e00, +	0x42008800, +	0x20008902, +	0x0099cf02, +/* 0x02c7: ctx_init_strand_loop */ +	0xf608fe95, +	0x8ef6008e, +	0x808acf40, +	0xb606a5b6, +	0xeabb01a0, +	0x0480b600, +	0xf40192b6, +	0xe4b6e81b, +	0xf2efbc08, +	0x99f094bd, +	0x17008003, +	0x0009f602, +	0x00f804bd, +/* 0x02f8: error */ +	0x02050080, +	0xbd000ff6, +	0x80010f04, +	0xf6030700, +	0x04bd000f, +/* 0x030e: init */ +	0x04bd00f8, +	0x410007fe, +	0x11cf4200, +	0x0911e700, +	0x0814b601, +	0x020014fe, +	0x12004002, +	0xbd0002f6, +	0x05c94104, +	0xbd0010fe, +	0x07004024, +	0xbd0002f6, +	0x20034204, +	0x01010080, +	0xbd0002f6, +	0x20044204, +	0x01010480, +	0xbd0002f6, +	0x200b4204, +	0x01010880, +	0xbd0002f6, +	0x200c4204, +	0x01011c80, +	0xbd0002f6, +	0x01039204, +	0x03090080, +	0xbd0003f6, +	0x87044204, +	0xf6040040, +	0x04bd0002, +	0x00400402, +	0x0002f603, +	0x31f404bd, +	0x96048e10, +	0x00657e40, +	0xc7feb200, +	0x01b590f1, +	0x1ff4f003, +	0x01020fb5, +	0x041fbb01, +	0x800112b6, +	0xf6010300, +	0x04bd0001, +	0x01040080, +	0xbd0001f6, +	0x01004104, +	0xa87e020f, +	0xb77e0006, +	0x100f0006, +	0x0006f97e, +	0x98000e98, +	0x207e010f, +	0x14950001, +	0xc0008008, +	0x0004f601, +	0x008004bd, +	0x04f601c1, +	0xb704bd00, +	0xbb130030, +	0xf5b6001f, +	0xd3008002, +	0x000ff601, +	0x15b604bd, +	0x0110b608, +	0xb20814b6, +	0x02687e1f, +	0x001fbb00, +	0x84020398, +/* 0x041f: init_gpc */ +	0xb8502000, +	0x0008044e, +	0x8f7e1fb2, +	0x4eb80000, +	0xbd00010c, +	0x008f7ef4, +	0x044eb800, +	0x8f7e0001, +	0x4eb80000, +	0x0f000100, +	0x008f7e02, +	0x004eb800, +/* 0x044e: init_gpc_wait */ +	0x657e0008, +	0xffc80000, +	0xf90bf41f, +	0x08044eb8, +	0x00657e00, +	0x001fbb00, +	0x800040b7, +	0xf40132b6, +	0x000fb41b, +	0x0006f97e, +	0xa87e000f, +	0x00800006, +	0x01f60201, +	0xbd04bd00, +	0x1f19f014, +	0x02300080, +	0xbd0001f6, +/* 0x0491: main */ +	0x0031f404, +	0x0d0028f4, +	0x00377e10, +	0xf401f400, +	0x4001e4b1, +	0x00c71bf5, +	0x99f094bd, +	0x37008004, +	0x0009f602, +	0x008104bd, +	0x11cf02c0, +	0xc1008200, +	0x0022cf02, +	0xf41f13c8, +	0x23c8770b, +	0x550bf41f, +	0x12b220f9, +	0x99f094bd, +	0x37008007, +	0x0009f602, +	0x32f404bd, +	0x0231f401, +	0x00087c7e, +	0x99f094bd, +	0x17008007, +	0x0009f602, +	0x20fc04bd, +	0x99f094bd, +	0x37008006, +	0x0009f602, +	0x31f404bd, +	0x087c7e01, +	0xf094bd00, +	0x00800699, +	0x09f60217, +	0xf404bd00, +/* 0x0522: chsw_prev_no_next */ +	0x20f92f0e, +	0x32f412b2, +	0x0232f401, +	0x00087c7e, +	0x008020fc, +	0x02f602c0, +	0xf404bd00, +/* 0x053e: chsw_no_prev */ +	0x23c8130e, +	0x0d0bf41f, +	0xf40131f4, +	0x7c7e0232, +/* 0x054e: chsw_done */ +	0x01020008, +	0x02c30080, +	0xbd0002f6, +	0xf094bd04, +	0x00800499, +	0x09f60217, +	0xf504bd00, +/* 0x056b: main_not_ctx_switch */ +	0xb0ff2a0e, +	0x1bf401e4, +	0x7ef2b20c, +	0xf400081c, +/* 0x057a: main_not_ctx_chan */ +	0xe4b0400e, +	0x2c1bf402, +	0x99f094bd, +	0x37008007, +	0x0009f602, +	0x32f404bd, +	0x0232f401, +	0x00087c7e, +	0x99f094bd, +	0x17008007, +	0x0009f602, +	0x0ef404bd, +/* 0x05a9: main_not_ctx_save */ +	0x10ef9411, +	0x7e01f5f0, +	0xf50002f8, +/* 0x05b7: main_done */ +	0xbdfede0e, +	0x1f29f024, +	0x02300080, +	0xbd0002f6, +	0xcc0ef504, +/* 0x05c9: ih */ +	0xfe80f9fe, +	0x80f90188, +	0xa0f990f9, +	0xd0f9b0f9, +	0xf0f9e0f9, +	0x004a04bd, +	0x00aacf02, +	0xf404abc4, +	0x100d230b, +	0xcf1a004e, +	0x004f00ee, +	0x00ffcf19, +	0x0000047e, +	0x0400b0b7, +	0x0040010e, +	0x000ef61d, +/* 0x060a: ih_no_fifo */ +	0xabe404bd, +	0x0bf40100, +	0x4e100d0c, +	0x047e4001, +/* 0x061a: ih_no_ctxsw */ +	0xabe40000, +	0x0bf40400, +	0x07088e56, +	0x00657e40, +	0x80ffb200, +	0xf6020400, +	0x04bd000f, +	0x4007048e, +	0x0000657e, +	0x0080ffb2, +	0x0ff60203, +	0xc704bd00, +	0xee9450fe, +	0x07008f02, +	0x00efbb40, +	0x0000657e, +	0x02020080, +	0xbd000ff6, +	0x7e030f04, +	0x4b0002f8, +	0xbfb20100, +	0x4001448e, +	0x00008f7e, +/* 0x0674: ih_no_fwmthd */ +	0xbd05044b, +	0xb4abffb0, +	0x800c0bf4, +	0xf6030700, +	0x04bd000b, +/* 0x0688: ih_no_other */ +	0xf6010040, +	0x04bd000a, +	0xe0fcf0fc, +	0xb0fcd0fc, +	0x90fca0fc, +	0x88fe80fc, +	0xf480fc00, +	0x01f80032, +/* 0x06a8: ctx_4170s */ +	0xb210f5f0, +	0x41708eff, +	0x008f7e40, +/* 0x06b7: ctx_4170w */ +	0x8e00f800, +	0x7e404170, +	0xb2000065, +	0x10f4f0ff, +	0xf8f31bf4, +/* 0x06c9: ctx_redswitch */ +	0x02004e00, +	0xf040e5f0, +	0xe5f020e5, +	0x85008010, +	0x000ef601, +	0x080f04bd, +/* 0x06e0: ctx_redswitch_delay */ +	0xf401f2b6, +	0xe5f1fd1b, +	0xe5f10400, +	0x00800100, +	0x0ef60185, +	0xf804bd00, +/* 0x06f9: ctx_86c */ +	0x23008000, +	0x000ff602, +	0xffb204bd, +	0x408a148e, +	0x00008f7e, +	0x8c8effb2, +	0x8f7e41a8, +	0x00f80000, +/* 0x0718: ctx_mem */ +	0x02840080, +	0xbd000ff6, +/* 0x0721: ctx_mem_wait */ +	0x84008f04, +	0x00ffcf02, +	0xf405fffd, +	0x00f8f61b, +/* 0x0730: ctx_load */ +	0x99f094bd, +	0x37008005, +	0x0009f602, +	0x0c0a04bd, +	0x0000b87e, +	0x0080f4bd, +	0x0ff60289, +	0x8004bd00, +	0xf602c100, +	0x04bd0002, +	0x02830080, +	0xbd0002f6, +	0x7e070f04, +	0x80000718, +	0xf602c000, +	0x04bd0002, +	0xf0000bfe, +	0x24b61f2a, +	0x0220b604, +	0x99f094bd, +	0x37008008, +	0x0009f602, +	0x008004bd, +	0x02f60281, +	0xd204bd00, +	0x80000000, +	0x800225f0, +	0xf6028800, +	0x04bd0002, +	0x00421001, +	0x0223f002, +	0xf80512fa, +	0xf094bd03, +	0x00800899, +	0x09f60217, +	0x9804bd00, +	0x14b68101, +	0x80029818, +	0xfd0825b6, +	0x01b50512, +	0xf094bd16, +	0x00800999, +	0x09f60237, +	0x8004bd00, +	0xf6028100, +	0x04bd0001, +	0x00800102, +	0x02f60288, +	0x4104bd00, +	0x13f00100, +	0x0501fa06, +	0x94bd03f8, +	0x800999f0, +	0xf6021700, +	0x04bd0009, +	0x99f094bd, +	0x17008005, +	0x0009f602, +	0x00f804bd, +/* 0x081c: ctx_chan */ +	0x0007307e, +	0xb87e0c0a, +	0x050f0000, +	0x0007187e, +/* 0x082e: ctx_mmio_exec */ +	0x039800f8, +	0x81008041, +	0x0003f602, +	0x34bd04bd, +/* 0x083c: ctx_mmio_loop */ +	0xf4ff34c4, +	0x00450e1b, +	0x0653f002, +	0xf80535fa, +/* 0x084d: ctx_mmio_pull */ +	0x804e9803, +	0x7e814f98, +	0xb600008f, +	0x12b60830, +	0xdf1bf401, +/* 0x0860: ctx_mmio_done */ +	0x80160398, +	0xf6028100, +	0x04bd0003, +	0x414000b5, +	0x13f00100, +	0x0601fa06, +	0x00f803f8, +/* 0x087c: ctx_xfer */ +	0x0080040e, +	0x0ef60302, +/* 0x0887: ctx_xfer_idle */ +	0x8e04bd00, +	0xcf030000, +	0xe4f100ee, +	0x1bf42000, +	0x0611f4f5, +/* 0x089b: ctx_xfer_pre */ +	0x0f0c02f4, +	0x06f97e10, +	0x1b11f400, +/* 0x08a4: ctx_xfer_pre_load */ +	0xa87e020f, +	0xb77e0006, +	0xc97e0006, +	0xf4bd0006, +	0x0006a87e, +	0x0007307e, +/* 0x08bc: ctx_xfer_exec */ +	0xbd160198, +	0x05008024, +	0x0002f601, +	0x1fb204bd, +	0x41a5008e, +	0x00008f7e, +	0xf001fcf0, +	0x24b6022c, +	0x05f2fd01, +	0x048effb2, +	0x8f7e41a5, +	0x167e0000, +	0x24bd0002, +	0x0247fc80, +	0xbd0002f6, +	0x012cf004, +	0x800320b6, +	0xf6024afc, +	0x04bd0002, +	0xf001acf0, +	0x000b06a5, +	0x98000c98, +	0x000e010d, +	0x00013d7e, +	0xec7e080a, +	0x0a7e0000, +	0x01f40002, +	0x7e0c0a12, +	0x0f0000b8, +	0x07187e05, +	0x2d02f400, +/* 0x0938: ctx_xfer_post */ +	0xa87e020f, +	0xf4bd0006, +	0x0006f97e, +	0x0002277e, +	0x0006b77e, +	0xa87ef4bd, +	0x11f40006, +	0x40019810, +	0xf40511fd, +	0x2e7e070b, +/* 0x0962: ctx_xfer_no_post_mmio */ +/* 0x0962: ctx_xfer_done */ +	0x00f80008, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 new file mode 100644 index 00000000000..7c5d25630fa --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5 @@ -0,0 +1,40 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#define CHIPSET GK208 +#include "macros.fuc" + +.section #nv108_grhub_data +#define INCLUDE_DATA +#include "com.fuc" +#include "hub.fuc" +#undef INCLUDE_DATA + +.section #nv108_grhub_code +#define INCLUDE_CODE +bra #init +#include "com.fuc" +#include "hub.fuc" +.align 256 +#undef INCLUDE_CODE diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h new file mode 100644 index 00000000000..e49b5a877ae --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnv108.fuc5.h @@ -0,0 +1,916 @@ +uint32_t nv108_grhub_data[] = { +/* 0x0000: hub_mmio_list_head */ +	0x00000300, +/* 0x0004: hub_mmio_list_tail */ +	0x00000304, +/* 0x0008: gpc_count */ +	0x00000000, +/* 0x000c: rop_count */ +	0x00000000, +/* 0x0010: cmd_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0058: ctx_current */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0100: chan_data */ +/* 0x0100: chan_mmio_count */ +	0x00000000, +/* 0x0104: chan_mmio_address */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0200: xfer_data */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0300: hub_mmio_list_base */ +	0x0417e91c, +}; + +uint32_t nv108_grhub_code[] = { +	0x030e0ef5, +/* 0x0004: queue_put */ +	0x9800d898, +	0x86f001d9, +	0xf489a408, +	0x020f0b1b, +	0x0002f87e, +/* 0x001a: queue_put_next */ +	0x98c400f8, +	0x0384b607, +	0xb6008dbb, +	0x8eb50880, +	0x018fb500, +	0xf00190b6, +	0xd9b50f94, +/* 0x0037: queue_get */ +	0xf400f801, +	0xd8980131, +	0x01d99800, +	0x0bf489a4, +	0x0789c421, +	0xbb0394b6, +	0x90b6009d, +	0x009e9808, +	0xb6019f98, +	0x84f00180, +	0x00d8b50f, +/* 0x0063: queue_get_done */ +	0xf80132f4, +/* 0x0065: nv_rd32 */ +	0xf0ecb200, +	0x00801fc9, +	0x0cf601ca, +/* 0x0073: nv_rd32_wait */ +	0x8c04bd00, +	0xcf01ca00, +	0xccc800cc, +	0xf61bf41f, +	0xec7e060a, +	0x008f0000, +	0xffcf01cb, +/* 0x008f: nv_wr32 */ +	0x8000f800, +	0xf601cc00, +	0x04bd000f, +	0xc9f0ecb2, +	0x1ec9f01f, +	0x01ca0080, +	0xbd000cf6, +/* 0x00a9: nv_wr32_wait */ +	0xca008c04, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f61b, +/* 0x00b8: wait_donez */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x00cf: wait_donez_ne */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf61bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x00ec: wait_doneo */ +	0x99f094bd, +	0x37008000, +	0x0009f602, +	0x008004bd, +	0x0af60206, +/* 0x0103: wait_doneo_e */ +	0x8804bd00, +	0xcf010000, +	0x8aff0088, +	0xf60bf488, +	0x99f094bd, +	0x17008000, +	0x0009f602, +	0x00f804bd, +/* 0x0120: mmctx_size */ +/* 0x0122: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0x1bf4efa4, +	0xf89fb2ec, +/* 0x013d: mmctx_xfer */ +	0xf094bd00, +	0x00800199, +	0x09f60237, +	0xbd04bd00, +	0x05bbfd94, +	0x800f0bf4, +	0xf601c400, +	0x04bd000b, +/* 0x015f: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0xc6008018, +	0x000ef601, +	0x008004bd, +	0x0ff601c7, +	0xf004bd00, +/* 0x017a: mmctx_multi_disabled */ +	0xabc80199, +	0x10b4b600, +	0xc80cb9f0, +	0xe4b601ae, +	0x05befd11, +	0x01c50080, +	0xbd000bf6, +/* 0x0195: mmctx_exec_loop */ +/* 0x0195: mmctx_wait_free */ +	0xc5008e04, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f60b, +	0x05e9fd00, +	0x01c80080, +	0xbd000ef6, +	0x04c0b604, +	0x1bf4cda4, +	0x02abc8df, +/* 0x01bf: mmctx_fini_wait */ +	0x8b1c1bf4, +	0xcf01c500, +	0xb4f000bb, +	0x10b4b01f, +	0x0af31bf4, +	0x00b87e05, +	0x250ef400, +/* 0x01d8: mmctx_stop */ +	0xb600abc8, +	0xb9f010b4, +	0x12b9f00c, +	0x01c50080, +	0xbd000bf6, +/* 0x01ed: mmctx_stop_wait */ +	0xc5008b04, +	0x00bbcf01, +	0xf412bbc8, +/* 0x01fa: mmctx_done */ +	0x94bdf61b, +	0x800199f0, +	0xf6021700, +	0x04bd0009, +/* 0x020a: strand_wait */ +	0xa0f900f8, +	0xb87e020a, +	0xa0fc0000, +/* 0x0216: strand_pre */ +	0x0c0900f8, +	0x024afc80, +	0xbd0009f6, +	0x020a7e04, +/* 0x0227: strand_post */ +	0x0900f800, +	0x4afc800d, +	0x0009f602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0238: strand_set */ +	0xfc800f0c, +	0x0cf6024f, +	0x0c04bd00, +	0x4afc800b, +	0x000cf602, +	0xfc8004bd, +	0x0ef6024f, +	0x0c04bd00, +	0x4afc800a, +	0x000cf602, +	0x0a7e04bd, +	0x00f80002, +/* 0x0268: strand_ctx_init */ +	0x99f094bd, +	0x37008003, +	0x0009f602, +	0x167e04bd, +	0x030e0002, +	0x0002387e, +	0xfc80c4bd, +	0x0cf60247, +	0x0c04bd00, +	0x4afc8001, +	0x000cf602, +	0x0a7e04bd, +	0x0c920002, +	0x46fc8001, +	0x000cf602, +	0x020c04bd, +	0x024afc80, +	0xbd000cf6, +	0x020a7e04, +	0x02277e00, +	0x42008800, +	0x20008902, +	0x0099cf02, +/* 0x02c7: ctx_init_strand_loop */ +	0xf608fe95, +	0x8ef6008e, +	0x808acf40, +	0xb606a5b6, +	0xeabb01a0, +	0x0480b600, +	0xf40192b6, +	0xe4b6e81b, +	0xf2efbc08, +	0x99f094bd, +	0x17008003, +	0x0009f602, +	0x00f804bd, +/* 0x02f8: error */ +	0x02050080, +	0xbd000ff6, +	0x80010f04, +	0xf6030700, +	0x04bd000f, +/* 0x030e: init */ +	0x04bd00f8, +	0x410007fe, +	0x11cf4200, +	0x0911e700, +	0x0814b601, +	0x020014fe, +	0x12004002, +	0xbd0002f6, +	0x05c94104, +	0xbd0010fe, +	0x07004024, +	0xbd0002f6, +	0x20034204, +	0x01010080, +	0xbd0002f6, +	0x20044204, +	0x01010480, +	0xbd0002f6, +	0x200b4204, +	0x01010880, +	0xbd0002f6, +	0x200c4204, +	0x01011c80, +	0xbd0002f6, +	0x01039204, +	0x03090080, +	0xbd0003f6, +	0x87044204, +	0xf6040040, +	0x04bd0002, +	0x00400402, +	0x0002f603, +	0x31f404bd, +	0x96048e10, +	0x00657e40, +	0xc7feb200, +	0x01b590f1, +	0x1ff4f003, +	0x01020fb5, +	0x041fbb01, +	0x800112b6, +	0xf6010300, +	0x04bd0001, +	0x01040080, +	0xbd0001f6, +	0x01004104, +	0xa87e020f, +	0xb77e0006, +	0x100f0006, +	0x0006f97e, +	0x98000e98, +	0x207e010f, +	0x14950001, +	0xc0008008, +	0x0004f601, +	0x008004bd, +	0x04f601c1, +	0xb704bd00, +	0xbb130030, +	0xf5b6001f, +	0xd3008002, +	0x000ff601, +	0x15b604bd, +	0x0110b608, +	0xb20814b6, +	0x02687e1f, +	0x001fbb00, +	0x84020398, +/* 0x041f: init_gpc */ +	0xb8502000, +	0x0008044e, +	0x8f7e1fb2, +	0x4eb80000, +	0xbd00010c, +	0x008f7ef4, +	0x044eb800, +	0x8f7e0001, +	0x4eb80000, +	0x0f000100, +	0x008f7e02, +	0x004eb800, +/* 0x044e: init_gpc_wait */ +	0x657e0008, +	0xffc80000, +	0xf90bf41f, +	0x08044eb8, +	0x00657e00, +	0x001fbb00, +	0x800040b7, +	0xf40132b6, +	0x000fb41b, +	0x0006f97e, +	0xa87e000f, +	0x00800006, +	0x01f60201, +	0xbd04bd00, +	0x1f19f014, +	0x02300080, +	0xbd0001f6, +/* 0x0491: main */ +	0x0031f404, +	0x0d0028f4, +	0x00377e10, +	0xf401f400, +	0x4001e4b1, +	0x00c71bf5, +	0x99f094bd, +	0x37008004, +	0x0009f602, +	0x008104bd, +	0x11cf02c0, +	0xc1008200, +	0x0022cf02, +	0xf41f13c8, +	0x23c8770b, +	0x550bf41f, +	0x12b220f9, +	0x99f094bd, +	0x37008007, +	0x0009f602, +	0x32f404bd, +	0x0231f401, +	0x00087c7e, +	0x99f094bd, +	0x17008007, +	0x0009f602, +	0x20fc04bd, +	0x99f094bd, +	0x37008006, +	0x0009f602, +	0x31f404bd, +	0x087c7e01, +	0xf094bd00, +	0x00800699, +	0x09f60217, +	0xf404bd00, +/* 0x0522: chsw_prev_no_next */ +	0x20f92f0e, +	0x32f412b2, +	0x0232f401, +	0x00087c7e, +	0x008020fc, +	0x02f602c0, +	0xf404bd00, +/* 0x053e: chsw_no_prev */ +	0x23c8130e, +	0x0d0bf41f, +	0xf40131f4, +	0x7c7e0232, +/* 0x054e: chsw_done */ +	0x01020008, +	0x02c30080, +	0xbd0002f6, +	0xf094bd04, +	0x00800499, +	0x09f60217, +	0xf504bd00, +/* 0x056b: main_not_ctx_switch */ +	0xb0ff2a0e, +	0x1bf401e4, +	0x7ef2b20c, +	0xf400081c, +/* 0x057a: main_not_ctx_chan */ +	0xe4b0400e, +	0x2c1bf402, +	0x99f094bd, +	0x37008007, +	0x0009f602, +	0x32f404bd, +	0x0232f401, +	0x00087c7e, +	0x99f094bd, +	0x17008007, +	0x0009f602, +	0x0ef404bd, +/* 0x05a9: main_not_ctx_save */ +	0x10ef9411, +	0x7e01f5f0, +	0xf50002f8, +/* 0x05b7: main_done */ +	0xbdfede0e, +	0x1f29f024, +	0x02300080, +	0xbd0002f6, +	0xcc0ef504, +/* 0x05c9: ih */ +	0xfe80f9fe, +	0x80f90188, +	0xa0f990f9, +	0xd0f9b0f9, +	0xf0f9e0f9, +	0x004a04bd, +	0x00aacf02, +	0xf404abc4, +	0x100d230b, +	0xcf1a004e, +	0x004f00ee, +	0x00ffcf19, +	0x0000047e, +	0x0400b0b7, +	0x0040010e, +	0x000ef61d, +/* 0x060a: ih_no_fifo */ +	0xabe404bd, +	0x0bf40100, +	0x4e100d0c, +	0x047e4001, +/* 0x061a: ih_no_ctxsw */ +	0xabe40000, +	0x0bf40400, +	0x07088e56, +	0x00657e40, +	0x80ffb200, +	0xf6020400, +	0x04bd000f, +	0x4007048e, +	0x0000657e, +	0x0080ffb2, +	0x0ff60203, +	0xc704bd00, +	0xee9450fe, +	0x07008f02, +	0x00efbb40, +	0x0000657e, +	0x02020080, +	0xbd000ff6, +	0x7e030f04, +	0x4b0002f8, +	0xbfb20100, +	0x4001448e, +	0x00008f7e, +/* 0x0674: ih_no_fwmthd */ +	0xbd05044b, +	0xb4abffb0, +	0x800c0bf4, +	0xf6030700, +	0x04bd000b, +/* 0x0688: ih_no_other */ +	0xf6010040, +	0x04bd000a, +	0xe0fcf0fc, +	0xb0fcd0fc, +	0x90fca0fc, +	0x88fe80fc, +	0xf480fc00, +	0x01f80032, +/* 0x06a8: ctx_4170s */ +	0xb210f5f0, +	0x41708eff, +	0x008f7e40, +/* 0x06b7: ctx_4170w */ +	0x8e00f800, +	0x7e404170, +	0xb2000065, +	0x10f4f0ff, +	0xf8f31bf4, +/* 0x06c9: ctx_redswitch */ +	0x02004e00, +	0xf040e5f0, +	0xe5f020e5, +	0x85008010, +	0x000ef601, +	0x080f04bd, +/* 0x06e0: ctx_redswitch_delay */ +	0xf401f2b6, +	0xe5f1fd1b, +	0xe5f10400, +	0x00800100, +	0x0ef60185, +	0xf804bd00, +/* 0x06f9: ctx_86c */ +	0x23008000, +	0x000ff602, +	0xffb204bd, +	0x408a148e, +	0x00008f7e, +	0x8c8effb2, +	0x8f7e41a8, +	0x00f80000, +/* 0x0718: ctx_mem */ +	0x02840080, +	0xbd000ff6, +/* 0x0721: ctx_mem_wait */ +	0x84008f04, +	0x00ffcf02, +	0xf405fffd, +	0x00f8f61b, +/* 0x0730: ctx_load */ +	0x99f094bd, +	0x37008005, +	0x0009f602, +	0x0c0a04bd, +	0x0000b87e, +	0x0080f4bd, +	0x0ff60289, +	0x8004bd00, +	0xf602c100, +	0x04bd0002, +	0x02830080, +	0xbd0002f6, +	0x7e070f04, +	0x80000718, +	0xf602c000, +	0x04bd0002, +	0xf0000bfe, +	0x24b61f2a, +	0x0220b604, +	0x99f094bd, +	0x37008008, +	0x0009f602, +	0x008004bd, +	0x02f60281, +	0xd204bd00, +	0x80000000, +	0x800225f0, +	0xf6028800, +	0x04bd0002, +	0x00421001, +	0x0223f002, +	0xf80512fa, +	0xf094bd03, +	0x00800899, +	0x09f60217, +	0x9804bd00, +	0x14b68101, +	0x80029818, +	0xfd0825b6, +	0x01b50512, +	0xf094bd16, +	0x00800999, +	0x09f60237, +	0x8004bd00, +	0xf6028100, +	0x04bd0001, +	0x00800102, +	0x02f60288, +	0x4104bd00, +	0x13f00100, +	0x0501fa06, +	0x94bd03f8, +	0x800999f0, +	0xf6021700, +	0x04bd0009, +	0x99f094bd, +	0x17008005, +	0x0009f602, +	0x00f804bd, +/* 0x081c: ctx_chan */ +	0x0007307e, +	0xb87e0c0a, +	0x050f0000, +	0x0007187e, +/* 0x082e: ctx_mmio_exec */ +	0x039800f8, +	0x81008041, +	0x0003f602, +	0x34bd04bd, +/* 0x083c: ctx_mmio_loop */ +	0xf4ff34c4, +	0x00450e1b, +	0x0653f002, +	0xf80535fa, +/* 0x084d: ctx_mmio_pull */ +	0x804e9803, +	0x7e814f98, +	0xb600008f, +	0x12b60830, +	0xdf1bf401, +/* 0x0860: ctx_mmio_done */ +	0x80160398, +	0xf6028100, +	0x04bd0003, +	0x414000b5, +	0x13f00100, +	0x0601fa06, +	0x00f803f8, +/* 0x087c: ctx_xfer */ +	0x0080040e, +	0x0ef60302, +/* 0x0887: ctx_xfer_idle */ +	0x8e04bd00, +	0xcf030000, +	0xe4f100ee, +	0x1bf42000, +	0x0611f4f5, +/* 0x089b: ctx_xfer_pre */ +	0x0f0c02f4, +	0x06f97e10, +	0x1b11f400, +/* 0x08a4: ctx_xfer_pre_load */ +	0xa87e020f, +	0xb77e0006, +	0xc97e0006, +	0xf4bd0006, +	0x0006a87e, +	0x0007307e, +/* 0x08bc: ctx_xfer_exec */ +	0xbd160198, +	0x05008024, +	0x0002f601, +	0x1fb204bd, +	0x41a5008e, +	0x00008f7e, +	0xf001fcf0, +	0x24b6022c, +	0x05f2fd01, +	0x048effb2, +	0x8f7e41a5, +	0x167e0000, +	0x24bd0002, +	0x0247fc80, +	0xbd0002f6, +	0x012cf004, +	0x800320b6, +	0xf6024afc, +	0x04bd0002, +	0xf001acf0, +	0x000b06a5, +	0x98000c98, +	0x000e010d, +	0x00013d7e, +	0xec7e080a, +	0x0a7e0000, +	0x01f40002, +	0x7e0c0a12, +	0x0f0000b8, +	0x07187e05, +	0x2d02f400, +/* 0x0938: ctx_xfer_post */ +	0xa87e020f, +	0xf4bd0006, +	0x0006f97e, +	0x0002277e, +	0x0006b77e, +	0xa87ef4bd, +	0x11f40006, +	0x40019810, +	0xf40511fd, +	0x2e7e070b, +/* 0x0962: ctx_xfer_no_post_mmio */ +/* 0x0962: ctx_xfer_done */ +	0x00f80008, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h index b59f694c042..92dfe6a4ac8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc.h @@ -206,14 +206,14 @@ uint32_t nvc0_grhub_data[] = {  };  uint32_t nvc0_grhub_code[] = { -	0x031b0ef5, +	0x039b0ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -237,184 +237,214 @@ uint32_t nvc0_grhub_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f00f00, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f00f,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf00f0007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f00f00, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -428,7 +458,7 @@ uint32_t nvc0_grhub_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0x07f100f8,  	0x03f00500,  	0x000fd002, @@ -436,82 +466,117 @@ uint32_t nvc0_grhub_code[] = {  	0x0007f101,  	0x0303f007,  	0xbd000fd0, -/* 0x031b: init */ +/* 0x039b: init */  	0xbd00f804, -	0x0004fe04, -	0xf10007fe, -	0xf0120017, -	0x12d00227, -	0xb117f100, -	0x0010fe05, -	0x040017f1, -	0xf1c010d0, -	0xb6040437, -	0x27f10634, -	0x32d02003, -	0x0427f100, -	0x0132d020, +	0x0007fe04, +	0x420017f1, +	0xcf0013f0, +	0x11e70011, +	0x14b60109, +	0x0014fe08, +	0xf10227f0, +	0xf0120007, +	0x02d00003, +	0xf104bd00, +	0xfe06c817, +	0x24bd0010, +	0x070007f1, +	0xd00003f0, +	0x04bd0002, +	0x200327f1, +	0x010007f1, +	0xd00103f0, +	0x04bd0002, +	0x200427f1, +	0x010407f1, +	0xd00103f0, +	0x04bd0002,  	0x200b27f1, -	0xf10232d0, -	0xd0200c27, -	0x27f10732, -	0x24b60c24, -	0x0003b906, -	0xf10023d0, +	0x010807f1, +	0xd00103f0, +	0x04bd0002, +	0x200c27f1, +	0x011c07f1, +	0xd00103f0, +	0x04bd0002, +	0xf1010392, +	0xf0090007, +	0x03d00303, +	0xf104bd00,  	0xf0870427, -	0x12d00023, -	0x0012b700, -	0x0427f001, -	0xf40012d0, -	0xe7f11031, -	0xe3f09604, -	0x6821f440, -	0x8090f1c7, -	0xf4f00301, -	0x020f801f, -	0xbb0117f0, -	0x12b6041f, -	0x0c27f101, -	0x0624b604, -	0xd00021d0, -	0x17f14021, -	0x0e980100, -	0x010f9800, -	0x014721f5, -	0x070037f1, -	0x950634b6, -	0x34d00814, -	0x4034d000, -	0x130030b7, -	0xb6001fbb, -	0x3fd002f5, -	0x0815b600, -	0xb60110b6, -	0x1fb90814, -	0x7121f502, -	0x001fbb02, -	0xf1020398, -	0xf0200047, -/* 0x03f6: init_gpc */ -	0x4ea05043, -	0x1fb90804, -	0x8d21f402, -	0x010c4ea0, -	0x21f4f4bd, -	0x044ea08d, -	0x8d21f401, -	0x01004ea0, -	0xf402f7f0, -	0x4ea08d21, -/* 0x041e: init_gpc_wait */ -	0x21f40800, -	0x1fffc868, -	0xa0fa0bf4, -	0xf408044e, -	0x1fbb6821, -	0x0040b700, -	0x0132b680, -	0xf1be1bf4, +	0x07f10023, +	0x03f00400, +	0x0002d000, +	0x27f004bd, +	0x0007f104, +	0x0003f003, +	0xbd0002d0, +	0x1031f404, +	0x9604e7f1, +	0xf440e3f0, +	0xfeb96821, +	0x90f1c702, +	0xf0030180, +	0x0f801ff4, +	0x0117f002, +	0xb6041fbb, +	0x07f10112, +	0x03f00300, +	0x0001d001, +	0x07f104bd, +	0x03f00400, +	0x0001d001, +	0x17f104bd, +	0xf7f00100, +	0x0d21f502, +	0x1f21f508, +	0x10f7f008, +	0x086c21f5, +	0x98000e98, +	0x21f5010f, +	0x14950150, +	0x0007f108, +	0x0103f0c0, +	0xbd0004d0, +	0x0007f104, +	0x0103f0c1, +	0xbd0004d0, +	0x0030b704, +	0x001fbb13, +	0xf102f5b6, +	0xf0d30007, +	0x0fd00103, +	0xb604bd00, +	0x10b60815, +	0x0814b601, +	0xf5021fb9, +	0xbb02d321, +	0x0398001f, +	0x0047f102, +	0x5043f020, +/* 0x04f4: init_gpc */ +	0x08044ea0, +	0xf4021fb9, +	0x4ea09d21, +	0xf4bd010c, +	0xa09d21f4, +	0xf401044e, +	0x4ea09d21, +	0xf7f00100, +	0x9d21f402, +	0x08004ea0, +/* 0x051c: init_gpc_wait */ +	0xc86821f4, +	0x0bf41fff, +	0x044ea0fa, +	0x6821f408, +	0xb7001fbb, +	0xb6800040, +	0x1bf40132, +	0x00f7f0be, +	0x086c21f5, +	0xf500f7f0, +	0xf1080d21,  	0xf0010007,  	0x01d00203,  	0xbd04bd00, @@ -519,360 +584,421 @@ uint32_t nvc0_grhub_code[] = {  	0x080007f1,  	0xd00203f0,  	0x04bd0001, -/* 0x0458: main */ +/* 0x0564: main */  	0xf40031f4,  	0xd7f00028,  	0x3921f410,  	0xb1f401f4,  	0xf54001e4, -	0xbd00de1b, +	0xbd00e91b,  	0x0499f094,  	0x0f0007f1,  	0xd00203f0,  	0x04bd0009, -	0x0b0017f1, -	0xcf0614b6, -	0x11cf4012, -	0x1f13c800, -	0x00870bf5, -	0xf41f23c8, -	0x20f9620b, -	0xbd0212b9, -	0x0799f094, -	0x0f0007f1, -	0xd00203f0, -	0x04bd0009, -	0xf40132f4, -	0x21f50231, -	0x94bd082f, +	0xc00017f1, +	0xcf0213f0, +	0x27f10011, +	0x23f0c100, +	0x0022cf02, +	0xf51f13c8, +	0xc800890b, +	0x0bf41f23, +	0xb920f962, +	0x94bd0212,  	0xf10799f0, -	0xf0170007, +	0xf00f0007,  	0x09d00203, -	0xfc04bd00, -	0xf094bd20, -	0x07f10699, -	0x03f00f00, -	0x0009d002, -	0x31f404bd, -	0x2f21f501, -	0xf094bd08, -	0x07f10699, +	0xf404bd00, +	0x31f40132, +	0x4021f502, +	0xf094bd0a, +	0x07f10799,  	0x03f01700,  	0x0009d002, -	0x0ef404bd, -/* 0x04f9: chsw_prev_no_next */ -	0xb920f931, -	0x32f40212, -	0x0232f401, -	0x082f21f5, -	0x17f120fc, -	0x14b60b00, -	0x0012d006, -/* 0x0517: chsw_no_prev */ -	0xc8130ef4, -	0x0bf41f23, -	0x0131f40d, -	0xf50232f4, -/* 0x0527: chsw_done */ -	0xf1082f21, -	0xb60b0c17, -	0x27f00614, -	0x0012d001, +	0x20fc04bd,  	0x99f094bd, -	0x0007f104, +	0x0007f106, +	0x0203f00f, +	0xbd0009d0, +	0x0131f404, +	0x0a4021f5, +	0x99f094bd, +	0x0007f106,  	0x0203f017,  	0xbd0009d0, -	0x130ef504, -/* 0x0549: main_not_ctx_switch */ -	0x01e4b0ff, -	0xb90d1bf4, -	0x21f502f2, -	0x0ef407bb, -/* 0x0559: main_not_ctx_chan */ -	0x02e4b046, -	0xbd321bf4, -	0x0799f094, -	0x0f0007f1, +	0x330ef404, +/* 0x060c: chsw_prev_no_next */ +	0x12b920f9, +	0x0132f402, +	0xf50232f4, +	0xfc0a4021, +	0x0007f120, +	0x0203f0c0, +	0xbd0002d0, +	0x130ef404, +/* 0x062c: chsw_no_prev */ +	0xf41f23c8, +	0x31f40d0b, +	0x0232f401, +	0x0a4021f5, +/* 0x063c: chsw_done */ +	0xf10127f0, +	0xf0c30007, +	0x02d00203, +	0xbd04bd00, +	0x0499f094, +	0x170007f1,  	0xd00203f0,  	0x04bd0009, -	0xf40132f4, -	0x21f50232, -	0x94bd082f, +	0xff080ef5, +/* 0x0660: main_not_ctx_switch */ +	0xf401e4b0, +	0xf2b90d1b, +	0xd021f502, +	0x460ef409, +/* 0x0670: main_not_ctx_chan */ +	0xf402e4b0, +	0x94bd321b,  	0xf10799f0, -	0xf0170007, +	0xf00f0007,  	0x09d00203,  	0xf404bd00, -/* 0x058e: main_not_ctx_save */ -	0xef94110e, -	0x01f5f010, -	0x02fe21f5, -	0xfec00ef5, -/* 0x059c: main_done */ -	0x29f024bd, -	0x0007f11f, -	0x0203f008, -	0xbd0002d0, -	0xab0ef504, -/* 0x05b1: ih */ -	0xfe80f9fe, -	0x80f90188, -	0xa0f990f9, -	0xd0f9b0f9, -	0xf0f9e0f9, -	0x0acf04bd, -	0x04abc480, -	0xf11d0bf4, -	0xf01900b7, -	0xbecf10d7, -	0x00bfcf40, +	0x32f40132, +	0x4021f502, +	0xf094bd0a, +	0x07f10799, +	0x03f01700, +	0x0009d002, +	0x0ef404bd, +/* 0x06a5: main_not_ctx_save */ +	0x10ef9411, +	0xf501f5f0, +	0xf5037e21, +/* 0x06b3: main_done */ +	0xbdfeb50e, +	0x1f29f024, +	0x080007f1, +	0xd00203f0, +	0x04bd0002, +	0xfea00ef5, +/* 0x06c8: ih */ +	0x88fe80f9, +	0xf980f901, +	0xf9a0f990, +	0xf9d0f9b0, +	0xbdf0f9e0, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x10d7f030, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00,  	0xb70421f4,  	0xf00400b0, -	0xbed001e7, -/* 0x05e9: ih_no_fifo */ -	0x00abe400, -	0x0d0bf401, -	0xf110d7f0, -	0xf44001e7, -/* 0x05fa: ih_no_ctxsw */ -	0xb7f10421, -	0xb0bd0104, -	0xf4b4abff, -	0xa7f10d0b, -	0xa4b60c1c, -	0x00abd006, -/* 0x0610: ih_no_other */ -	0xfc400ad0, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x071a: ih_no_fifo */ +	0xabe404bd, +	0x0bf40100, +	0x10d7f00d, +	0x4001e7f1, +/* 0x072b: ih_no_ctxsw */ +	0xe40421f4, +	0xf40400ab, +	0xe7f16c0b, +	0xe3f00708, +	0x6821f440, +	0xf102ffb9, +	0xf0040007, +	0x0fd00203, +	0xf104bd00, +	0xf00704e7, +	0x21f440e3, +	0x02ffb968, +	0x030007f1, +	0xd00203f0, +	0x04bd000f, +	0x9450fec7, +	0xf7f102ee, +	0xf3f00700, +	0x00efbb40, +	0xf16821f4, +	0xf0020007, +	0x0fd00203, +	0xf004bd00, +	0x21f503f7, +	0xb7f1037e, +	0xbfb90100, +	0x44e7f102, +	0x40e3f001, +/* 0x079b: ih_no_fwmthd */ +	0xf19d21f4, +	0xbd0504b7, +	0xb4abffb0, +	0xf10f0bf4, +	0xf0070007, +	0x0bd00303, +/* 0x07b3: ih_no_other */ +	0xf104bd00, +	0xf0010007, +	0x0ad00003, +	0xfc04bd00,  	0xfce0fcf0,  	0xfcb0fcd0,  	0xfc90fca0,  	0x0088fe80,  	0x32f480fc, -/* 0x062b: ctx_4160s */ -	0xf101f800, -	0xf04160e7, -	0xf7f040e3, -	0x8d21f401, -/* 0x0638: ctx_4160s_wait */ -	0xc86821f4, -	0x0bf404ff, -/* 0x0643: ctx_4160c */ -	0xf100f8fa, +/* 0x07d7: ctx_4160s */ +	0xf001f800, +	0xffb901f7, +	0x60e7f102, +	0x40e3f041, +/* 0x07e7: ctx_4160s_wait */ +	0xf19d21f4,  	0xf04160e7, -	0xf4bd40e3, -	0xf88d21f4, -/* 0x0651: ctx_4170s */ -	0x70e7f100, +	0x21f440e3, +	0x02ffb968, +	0xf404ffc8, +	0x00f8f00b, +/* 0x07fc: ctx_4160c */ +	0xffb9f4bd, +	0x60e7f102,  	0x40e3f041, -	0xf410f5f0, -	0x00f88d21, -/* 0x0660: ctx_4170w */ -	0x4170e7f1, -	0xf440e3f0, -	0xf4f06821, -	0xf31bf410, -/* 0x0672: ctx_redswitch */ -	0xe7f100f8, -	0xe4b60614, -	0x70f7f106, -	0x00efd002, -/* 0x0683: ctx_redswitch_delay */ -	0xb608f7f0, -	0x1bf401f2, -	0x70f7f1fd, -	0x00efd007, -/* 0x0692: ctx_86c */ -	0xe7f100f8, -	0xe4b6086c, -	0x00efd006, -	0x8a14e7f1, -	0xf440e3f0, -	0xe7f18d21, -	0xe3f0a86c, -	0x8d21f441, -/* 0x06b2: ctx_load */ +	0xf89d21f4, +/* 0x080d: ctx_4170s */ +	0x10f5f000, +	0xf102ffb9, +	0xf04170e7, +	0x21f440e3, +/* 0x081f: ctx_4170w */ +	0xf100f89d, +	0xf04170e7, +	0x21f440e3, +	0x02ffb968, +	0xf410f4f0, +	0x00f8f01b, +/* 0x0834: ctx_redswitch */ +	0x0200e7f1, +	0xf040e5f0, +	0xe5f020e5, +	0x0007f110, +	0x0103f085, +	0xbd000ed0, +	0x08f7f004, +/* 0x0850: ctx_redswitch_delay */ +	0xf401f2b6, +	0xe5f1fd1b, +	0xe5f10400, +	0x07f10100, +	0x03f08500, +	0x000ed001, +	0x00f804bd, +/* 0x086c: ctx_86c */ +	0x1b0007f1, +	0xd00203f0, +	0x04bd000f, +	0xf102ffb9, +	0xf08a14e7, +	0x21f440e3, +	0x02ffb99d, +	0xa86ce7f1, +	0xf441e3f0, +	0x00f89d21, +/* 0x0894: ctx_mem */ +	0x840007f1, +	0xd00203f0, +	0x04bd000f, +/* 0x08a0: ctx_mem_wait */ +	0x8400f7f1, +	0xcf02f3f0, +	0xfffd00ff, +	0xf31bf405, +/* 0x08b2: ctx_load */  	0x94bd00f8,  	0xf10599f0,  	0xf00f0007,  	0x09d00203,  	0xf004bd00,  	0x21f40ca7, -	0x2417f1c9, -	0x0614b60a, -	0xf10010d0, -	0xb60b0037, -	0x32d00634, -	0x0c17f140, -	0x0614b60a, -	0xd00747f0, -	0x14d00012, -/* 0x06ed: ctx_chan_wait_0 */ -	0x4014cf40, -	0xf41f44f0, -	0x32d0fa1b, -	0x000bfe00, -	0xb61f2af0, -	0x20b60424, -	0xf094bd02, +	0xf1f4bdd0, +	0xf0890007, +	0x0fd00203, +	0xf104bd00, +	0xf0c10007, +	0x02d00203, +	0xf104bd00, +	0xf0830007, +	0x02d00203, +	0xf004bd00, +	0x21f507f7, +	0x07f10894, +	0x03f0c000, +	0x0002d002, +	0x0bfe04bd, +	0x1f2af000, +	0xb60424b6, +	0x94bd0220, +	0xf10899f0, +	0xf00f0007, +	0x09d00203, +	0xf104bd00, +	0xf0810007, +	0x02d00203, +	0xf104bd00, +	0xf1000027, +	0xf0800023, +	0x07f10225, +	0x03f08800, +	0x0002d002, +	0x17f004bd, +	0x0027f110, +	0x0223f002, +	0xf80512fa, +	0xf094bd03,  	0x07f10899, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x17f104bd, -	0x14b60a04, -	0x0012d006, -	0x0a2017f1, -	0xf00614b6, -	0x23f10227, -	0x12d08000, -	0x1017f000, -	0x020027f1, -	0xfa0223f0, -	0x03f80512, +	0x019804bd, +	0x1814b681, +	0xb6800298, +	0x12fd0825, +	0x16018005,  	0x99f094bd, -	0x0007f108, -	0x0203f017, +	0x0007f109, +	0x0203f00f,  	0xbd0009d0, -	0x81019804, -	0x981814b6, -	0x25b68002, -	0x0512fd08, -	0xbd160180, -	0x0999f094, -	0x0f0007f1, -	0xd00203f0, -	0x04bd0009, -	0x0a0427f1, -	0xd00624b6, -	0x27f00021, -	0x2017f101, -	0x0614b60a, -	0xf10012d0, -	0xf0010017, -	0x01fa0613, -	0xbd03f805, -	0x0999f094, -	0x170007f1, +	0x0007f104, +	0x0203f081, +	0xbd0001d0, +	0x0127f004, +	0x880007f1,  	0xd00203f0, -	0x04bd0009, +	0x04bd0002, +	0x010017f1, +	0xfa0613f0, +	0x03f80501,  	0x99f094bd, -	0x0007f105, +	0x0007f109,  	0x0203f017,  	0xbd0009d0, -/* 0x07bb: ctx_chan */ -	0xf500f804, -	0xf5062b21, -	0xf006b221, -	0x21f40ca7, -	0x1017f1c9, -	0x0614b60a, -	0xd00527f0, -/* 0x07d6: ctx_chan_wait */ -	0x12cf0012, -	0x0522fd00, -	0xf5fa1bf4, -	0xf8064321, -/* 0x07e5: ctx_mmio_exec */ -	0x41039800, -	0x0a0427f1, -	0xd00624b6, -	0x34bd0023, -/* 0x07f4: ctx_mmio_loop */ +	0xf094bd04, +	0x07f10599, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x09d0: ctx_chan */ +	0x07d721f5, +	0x08b221f5, +	0xf40ca7f0, +	0xf7f0d021, +	0x9421f505, +	0xfc21f508, +/* 0x09eb: ctx_mmio_exec */ +	0x9800f807, +	0x07f14103, +	0x03f08100, +	0x0003d002, +	0x34bd04bd, +/* 0x09fc: ctx_mmio_loop */  	0xf4ff34c4,  	0x57f10f1b,  	0x53f00200,  	0x0535fa06, -/* 0x0806: ctx_mmio_pull */ +/* 0x0a0e: ctx_mmio_pull */  	0x4e9803f8,  	0x814f9880, -	0xb68d21f4, +	0xb69d21f4,  	0x12b60830,  	0xdf1bf401, -/* 0x0818: ctx_mmio_done */ -	0xd0160398, -	0x00800023, -	0x0017f140, -	0x0613f001, -	0xf80601fa, -/* 0x082f: ctx_xfer */ -	0xf100f803, -	0xb60c00f7, -	0xe7f006f4, -	0x80fed004, -/* 0x083c: ctx_xfer_idle */ -	0xf100fecf, -	0xf42000e4, -	0x11f4f91b, -	0x1102f406, -/* 0x084c: ctx_xfer_pre */ -	0xf510f7f0, -	0xf5069221, -	0xf4062b21, -/* 0x085a: ctx_xfer_pre_load */ -	0xf7f01c11, -	0x5121f502, -	0x6021f506, -	0x7221f506, -	0xf5f4bd06, -	0xf5065121, -/* 0x0873: ctx_xfer_exec */ -	0x9806b221, -	0x27f11601, -	0x24b60414, -	0x0020d006, -	0xa500e7f1, -	0xb941e3f0, -	0x21f4021f, -	0x04e0b68d, -	0xf001fcf0, -	0x24b6022c, -	0x05f2fd01, -	0xf18d21f4, -	0xf04afc17, -	0x27f00213, -	0x0012d00c, -	0x021521f5, -	0x47fc27f1, -	0xd00223f0, -	0x2cf00020, +/* 0x0a20: ctx_mmio_done */ +	0xf1160398, +	0xf0810007, +	0x03d00203, +	0x8004bd00, +	0x17f14000, +	0x13f00100, +	0x0601fa06, +	0x00f803f8, +/* 0x0a40: ctx_xfer */ +	0xf104e7f0, +	0xf0020007, +	0x0ed00303, +/* 0x0a4f: ctx_xfer_idle */ +	0xf104bd00, +	0xf00000e7, +	0xeecf03e3, +	0x00e4f100, +	0xf21bf420, +	0xf40611f4, +/* 0x0a66: ctx_xfer_pre */ +	0xf7f01102, +	0x6c21f510, +	0xd721f508, +	0x1c11f407, +/* 0x0a74: ctx_xfer_pre_load */ +	0xf502f7f0, +	0xf5080d21, +	0xf5081f21, +	0xbd083421, +	0x0d21f5f4, +	0xb221f508, +/* 0x0a8d: ctx_xfer_exec */ +	0x16019808, +	0x07f124bd, +	0x03f00500, +	0x0002d001, +	0x1fb904bd, +	0x00e7f102, +	0x41e3f0a5, +	0xf09d21f4, +	0x2cf001fc, +	0x0124b602, +	0xb905f2fd, +	0xe7f102ff, +	0xe3f0a504, +	0x9d21f441, +	0x026a21f5, +	0x07f124bd, +	0x03f047fc, +	0x0002d002, +	0x2cf004bd,  	0x0320b601, -	0xf00012d0, -	0xa5f001ac, -	0x00b7f006, -	0x98000c98, -	0xe7f0010d, -	0x6621f500, -	0x08a7f001, -	0x010921f5, -	0x021521f5, -	0xf02201f4, -	0x21f40ca7, -	0x1017f1c9, -	0x0614b60a, -	0xd00527f0, -/* 0x08fa: ctx_xfer_post_save_wait */ -	0x12cf0012, -	0x0522fd00, -	0xf4fa1bf4, -/* 0x0906: ctx_xfer_post */ -	0xf7f03202, -	0x5121f502, -	0xf5f4bd06, -	0xf5069221, -	0xf5023421, -	0xbd066021, -	0x5121f5f4, -	0x1011f406, -	0xfd400198, -	0x0bf40511, -	0xe521f507, -/* 0x0931: ctx_xfer_no_post_mmio */ -	0x4321f507, -/* 0x0935: ctx_xfer_done */ -	0x0000f806, -	0x00000000, -	0x00000000, -	0x00000000, -	0x00000000, -	0x00000000, +	0x4afc07f1, +	0xd00203f0, +	0x04bd0002, +	0xf001acf0, +	0xb7f006a5, +	0x000c9800, +	0xf0010d98, +	0x21f500e7, +	0xa7f0016f, +	0x1021f508, +	0x5e21f501, +	0x1301f402, +	0xf40ca7f0, +	0xf7f0d021, +	0x9421f505, +	0x3202f408, +/* 0x0b1c: ctx_xfer_post */ +	0xf502f7f0, +	0xbd080d21, +	0x6c21f5f4, +	0x7f21f508, +	0x1f21f502, +	0xf5f4bd08, +	0xf4080d21, +	0x01981011, +	0x0511fd40, +	0xf5070bf4, +/* 0x0b47: ctx_xfer_no_post_mmio */ +	0xf509eb21, +/* 0x0b4b: ctx_xfer_done */ +	0xf807fc21,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h index a1b9f763996..62b0c7601d8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvd7.fuc.h @@ -206,14 +206,14 @@ uint32_t nvd7_grhub_data[] = {  };  uint32_t nvd7_grhub_code[] = { -	0x031b0ef5, +	0x039b0ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -237,184 +237,214 @@ uint32_t nvd7_grhub_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f00f00, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f00f,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf00f0007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f00f00, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -428,7 +458,7 @@ uint32_t nvd7_grhub_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0x07f100f8,  	0x03f00500,  	0x000fd002, @@ -436,82 +466,117 @@ uint32_t nvd7_grhub_code[] = {  	0x0007f101,  	0x0303f007,  	0xbd000fd0, -/* 0x031b: init */ +/* 0x039b: init */  	0xbd00f804, -	0x0004fe04, -	0xf10007fe, -	0xf0120017, -	0x12d00227, -	0xb117f100, -	0x0010fe05, -	0x040017f1, -	0xf1c010d0, -	0xb6040437, -	0x27f10634, -	0x32d02003, -	0x0427f100, -	0x0132d020, +	0x0007fe04, +	0x420017f1, +	0xcf0013f0, +	0x11e70011, +	0x14b60109, +	0x0014fe08, +	0xf10227f0, +	0xf0120007, +	0x02d00003, +	0xf104bd00, +	0xfe06c817, +	0x24bd0010, +	0x070007f1, +	0xd00003f0, +	0x04bd0002, +	0x200327f1, +	0x010007f1, +	0xd00103f0, +	0x04bd0002, +	0x200427f1, +	0x010407f1, +	0xd00103f0, +	0x04bd0002,  	0x200b27f1, -	0xf10232d0, -	0xd0200c27, -	0x27f10732, -	0x24b60c24, -	0x0003b906, -	0xf10023d0, +	0x010807f1, +	0xd00103f0, +	0x04bd0002, +	0x200c27f1, +	0x011c07f1, +	0xd00103f0, +	0x04bd0002, +	0xf1010392, +	0xf0090007, +	0x03d00303, +	0xf104bd00,  	0xf0870427, -	0x12d00023, -	0x0012b700, -	0x0427f001, -	0xf40012d0, -	0xe7f11031, -	0xe3f09604, -	0x6821f440, -	0x8090f1c7, -	0xf4f00301, -	0x020f801f, -	0xbb0117f0, -	0x12b6041f, -	0x0c27f101, -	0x0624b604, -	0xd00021d0, -	0x17f14021, -	0x0e980100, -	0x010f9800, -	0x014721f5, -	0x070037f1, -	0x950634b6, -	0x34d00814, -	0x4034d000, -	0x130030b7, -	0xb6001fbb, -	0x3fd002f5, -	0x0815b600, -	0xb60110b6, -	0x1fb90814, -	0x7121f502, -	0x001fbb02, -	0xf1020398, -	0xf0200047, -/* 0x03f6: init_gpc */ -	0x4ea05043, -	0x1fb90804, -	0x8d21f402, -	0x010c4ea0, -	0x21f4f4bd, -	0x044ea08d, -	0x8d21f401, -	0x01004ea0, -	0xf402f7f0, -	0x4ea08d21, -/* 0x041e: init_gpc_wait */ -	0x21f40800, -	0x1fffc868, -	0xa0fa0bf4, -	0xf408044e, -	0x1fbb6821, -	0x0040b700, -	0x0132b680, -	0xf1be1bf4, +	0x07f10023, +	0x03f00400, +	0x0002d000, +	0x27f004bd, +	0x0007f104, +	0x0003f003, +	0xbd0002d0, +	0x1031f404, +	0x9604e7f1, +	0xf440e3f0, +	0xfeb96821, +	0x90f1c702, +	0xf0030180, +	0x0f801ff4, +	0x0117f002, +	0xb6041fbb, +	0x07f10112, +	0x03f00300, +	0x0001d001, +	0x07f104bd, +	0x03f00400, +	0x0001d001, +	0x17f104bd, +	0xf7f00100, +	0x0d21f502, +	0x1f21f508, +	0x10f7f008, +	0x086c21f5, +	0x98000e98, +	0x21f5010f, +	0x14950150, +	0x0007f108, +	0x0103f0c0, +	0xbd0004d0, +	0x0007f104, +	0x0103f0c1, +	0xbd0004d0, +	0x0030b704, +	0x001fbb13, +	0xf102f5b6, +	0xf0d30007, +	0x0fd00103, +	0xb604bd00, +	0x10b60815, +	0x0814b601, +	0xf5021fb9, +	0xbb02d321, +	0x0398001f, +	0x0047f102, +	0x5043f020, +/* 0x04f4: init_gpc */ +	0x08044ea0, +	0xf4021fb9, +	0x4ea09d21, +	0xf4bd010c, +	0xa09d21f4, +	0xf401044e, +	0x4ea09d21, +	0xf7f00100, +	0x9d21f402, +	0x08004ea0, +/* 0x051c: init_gpc_wait */ +	0xc86821f4, +	0x0bf41fff, +	0x044ea0fa, +	0x6821f408, +	0xb7001fbb, +	0xb6800040, +	0x1bf40132, +	0x00f7f0be, +	0x086c21f5, +	0xf500f7f0, +	0xf1080d21,  	0xf0010007,  	0x01d00203,  	0xbd04bd00, @@ -519,360 +584,421 @@ uint32_t nvd7_grhub_code[] = {  	0x080007f1,  	0xd00203f0,  	0x04bd0001, -/* 0x0458: main */ +/* 0x0564: main */  	0xf40031f4,  	0xd7f00028,  	0x3921f410,  	0xb1f401f4,  	0xf54001e4, -	0xbd00de1b, +	0xbd00e91b,  	0x0499f094,  	0x0f0007f1,  	0xd00203f0,  	0x04bd0009, -	0x0b0017f1, -	0xcf0614b6, -	0x11cf4012, -	0x1f13c800, -	0x00870bf5, -	0xf41f23c8, -	0x20f9620b, -	0xbd0212b9, -	0x0799f094, -	0x0f0007f1, -	0xd00203f0, -	0x04bd0009, -	0xf40132f4, -	0x21f50231, -	0x94bd082f, +	0xc00017f1, +	0xcf0213f0, +	0x27f10011, +	0x23f0c100, +	0x0022cf02, +	0xf51f13c8, +	0xc800890b, +	0x0bf41f23, +	0xb920f962, +	0x94bd0212,  	0xf10799f0, -	0xf0170007, +	0xf00f0007,  	0x09d00203, -	0xfc04bd00, -	0xf094bd20, -	0x07f10699, -	0x03f00f00, -	0x0009d002, -	0x31f404bd, -	0x2f21f501, -	0xf094bd08, -	0x07f10699, +	0xf404bd00, +	0x31f40132, +	0x4021f502, +	0xf094bd0a, +	0x07f10799,  	0x03f01700,  	0x0009d002, -	0x0ef404bd, -/* 0x04f9: chsw_prev_no_next */ -	0xb920f931, -	0x32f40212, -	0x0232f401, -	0x082f21f5, -	0x17f120fc, -	0x14b60b00, -	0x0012d006, -/* 0x0517: chsw_no_prev */ -	0xc8130ef4, -	0x0bf41f23, -	0x0131f40d, -	0xf50232f4, -/* 0x0527: chsw_done */ -	0xf1082f21, -	0xb60b0c17, -	0x27f00614, -	0x0012d001, +	0x20fc04bd,  	0x99f094bd, -	0x0007f104, +	0x0007f106, +	0x0203f00f, +	0xbd0009d0, +	0x0131f404, +	0x0a4021f5, +	0x99f094bd, +	0x0007f106,  	0x0203f017,  	0xbd0009d0, -	0x130ef504, -/* 0x0549: main_not_ctx_switch */ -	0x01e4b0ff, -	0xb90d1bf4, -	0x21f502f2, -	0x0ef407bb, -/* 0x0559: main_not_ctx_chan */ -	0x02e4b046, -	0xbd321bf4, -	0x0799f094, -	0x0f0007f1, +	0x330ef404, +/* 0x060c: chsw_prev_no_next */ +	0x12b920f9, +	0x0132f402, +	0xf50232f4, +	0xfc0a4021, +	0x0007f120, +	0x0203f0c0, +	0xbd0002d0, +	0x130ef404, +/* 0x062c: chsw_no_prev */ +	0xf41f23c8, +	0x31f40d0b, +	0x0232f401, +	0x0a4021f5, +/* 0x063c: chsw_done */ +	0xf10127f0, +	0xf0c30007, +	0x02d00203, +	0xbd04bd00, +	0x0499f094, +	0x170007f1,  	0xd00203f0,  	0x04bd0009, -	0xf40132f4, -	0x21f50232, -	0x94bd082f, +	0xff080ef5, +/* 0x0660: main_not_ctx_switch */ +	0xf401e4b0, +	0xf2b90d1b, +	0xd021f502, +	0x460ef409, +/* 0x0670: main_not_ctx_chan */ +	0xf402e4b0, +	0x94bd321b,  	0xf10799f0, -	0xf0170007, +	0xf00f0007,  	0x09d00203,  	0xf404bd00, -/* 0x058e: main_not_ctx_save */ -	0xef94110e, -	0x01f5f010, -	0x02fe21f5, -	0xfec00ef5, -/* 0x059c: main_done */ -	0x29f024bd, -	0x0007f11f, -	0x0203f008, -	0xbd0002d0, -	0xab0ef504, -/* 0x05b1: ih */ -	0xfe80f9fe, -	0x80f90188, -	0xa0f990f9, -	0xd0f9b0f9, -	0xf0f9e0f9, -	0x0acf04bd, -	0x04abc480, -	0xf11d0bf4, -	0xf01900b7, -	0xbecf10d7, -	0x00bfcf40, +	0x32f40132, +	0x4021f502, +	0xf094bd0a, +	0x07f10799, +	0x03f01700, +	0x0009d002, +	0x0ef404bd, +/* 0x06a5: main_not_ctx_save */ +	0x10ef9411, +	0xf501f5f0, +	0xf5037e21, +/* 0x06b3: main_done */ +	0xbdfeb50e, +	0x1f29f024, +	0x080007f1, +	0xd00203f0, +	0x04bd0002, +	0xfea00ef5, +/* 0x06c8: ih */ +	0x88fe80f9, +	0xf980f901, +	0xf9a0f990, +	0xf9d0f9b0, +	0xbdf0f9e0, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x10d7f030, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00,  	0xb70421f4,  	0xf00400b0, -	0xbed001e7, -/* 0x05e9: ih_no_fifo */ -	0x00abe400, -	0x0d0bf401, -	0xf110d7f0, -	0xf44001e7, -/* 0x05fa: ih_no_ctxsw */ -	0xb7f10421, -	0xb0bd0104, -	0xf4b4abff, -	0xa7f10d0b, -	0xa4b60c1c, -	0x00abd006, -/* 0x0610: ih_no_other */ -	0xfc400ad0, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x071a: ih_no_fifo */ +	0xabe404bd, +	0x0bf40100, +	0x10d7f00d, +	0x4001e7f1, +/* 0x072b: ih_no_ctxsw */ +	0xe40421f4, +	0xf40400ab, +	0xe7f16c0b, +	0xe3f00708, +	0x6821f440, +	0xf102ffb9, +	0xf0040007, +	0x0fd00203, +	0xf104bd00, +	0xf00704e7, +	0x21f440e3, +	0x02ffb968, +	0x030007f1, +	0xd00203f0, +	0x04bd000f, +	0x9450fec7, +	0xf7f102ee, +	0xf3f00700, +	0x00efbb40, +	0xf16821f4, +	0xf0020007, +	0x0fd00203, +	0xf004bd00, +	0x21f503f7, +	0xb7f1037e, +	0xbfb90100, +	0x44e7f102, +	0x40e3f001, +/* 0x079b: ih_no_fwmthd */ +	0xf19d21f4, +	0xbd0504b7, +	0xb4abffb0, +	0xf10f0bf4, +	0xf0070007, +	0x0bd00303, +/* 0x07b3: ih_no_other */ +	0xf104bd00, +	0xf0010007, +	0x0ad00003, +	0xfc04bd00,  	0xfce0fcf0,  	0xfcb0fcd0,  	0xfc90fca0,  	0x0088fe80,  	0x32f480fc, -/* 0x062b: ctx_4160s */ -	0xf101f800, -	0xf04160e7, -	0xf7f040e3, -	0x8d21f401, -/* 0x0638: ctx_4160s_wait */ -	0xc86821f4, -	0x0bf404ff, -/* 0x0643: ctx_4160c */ -	0xf100f8fa, +/* 0x07d7: ctx_4160s */ +	0xf001f800, +	0xffb901f7, +	0x60e7f102, +	0x40e3f041, +/* 0x07e7: ctx_4160s_wait */ +	0xf19d21f4,  	0xf04160e7, -	0xf4bd40e3, -	0xf88d21f4, -/* 0x0651: ctx_4170s */ -	0x70e7f100, +	0x21f440e3, +	0x02ffb968, +	0xf404ffc8, +	0x00f8f00b, +/* 0x07fc: ctx_4160c */ +	0xffb9f4bd, +	0x60e7f102,  	0x40e3f041, -	0xf410f5f0, -	0x00f88d21, -/* 0x0660: ctx_4170w */ -	0x4170e7f1, -	0xf440e3f0, -	0xf4f06821, -	0xf31bf410, -/* 0x0672: ctx_redswitch */ -	0xe7f100f8, -	0xe4b60614, -	0x70f7f106, -	0x00efd002, -/* 0x0683: ctx_redswitch_delay */ -	0xb608f7f0, -	0x1bf401f2, -	0x70f7f1fd, -	0x00efd007, -/* 0x0692: ctx_86c */ -	0xe7f100f8, -	0xe4b6086c, -	0x00efd006, -	0x8a14e7f1, -	0xf440e3f0, -	0xe7f18d21, -	0xe3f0a86c, -	0x8d21f441, -/* 0x06b2: ctx_load */ +	0xf89d21f4, +/* 0x080d: ctx_4170s */ +	0x10f5f000, +	0xf102ffb9, +	0xf04170e7, +	0x21f440e3, +/* 0x081f: ctx_4170w */ +	0xf100f89d, +	0xf04170e7, +	0x21f440e3, +	0x02ffb968, +	0xf410f4f0, +	0x00f8f01b, +/* 0x0834: ctx_redswitch */ +	0x0200e7f1, +	0xf040e5f0, +	0xe5f020e5, +	0x0007f110, +	0x0103f085, +	0xbd000ed0, +	0x08f7f004, +/* 0x0850: ctx_redswitch_delay */ +	0xf401f2b6, +	0xe5f1fd1b, +	0xe5f10400, +	0x07f10100, +	0x03f08500, +	0x000ed001, +	0x00f804bd, +/* 0x086c: ctx_86c */ +	0x1b0007f1, +	0xd00203f0, +	0x04bd000f, +	0xf102ffb9, +	0xf08a14e7, +	0x21f440e3, +	0x02ffb99d, +	0xa86ce7f1, +	0xf441e3f0, +	0x00f89d21, +/* 0x0894: ctx_mem */ +	0x840007f1, +	0xd00203f0, +	0x04bd000f, +/* 0x08a0: ctx_mem_wait */ +	0x8400f7f1, +	0xcf02f3f0, +	0xfffd00ff, +	0xf31bf405, +/* 0x08b2: ctx_load */  	0x94bd00f8,  	0xf10599f0,  	0xf00f0007,  	0x09d00203,  	0xf004bd00,  	0x21f40ca7, -	0x2417f1c9, -	0x0614b60a, -	0xf10010d0, -	0xb60b0037, -	0x32d00634, -	0x0c17f140, -	0x0614b60a, -	0xd00747f0, -	0x14d00012, -/* 0x06ed: ctx_chan_wait_0 */ -	0x4014cf40, -	0xf41f44f0, -	0x32d0fa1b, -	0x000bfe00, -	0xb61f2af0, -	0x20b60424, -	0xf094bd02, +	0xf1f4bdd0, +	0xf0890007, +	0x0fd00203, +	0xf104bd00, +	0xf0c10007, +	0x02d00203, +	0xf104bd00, +	0xf0830007, +	0x02d00203, +	0xf004bd00, +	0x21f507f7, +	0x07f10894, +	0x03f0c000, +	0x0002d002, +	0x0bfe04bd, +	0x1f2af000, +	0xb60424b6, +	0x94bd0220, +	0xf10899f0, +	0xf00f0007, +	0x09d00203, +	0xf104bd00, +	0xf0810007, +	0x02d00203, +	0xf104bd00, +	0xf1000027, +	0xf0800023, +	0x07f10225, +	0x03f08800, +	0x0002d002, +	0x17f004bd, +	0x0027f110, +	0x0223f002, +	0xf80512fa, +	0xf094bd03,  	0x07f10899, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x17f104bd, -	0x14b60a04, -	0x0012d006, -	0x0a2017f1, -	0xf00614b6, -	0x23f10227, -	0x12d08000, -	0x1017f000, -	0x020027f1, -	0xfa0223f0, -	0x03f80512, +	0x019804bd, +	0x1814b681, +	0xb6800298, +	0x12fd0825, +	0x16018005,  	0x99f094bd, -	0x0007f108, -	0x0203f017, +	0x0007f109, +	0x0203f00f,  	0xbd0009d0, -	0x81019804, -	0x981814b6, -	0x25b68002, -	0x0512fd08, -	0xbd160180, -	0x0999f094, -	0x0f0007f1, -	0xd00203f0, -	0x04bd0009, -	0x0a0427f1, -	0xd00624b6, -	0x27f00021, -	0x2017f101, -	0x0614b60a, -	0xf10012d0, -	0xf0010017, -	0x01fa0613, -	0xbd03f805, -	0x0999f094, -	0x170007f1, +	0x0007f104, +	0x0203f081, +	0xbd0001d0, +	0x0127f004, +	0x880007f1,  	0xd00203f0, -	0x04bd0009, +	0x04bd0002, +	0x010017f1, +	0xfa0613f0, +	0x03f80501,  	0x99f094bd, -	0x0007f105, +	0x0007f109,  	0x0203f017,  	0xbd0009d0, -/* 0x07bb: ctx_chan */ -	0xf500f804, -	0xf5062b21, -	0xf006b221, -	0x21f40ca7, -	0x1017f1c9, -	0x0614b60a, -	0xd00527f0, -/* 0x07d6: ctx_chan_wait */ -	0x12cf0012, -	0x0522fd00, -	0xf5fa1bf4, -	0xf8064321, -/* 0x07e5: ctx_mmio_exec */ -	0x41039800, -	0x0a0427f1, -	0xd00624b6, -	0x34bd0023, -/* 0x07f4: ctx_mmio_loop */ +	0xf094bd04, +	0x07f10599, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x09d0: ctx_chan */ +	0x07d721f5, +	0x08b221f5, +	0xf40ca7f0, +	0xf7f0d021, +	0x9421f505, +	0xfc21f508, +/* 0x09eb: ctx_mmio_exec */ +	0x9800f807, +	0x07f14103, +	0x03f08100, +	0x0003d002, +	0x34bd04bd, +/* 0x09fc: ctx_mmio_loop */  	0xf4ff34c4,  	0x57f10f1b,  	0x53f00200,  	0x0535fa06, -/* 0x0806: ctx_mmio_pull */ +/* 0x0a0e: ctx_mmio_pull */  	0x4e9803f8,  	0x814f9880, -	0xb68d21f4, +	0xb69d21f4,  	0x12b60830,  	0xdf1bf401, -/* 0x0818: ctx_mmio_done */ -	0xd0160398, -	0x00800023, -	0x0017f140, -	0x0613f001, -	0xf80601fa, -/* 0x082f: ctx_xfer */ -	0xf100f803, -	0xb60c00f7, -	0xe7f006f4, -	0x80fed004, -/* 0x083c: ctx_xfer_idle */ -	0xf100fecf, -	0xf42000e4, -	0x11f4f91b, -	0x1102f406, -/* 0x084c: ctx_xfer_pre */ -	0xf510f7f0, -	0xf5069221, -	0xf4062b21, -/* 0x085a: ctx_xfer_pre_load */ -	0xf7f01c11, -	0x5121f502, -	0x6021f506, -	0x7221f506, -	0xf5f4bd06, -	0xf5065121, -/* 0x0873: ctx_xfer_exec */ -	0x9806b221, -	0x27f11601, -	0x24b60414, -	0x0020d006, -	0xa500e7f1, -	0xb941e3f0, -	0x21f4021f, -	0x04e0b68d, -	0xf001fcf0, -	0x24b6022c, -	0x05f2fd01, -	0xf18d21f4, -	0xf04afc17, -	0x27f00213, -	0x0012d00c, -	0x021521f5, -	0x47fc27f1, -	0xd00223f0, -	0x2cf00020, +/* 0x0a20: ctx_mmio_done */ +	0xf1160398, +	0xf0810007, +	0x03d00203, +	0x8004bd00, +	0x17f14000, +	0x13f00100, +	0x0601fa06, +	0x00f803f8, +/* 0x0a40: ctx_xfer */ +	0xf104e7f0, +	0xf0020007, +	0x0ed00303, +/* 0x0a4f: ctx_xfer_idle */ +	0xf104bd00, +	0xf00000e7, +	0xeecf03e3, +	0x00e4f100, +	0xf21bf420, +	0xf40611f4, +/* 0x0a66: ctx_xfer_pre */ +	0xf7f01102, +	0x6c21f510, +	0xd721f508, +	0x1c11f407, +/* 0x0a74: ctx_xfer_pre_load */ +	0xf502f7f0, +	0xf5080d21, +	0xf5081f21, +	0xbd083421, +	0x0d21f5f4, +	0xb221f508, +/* 0x0a8d: ctx_xfer_exec */ +	0x16019808, +	0x07f124bd, +	0x03f00500, +	0x0002d001, +	0x1fb904bd, +	0x00e7f102, +	0x41e3f0a5, +	0xf09d21f4, +	0x2cf001fc, +	0x0124b602, +	0xb905f2fd, +	0xe7f102ff, +	0xe3f0a504, +	0x9d21f441, +	0x026a21f5, +	0x07f124bd, +	0x03f047fc, +	0x0002d002, +	0x2cf004bd,  	0x0320b601, -	0xf00012d0, -	0xa5f001ac, -	0x00b7f006, -	0x98000c98, -	0xe7f0010d, -	0x6621f500, -	0x08a7f001, -	0x010921f5, -	0x021521f5, -	0xf02201f4, -	0x21f40ca7, -	0x1017f1c9, -	0x0614b60a, -	0xd00527f0, -/* 0x08fa: ctx_xfer_post_save_wait */ -	0x12cf0012, -	0x0522fd00, -	0xf4fa1bf4, -/* 0x0906: ctx_xfer_post */ -	0xf7f03202, -	0x5121f502, -	0xf5f4bd06, -	0xf5069221, -	0xf5023421, -	0xbd066021, -	0x5121f5f4, -	0x1011f406, -	0xfd400198, -	0x0bf40511, -	0xe521f507, -/* 0x0931: ctx_xfer_no_post_mmio */ -	0x4321f507, -/* 0x0935: ctx_xfer_done */ -	0x0000f806, -	0x00000000, -	0x00000000, -	0x00000000, -	0x00000000, -	0x00000000, +	0x4afc07f1, +	0xd00203f0, +	0x04bd0002, +	0xf001acf0, +	0xb7f006a5, +	0x000c9800, +	0xf0010d98, +	0x21f500e7, +	0xa7f0016f, +	0x1021f508, +	0x5e21f501, +	0x1301f402, +	0xf40ca7f0, +	0xf7f0d021, +	0x9421f505, +	0x3202f408, +/* 0x0b1c: ctx_xfer_post */ +	0xf502f7f0, +	0xbd080d21, +	0x6c21f5f4, +	0x7f21f508, +	0x1f21f502, +	0xf5f4bd08, +	0xf4080d21, +	0x01981011, +	0x0511fd40, +	0xf5070bf4, +/* 0x0b47: ctx_xfer_no_post_mmio */ +	0xf509eb21, +/* 0x0b4b: ctx_xfer_done */ +	0xf807fc21,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h index eb7bc0e9576..51c3797d853 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnve0.fuc.h @@ -206,14 +206,14 @@ uint32_t nve0_grhub_data[] = {  };  uint32_t nve0_grhub_code[] = { -	0x031b0ef5, +	0x039b0ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -237,184 +237,214 @@ uint32_t nve0_grhub_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f00f00, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f00f00, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f00f,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf00f0007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f00f00, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x0f0007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -428,7 +458,7 @@ uint32_t nve0_grhub_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0x07f100f8,  	0x03f00500,  	0x000fd002, @@ -436,82 +466,117 @@ uint32_t nve0_grhub_code[] = {  	0x0007f101,  	0x0303f007,  	0xbd000fd0, -/* 0x031b: init */ +/* 0x039b: init */  	0xbd00f804, -	0x0004fe04, -	0xf10007fe, -	0xf0120017, -	0x12d00227, -	0xb117f100, -	0x0010fe05, -	0x040017f1, -	0xf1c010d0, -	0xb6040437, -	0x27f10634, -	0x32d02003, -	0x0427f100, -	0x0132d020, +	0x0007fe04, +	0x420017f1, +	0xcf0013f0, +	0x11e70011, +	0x14b60109, +	0x0014fe08, +	0xf10227f0, +	0xf0120007, +	0x02d00003, +	0xf104bd00, +	0xfe06c817, +	0x24bd0010, +	0x070007f1, +	0xd00003f0, +	0x04bd0002, +	0x200327f1, +	0x010007f1, +	0xd00103f0, +	0x04bd0002, +	0x200427f1, +	0x010407f1, +	0xd00103f0, +	0x04bd0002,  	0x200b27f1, -	0xf10232d0, -	0xd0200c27, -	0x27f10732, -	0x24b60c24, -	0x0003b906, -	0xf10023d0, +	0x010807f1, +	0xd00103f0, +	0x04bd0002, +	0x200c27f1, +	0x011c07f1, +	0xd00103f0, +	0x04bd0002, +	0xf1010392, +	0xf0090007, +	0x03d00303, +	0xf104bd00,  	0xf0870427, -	0x12d00023, -	0x0012b700, -	0x0427f001, -	0xf40012d0, -	0xe7f11031, -	0xe3f09604, -	0x6821f440, -	0x8090f1c7, -	0xf4f00301, -	0x020f801f, -	0xbb0117f0, -	0x12b6041f, -	0x0c27f101, -	0x0624b604, -	0xd00021d0, -	0x17f14021, -	0x0e980100, -	0x010f9800, -	0x014721f5, -	0x070037f1, -	0x950634b6, -	0x34d00814, -	0x4034d000, -	0x130030b7, -	0xb6001fbb, -	0x3fd002f5, -	0x0815b600, -	0xb60110b6, -	0x1fb90814, -	0x7121f502, -	0x001fbb02, -	0xf1020398, -	0xf0200047, -/* 0x03f6: init_gpc */ -	0x4ea05043, -	0x1fb90804, -	0x8d21f402, -	0x010c4ea0, -	0x21f4f4bd, -	0x044ea08d, -	0x8d21f401, -	0x01004ea0, -	0xf402f7f0, -	0x4ea08d21, -/* 0x041e: init_gpc_wait */ -	0x21f40800, -	0x1fffc868, -	0xa0fa0bf4, -	0xf408044e, -	0x1fbb6821, -	0x0040b700, -	0x0132b680, -	0xf1be1bf4, +	0x07f10023, +	0x03f00400, +	0x0002d000, +	0x27f004bd, +	0x0007f104, +	0x0003f003, +	0xbd0002d0, +	0x1031f404, +	0x9604e7f1, +	0xf440e3f0, +	0xfeb96821, +	0x90f1c702, +	0xf0030180, +	0x0f801ff4, +	0x0117f002, +	0xb6041fbb, +	0x07f10112, +	0x03f00300, +	0x0001d001, +	0x07f104bd, +	0x03f00400, +	0x0001d001, +	0x17f104bd, +	0xf7f00100, +	0xd721f502, +	0xe921f507, +	0x10f7f007, +	0x083621f5, +	0x98000e98, +	0x21f5010f, +	0x14950150, +	0x0007f108, +	0x0103f0c0, +	0xbd0004d0, +	0x0007f104, +	0x0103f0c1, +	0xbd0004d0, +	0x0030b704, +	0x001fbb13, +	0xf102f5b6, +	0xf0d30007, +	0x0fd00103, +	0xb604bd00, +	0x10b60815, +	0x0814b601, +	0xf5021fb9, +	0xbb02d321, +	0x0398001f, +	0x0047f102, +	0x5043f020, +/* 0x04f4: init_gpc */ +	0x08044ea0, +	0xf4021fb9, +	0x4ea09d21, +	0xf4bd010c, +	0xa09d21f4, +	0xf401044e, +	0x4ea09d21, +	0xf7f00100, +	0x9d21f402, +	0x08004ea0, +/* 0x051c: init_gpc_wait */ +	0xc86821f4, +	0x0bf41fff, +	0x044ea0fa, +	0x6821f408, +	0xb7001fbb, +	0xb6800040, +	0x1bf40132, +	0x00f7f0be, +	0x083621f5, +	0xf500f7f0, +	0xf107d721,  	0xf0010007,  	0x01d00203,  	0xbd04bd00, @@ -519,340 +584,401 @@ uint32_t nve0_grhub_code[] = {  	0x080007f1,  	0xd00203f0,  	0x04bd0001, -/* 0x0458: main */ +/* 0x0564: main */  	0xf40031f4,  	0xd7f00028,  	0x3921f410,  	0xb1f401f4,  	0xf54001e4, -	0xbd00de1b, +	0xbd00e91b,  	0x0499f094,  	0x0f0007f1,  	0xd00203f0,  	0x04bd0009, -	0x0b0017f1, -	0xcf0614b6, -	0x11cf4012, -	0x1f13c800, -	0x00870bf5, -	0xf41f23c8, -	0x20f9620b, -	0xbd0212b9, -	0x0799f094, -	0x0f0007f1, -	0xd00203f0, -	0x04bd0009, -	0xf40132f4, -	0x21f50231, -	0x94bd0801, +	0xc00017f1, +	0xcf0213f0, +	0x27f10011, +	0x23f0c100, +	0x0022cf02, +	0xf51f13c8, +	0xc800890b, +	0x0bf41f23, +	0xb920f962, +	0x94bd0212,  	0xf10799f0, -	0xf0170007, +	0xf00f0007,  	0x09d00203, -	0xfc04bd00, -	0xf094bd20, -	0x07f10699, -	0x03f00f00, -	0x0009d002, -	0x31f404bd, -	0x0121f501, -	0xf094bd08, -	0x07f10699, +	0xf404bd00, +	0x31f40132, +	0x0221f502, +	0xf094bd0a, +	0x07f10799,  	0x03f01700,  	0x0009d002, -	0x0ef404bd, -/* 0x04f9: chsw_prev_no_next */ -	0xb920f931, -	0x32f40212, -	0x0232f401, -	0x080121f5, -	0x17f120fc, -	0x14b60b00, -	0x0012d006, -/* 0x0517: chsw_no_prev */ -	0xc8130ef4, -	0x0bf41f23, -	0x0131f40d, -	0xf50232f4, -/* 0x0527: chsw_done */ -	0xf1080121, -	0xb60b0c17, -	0x27f00614, -	0x0012d001, +	0x20fc04bd,  	0x99f094bd, -	0x0007f104, +	0x0007f106, +	0x0203f00f, +	0xbd0009d0, +	0x0131f404, +	0x0a0221f5, +	0x99f094bd, +	0x0007f106,  	0x0203f017,  	0xbd0009d0, -	0x130ef504, -/* 0x0549: main_not_ctx_switch */ -	0x01e4b0ff, -	0xb90d1bf4, -	0x21f502f2, -	0x0ef40795, -/* 0x0559: main_not_ctx_chan */ -	0x02e4b046, -	0xbd321bf4, -	0x0799f094, -	0x0f0007f1, +	0x330ef404, +/* 0x060c: chsw_prev_no_next */ +	0x12b920f9, +	0x0132f402, +	0xf50232f4, +	0xfc0a0221, +	0x0007f120, +	0x0203f0c0, +	0xbd0002d0, +	0x130ef404, +/* 0x062c: chsw_no_prev */ +	0xf41f23c8, +	0x31f40d0b, +	0x0232f401, +	0x0a0221f5, +/* 0x063c: chsw_done */ +	0xf10127f0, +	0xf0c30007, +	0x02d00203, +	0xbd04bd00, +	0x0499f094, +	0x170007f1,  	0xd00203f0,  	0x04bd0009, -	0xf40132f4, -	0x21f50232, -	0x94bd0801, +	0xff080ef5, +/* 0x0660: main_not_ctx_switch */ +	0xf401e4b0, +	0xf2b90d1b, +	0x9a21f502, +	0x460ef409, +/* 0x0670: main_not_ctx_chan */ +	0xf402e4b0, +	0x94bd321b,  	0xf10799f0, -	0xf0170007, +	0xf00f0007,  	0x09d00203,  	0xf404bd00, -/* 0x058e: main_not_ctx_save */ -	0xef94110e, -	0x01f5f010, -	0x02fe21f5, -	0xfec00ef5, -/* 0x059c: main_done */ -	0x29f024bd, -	0x0007f11f, -	0x0203f008, -	0xbd0002d0, -	0xab0ef504, -/* 0x05b1: ih */ -	0xfe80f9fe, -	0x80f90188, -	0xa0f990f9, -	0xd0f9b0f9, -	0xf0f9e0f9, -	0x0acf04bd, -	0x04abc480, -	0xf11d0bf4, -	0xf01900b7, -	0xbecf10d7, -	0x00bfcf40, +	0x32f40132, +	0x0221f502, +	0xf094bd0a, +	0x07f10799, +	0x03f01700, +	0x0009d002, +	0x0ef404bd, +/* 0x06a5: main_not_ctx_save */ +	0x10ef9411, +	0xf501f5f0, +	0xf5037e21, +/* 0x06b3: main_done */ +	0xbdfeb50e, +	0x1f29f024, +	0x080007f1, +	0xd00203f0, +	0x04bd0002, +	0xfea00ef5, +/* 0x06c8: ih */ +	0x88fe80f9, +	0xf980f901, +	0xf9a0f990, +	0xf9d0f9b0, +	0xbdf0f9e0, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x10d7f030, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00,  	0xb70421f4,  	0xf00400b0, -	0xbed001e7, -/* 0x05e9: ih_no_fifo */ -	0x00abe400, -	0x0d0bf401, -	0xf110d7f0, -	0xf44001e7, -/* 0x05fa: ih_no_ctxsw */ -	0xb7f10421, -	0xb0bd0104, -	0xf4b4abff, -	0xa7f10d0b, -	0xa4b60c1c, -	0x00abd006, -/* 0x0610: ih_no_other */ -	0xfc400ad0, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x071a: ih_no_fifo */ +	0xabe404bd, +	0x0bf40100, +	0x10d7f00d, +	0x4001e7f1, +/* 0x072b: ih_no_ctxsw */ +	0xe40421f4, +	0xf40400ab, +	0xe7f16c0b, +	0xe3f00708, +	0x6821f440, +	0xf102ffb9, +	0xf0040007, +	0x0fd00203, +	0xf104bd00, +	0xf00704e7, +	0x21f440e3, +	0x02ffb968, +	0x030007f1, +	0xd00203f0, +	0x04bd000f, +	0x9450fec7, +	0xf7f102ee, +	0xf3f00700, +	0x00efbb40, +	0xf16821f4, +	0xf0020007, +	0x0fd00203, +	0xf004bd00, +	0x21f503f7, +	0xb7f1037e, +	0xbfb90100, +	0x44e7f102, +	0x40e3f001, +/* 0x079b: ih_no_fwmthd */ +	0xf19d21f4, +	0xbd0504b7, +	0xb4abffb0, +	0xf10f0bf4, +	0xf0070007, +	0x0bd00303, +/* 0x07b3: ih_no_other */ +	0xf104bd00, +	0xf0010007, +	0x0ad00003, +	0xfc04bd00,  	0xfce0fcf0,  	0xfcb0fcd0,  	0xfc90fca0,  	0x0088fe80,  	0x32f480fc, -/* 0x062b: ctx_4170s */ -	0xf101f800, -	0xf04170e7, -	0xf5f040e3, -	0x8d21f410, -/* 0x063a: ctx_4170w */ +/* 0x07d7: ctx_4170s */ +	0xf001f800, +	0xffb910f5, +	0x70e7f102, +	0x40e3f041, +	0xf89d21f4, +/* 0x07e9: ctx_4170w */ +	0x70e7f100, +	0x40e3f041, +	0xb96821f4, +	0xf4f002ff, +	0xf01bf410, +/* 0x07fe: ctx_redswitch */  	0xe7f100f8, -	0xe3f04170, -	0x6821f440, -	0xf410f4f0, +	0xe5f00200, +	0x20e5f040, +	0xf110e5f0, +	0xf0850007, +	0x0ed00103, +	0xf004bd00, +/* 0x081a: ctx_redswitch_delay */ +	0xf2b608f7, +	0xfd1bf401, +	0x0400e5f1, +	0x0100e5f1, +	0x850007f1, +	0xd00103f0, +	0x04bd000e, +/* 0x0836: ctx_86c */ +	0x07f100f8, +	0x03f01b00, +	0x000fd002, +	0xffb904bd, +	0x14e7f102, +	0x40e3f08a, +	0xb99d21f4, +	0xe7f102ff, +	0xe3f0a86c, +	0x9d21f441, +/* 0x085e: ctx_mem */ +	0x07f100f8, +	0x03f08400, +	0x000fd002, +/* 0x086a: ctx_mem_wait */ +	0xf7f104bd, +	0xf3f08400, +	0x00ffcf02, +	0xf405fffd,  	0x00f8f31b, -/* 0x064c: ctx_redswitch */ -	0x0614e7f1, -	0xf106e4b6, -	0xd00270f7, -	0xf7f000ef, -/* 0x065d: ctx_redswitch_delay */ -	0x01f2b608, -	0xf1fd1bf4, -	0xd00770f7, -	0x00f800ef, -/* 0x066c: ctx_86c */ -	0x086ce7f1, -	0xd006e4b6, -	0xe7f100ef, -	0xe3f08a14, -	0x8d21f440, -	0xa86ce7f1, -	0xf441e3f0, -	0x00f88d21, -/* 0x068c: ctx_load */ +/* 0x087c: ctx_load */  	0x99f094bd,  	0x0007f105,  	0x0203f00f,  	0xbd0009d0,  	0x0ca7f004, -	0xf1c921f4, -	0xb60a2417, -	0x10d00614, -	0x0037f100, -	0x0634b60b, -	0xf14032d0, -	0xb60a0c17, -	0x47f00614, -	0x0012d007, -/* 0x06c7: ctx_chan_wait_0 */ -	0xcf4014d0, -	0x44f04014, -	0xfa1bf41f, -	0xfe0032d0, -	0x2af0000b, -	0x0424b61f, -	0xbd0220b6, +	0xbdd021f4, +	0x0007f1f4, +	0x0203f089, +	0xbd000fd0, +	0x0007f104, +	0x0203f0c1, +	0xbd0002d0, +	0x0007f104, +	0x0203f083, +	0xbd0002d0, +	0x07f7f004, +	0x085e21f5, +	0xc00007f1, +	0xd00203f0, +	0x04bd0002, +	0xf0000bfe, +	0x24b61f2a, +	0x0220b604, +	0x99f094bd, +	0x0007f108, +	0x0203f00f, +	0xbd0009d0, +	0x0007f104, +	0x0203f081, +	0xbd0002d0, +	0x0027f104, +	0x0023f100, +	0x0225f080, +	0x880007f1, +	0xd00203f0, +	0x04bd0002, +	0xf11017f0, +	0xf0020027, +	0x12fa0223, +	0xbd03f805,  	0x0899f094, -	0x0f0007f1, +	0x170007f1,  	0xd00203f0,  	0x04bd0009, -	0x0a0417f1, -	0xd00614b6, -	0x17f10012, -	0x14b60a20, -	0x0227f006, -	0x800023f1, -	0xf00012d0, -	0x27f11017, -	0x23f00200, -	0x0512fa02, -	0x94bd03f8, -	0xf10899f0, -	0xf0170007, +	0xb6810198, +	0x02981814, +	0x0825b680, +	0x800512fd, +	0x94bd1601, +	0xf10999f0, +	0xf00f0007,  	0x09d00203, -	0x9804bd00, -	0x14b68101, -	0x80029818, -	0xfd0825b6, -	0x01800512, -	0xf094bd16, -	0x07f10999, -	0x03f00f00, -	0x0009d002, -	0x27f104bd, -	0x24b60a04, -	0x0021d006, -	0xf10127f0, -	0xb60a2017, -	0x12d00614, -	0x0017f100, -	0x0613f001, -	0xf80501fa, -	0xf094bd03, -	0x07f10999, -	0x03f01700, -	0x0009d002, -	0x94bd04bd, -	0xf10599f0, +	0xf104bd00, +	0xf0810007, +	0x01d00203, +	0xf004bd00, +	0x07f10127, +	0x03f08800, +	0x0002d002, +	0x17f104bd, +	0x13f00100, +	0x0501fa06, +	0x94bd03f8, +	0xf10999f0,  	0xf0170007,  	0x09d00203, -	0xf804bd00, -/* 0x0795: ctx_chan */ -	0x8c21f500, -	0x0ca7f006, -	0xf1c921f4, -	0xb60a1017, -	0x27f00614, -	0x0012d005, -/* 0x07ac: ctx_chan_wait */ -	0xfd0012cf, -	0x1bf40522, -/* 0x07b7: ctx_mmio_exec */ -	0x9800f8fa, -	0x27f14103, -	0x24b60a04, -	0x0023d006, -/* 0x07c6: ctx_mmio_loop */ +	0xbd04bd00, +	0x0599f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x099a: ctx_chan */ +	0x21f500f8, +	0xa7f0087c, +	0xd021f40c, +	0xf505f7f0, +	0xf8085e21, +/* 0x09ad: ctx_mmio_exec */ +	0x41039800, +	0x810007f1, +	0xd00203f0, +	0x04bd0003, +/* 0x09be: ctx_mmio_loop */  	0x34c434bd,  	0x0f1bf4ff,  	0x020057f1,  	0xfa0653f0,  	0x03f80535, -/* 0x07d8: ctx_mmio_pull */ +/* 0x09d0: ctx_mmio_pull */  	0x98804e98,  	0x21f4814f, -	0x0830b68d, +	0x0830b69d,  	0xf40112b6, -/* 0x07ea: ctx_mmio_done */ +/* 0x09e2: ctx_mmio_done */  	0x0398df1b, -	0x0023d016, -	0xf1400080, -	0xf0010017, -	0x01fa0613, -	0xf803f806, -/* 0x0801: ctx_xfer */ -	0x00f7f100, -	0x06f4b60c, -	0xd004e7f0, -/* 0x080e: ctx_xfer_idle */ -	0xfecf80fe, -	0x00e4f100, -	0xf91bf420, -	0xf40611f4, -/* 0x081e: ctx_xfer_pre */ -	0xf7f00d02, -	0x6c21f510, -	0x1c11f406, -/* 0x0828: ctx_xfer_pre_load */ -	0xf502f7f0, -	0xf5062b21, -	0xf5063a21, -	0xbd064c21, -	0x2b21f5f4, -	0x8c21f506, -/* 0x0841: ctx_xfer_exec */ -	0x16019806, -	0x041427f1, -	0xd00624b6, -	0xe7f10020, -	0xe3f0a500, -	0x021fb941, -	0xb68d21f4, -	0xfcf004e0, -	0x022cf001, -	0xfd0124b6, -	0x21f405f2, -	0xfc17f18d, -	0x0213f04a, -	0xd00c27f0, -	0x21f50012, -	0x27f10215, -	0x23f047fc, -	0x0020d002, +	0x0007f116, +	0x0203f081, +	0xbd0003d0, +	0x40008004, +	0x010017f1, +	0xfa0613f0, +	0x03f80601, +/* 0x0a02: ctx_xfer */ +	0xe7f000f8, +	0x0007f104, +	0x0303f002, +	0xbd000ed0, +/* 0x0a11: ctx_xfer_idle */ +	0x00e7f104, +	0x03e3f000, +	0xf100eecf, +	0xf42000e4, +	0x11f4f21b, +	0x0d02f406, +/* 0x0a28: ctx_xfer_pre */ +	0xf510f7f0, +	0xf4083621, +/* 0x0a32: ctx_xfer_pre_load */ +	0xf7f01c11, +	0xd721f502, +	0xe921f507, +	0xfe21f507, +	0xf5f4bd07, +	0xf507d721, +/* 0x0a4b: ctx_xfer_exec */ +	0x98087c21, +	0x24bd1601, +	0x050007f1, +	0xd00103f0, +	0x04bd0002, +	0xf1021fb9, +	0xf0a500e7, +	0x21f441e3, +	0x01fcf09d, +	0xb6022cf0, +	0xf2fd0124, +	0x02ffb905, +	0xa504e7f1, +	0xf441e3f0, +	0x21f59d21, +	0x24bd026a, +	0x47fc07f1, +	0xd00203f0, +	0x04bd0002,  	0xb6012cf0, -	0x12d00320, -	0x01acf000, -	0xf006a5f0, -	0x0c9800b7, -	0x010d9800, -	0xf500e7f0, -	0xf0016621, -	0x21f508a7, -	0x21f50109, -	0x01f40215, -	0x0ca7f022, -	0xf1c921f4, -	0xb60a1017, -	0x27f00614, -	0x0012d005, -/* 0x08c8: ctx_xfer_post_save_wait */ -	0xfd0012cf, -	0x1bf40522, -	0x2e02f4fa, -/* 0x08d4: ctx_xfer_post */ -	0xf502f7f0, -	0xbd062b21, -	0x6c21f5f4, -	0x3421f506, -	0x3a21f502, -	0xf5f4bd06, -	0xf4062b21, -	0x01981011, -	0x0511fd40, -	0xf5070bf4, -/* 0x08ff: ctx_xfer_no_post_mmio */ -/* 0x08ff: ctx_xfer_done */ -	0xf807b721, -	0x00000000, -	0x00000000, +	0x07f10320, +	0x03f04afc, +	0x0002d002, +	0xacf004bd, +	0x06a5f001, +	0x9800b7f0, +	0x0d98000c, +	0x00e7f001, +	0x016f21f5, +	0xf508a7f0, +	0xf5011021, +	0xf4025e21, +	0xa7f01301, +	0xd021f40c, +	0xf505f7f0, +	0xf4085e21, +/* 0x0ada: ctx_xfer_post */ +	0xf7f02e02, +	0xd721f502, +	0xf5f4bd07, +	0xf5083621, +	0xf5027f21, +	0xbd07e921, +	0xd721f5f4, +	0x1011f407, +	0xfd400198, +	0x0bf40511, +	0xad21f507, +/* 0x0b05: ctx_xfer_no_post_mmio */ +/* 0x0b05: ctx_xfer_done */ +	0x0000f809,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h index 438506d1474..a0af4b703a8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvf0.fuc.h @@ -206,14 +206,14 @@ uint32_t nvf0_grhub_data[] = {  };  uint32_t nvf0_grhub_code[] = { -	0x031b0ef5, +	0x039b0ef5,  /* 0x0004: queue_put */  	0x9800d898,  	0x86f001d9,  	0x0489b808,  	0xf00c1bf4,  	0x21f502f7, -	0x00f802fe, +	0x00f8037e,  /* 0x001c: queue_put_next */  	0xb60798c4,  	0x8dbb0384, @@ -237,184 +237,214 @@ uint32_t nvf0_grhub_code[] = {  /* 0x0066: queue_get_done */  	0x00f80132,  /* 0x0068: nv_rd32 */ -	0x0728b7f1, -	0xb906b4b6, -	0xc9f002ec, -	0x00bcd01f, -/* 0x0078: nv_rd32_wait */ -	0xc800bccf, -	0x1bf41fcc, -	0x06a7f0fa, -	0x010921f5, -	0xf840bfcf, -/* 0x008d: nv_wr32 */ -	0x28b7f100, -	0x06b4b607, -	0xb980bfd0, -	0xc9f002ec, -	0x1ec9f01f, -/* 0x00a3: nv_wr32_wait */ -	0xcf00bcd0, -	0xccc800bc, -	0xfa1bf41f, -/* 0x00ae: watchdog_reset */ -	0x87f100f8, -	0x84b60430, -	0x1ff9f006, -	0xf8008fd0, -/* 0x00bd: watchdog_clear */ -	0x3087f100, -	0x0684b604, -	0xf80080d0, -/* 0x00c9: wait_donez */ -	0xf094bd00, -	0x07f10099, -	0x03f03700, -	0x0009d002, -	0x07f104bd, -	0x03f00600, -	0x000ad002, -/* 0x00e6: wait_donez_ne */ -	0x87f104bd, -	0x83f00000, -	0x0088cf01, -	0xf4888aff, -	0x94bdf31b, -	0xf10099f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0109: wait_doneo */ -	0xf094bd00, +	0xf002ecb9, +	0x07f11fc9, +	0x03f0ca00, +	0x000cd001, +/* 0x007a: nv_rd32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0xa7f0f31b, +	0x1021f506, +	0x00f7f101, +	0x01f3f0cb, +	0xf800ffcf, +/* 0x009d: nv_wr32 */ +	0x0007f100, +	0x0103f0cc, +	0xbd000fd0, +	0x02ecb904, +	0xf01fc9f0, +	0x07f11ec9, +	0x03f0ca00, +	0x000cd001, +/* 0x00be: nv_wr32_wait */ +	0xc7f104bd, +	0xc3f0ca00, +	0x00cccf01, +	0xf41fccc8, +	0x00f8f31b, +/* 0x00d0: wait_donez */ +	0x99f094bd, +	0x0007f100, +	0x0203f037, +	0xbd0009d0, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x00ed: wait_donez_ne */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x1bf4888a, +	0xf094bdf3,  	0x07f10099, -	0x03f03700, +	0x03f01700,  	0x0009d002, -	0x87f104bd, -	0x84b60818, -	0x008ad006, -/* 0x0124: wait_doneo_e */ -	0x040087f1, -	0xcf0684b6, -	0x8aff0088, -	0xf30bf488, +	0x00f804bd, +/* 0x0110: wait_doneo */  	0x99f094bd,  	0x0007f100, -	0x0203f017, +	0x0203f037,  	0xbd0009d0, -/* 0x0147: mmctx_size */ -	0xbd00f804, -/* 0x0149: nv_mmctx_size_loop */ -	0x00e89894, -	0xb61a85b6, -	0x84b60180, -	0x0098bb02, -	0xb804e0b6, -	0x1bf404ef, -	0x029fb9eb, -/* 0x0166: mmctx_xfer */ -	0x94bd00f8, -	0xf10199f0, -	0xf0370007, -	0x09d00203, -	0xf104bd00, -	0xb6071087, -	0x94bd0684, -	0xf405bbfd, -	0x8bd0090b, -	0x0099f000, -/* 0x018c: mmctx_base_disabled */ -	0xf405eefd, -	0x8ed00c0b, -	0xc08fd080, -/* 0x019b: mmctx_multi_disabled */ -	0xb70199f0, -	0xc8010080, +	0x0007f104, +	0x0203f006, +	0xbd000ad0, +/* 0x012d: wait_doneo_e */ +	0x0087f104, +	0x0183f000, +	0xff0088cf, +	0x0bf4888a, +	0xf094bdf3, +	0x07f10099, +	0x03f01700, +	0x0009d002, +	0x00f804bd, +/* 0x0150: mmctx_size */ +/* 0x0152: nv_mmctx_size_loop */ +	0xe89894bd, +	0x1a85b600, +	0xb60180b6, +	0x98bb0284, +	0x04e0b600, +	0xf404efb8, +	0x9fb9eb1b, +/* 0x016f: mmctx_xfer */ +	0xbd00f802, +	0x0199f094, +	0x370007f1, +	0xd00203f0, +	0x04bd0009, +	0xbbfd94bd, +	0x120bf405, +	0xc40007f1, +	0xd00103f0, +	0x04bd000b, +/* 0x0197: mmctx_base_disabled */ +	0xfd0099f0, +	0x0bf405ee, +	0x0007f11e, +	0x0103f0c6, +	0xbd000ed0, +	0x0007f104, +	0x0103f0c7, +	0xbd000fd0, +	0x0199f004, +/* 0x01b8: mmctx_multi_disabled */ +	0xb600abc8, +	0xb9f010b4, +	0x01aec80c, +	0xfd11e4b6, +	0x07f105be, +	0x03f0c500, +	0x000bd001, +/* 0x01d6: mmctx_exec_loop */ +/* 0x01d6: mmctx_wait_free */ +	0xe7f104bd, +	0xe3f0c500, +	0x00eecf01, +	0xf41fe4f0, +	0xce98f30b, +	0x05e9fd00, +	0xc80007f1, +	0xd00103f0, +	0x04bd000e, +	0xb804c0b6, +	0x1bf404cd, +	0x02abc8d8, +/* 0x0207: mmctx_fini_wait */ +	0xf11f1bf4, +	0xf0c500b7, +	0xbbcf01b3, +	0x1fb4f000, +	0xf410b4b0, +	0xa7f0f01b, +	0xd021f405, +/* 0x0223: mmctx_stop */ +	0xc82b0ef4,  	0xb4b600ab,  	0x0cb9f010, -	0xb601aec8, -	0xbefd11e4, -	0x008bd005, -/* 0x01b4: mmctx_exec_loop */ -/* 0x01b4: mmctx_wait_free */ -	0xf0008ecf, -	0x0bf41fe4, -	0x00ce98fa, -	0xd005e9fd, -	0xc0b6c08e, -	0x04cdb804, -	0xc8e81bf4, -	0x1bf402ab, -/* 0x01d5: mmctx_fini_wait */ -	0x008bcf18, -	0xb01fb4f0, -	0x1bf410b4, -	0x02a7f0f7, -	0xf4c921f4, -/* 0x01ea: mmctx_stop */ -	0xabc81b0e, -	0x10b4b600, -	0xf00cb9f0, -	0x8bd012b9, -/* 0x01f9: mmctx_stop_wait */ -	0x008bcf00, -	0xf412bbc8, -/* 0x0202: mmctx_done */ -	0x94bdfa1b, -	0xf10199f0, -	0xf0170007, -	0x09d00203, -	0xf804bd00, -/* 0x0215: strand_wait */ -	0xf0a0f900, -	0x21f402a7, -	0xf8a0fcc9, -/* 0x0221: strand_pre */ -	0xfc87f100, -	0x0283f04a, -	0xd00c97f0, -	0x21f50089, -	0x00f80215, -/* 0x0234: strand_post */ -	0x4afc87f1, -	0xf00283f0, -	0x89d00d97, -	0x1521f500, -/* 0x0247: strand_set */ -	0xf100f802, -	0xf04ffca7, -	0xaba202a3, -	0xc7f00500, -	0x00acd00f, -	0xd00bc7f0, -	0x21f500bc, -	0xaed00215, -	0x0ac7f000, -	0xf500bcd0, -	0xf8021521, -/* 0x0271: strand_ctx_init */ -	0xf094bd00, -	0x07f10399, -	0x03f03700, +	0xf112b9f0, +	0xf0c50007, +	0x0bd00103, +/* 0x023b: mmctx_stop_wait */ +	0xf104bd00, +	0xf0c500b7, +	0xbbcf01b3, +	0x12bbc800, +/* 0x024b: mmctx_done */ +	0xbdf31bf4, +	0x0199f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x025e: strand_wait */ +	0xa0f900f8, +	0xf402a7f0, +	0xa0fcd021, +/* 0x026a: strand_pre */ +	0x97f000f8, +	0xfc07f10c, +	0x0203f04a, +	0xbd0009d0, +	0x5e21f504, +/* 0x027f: strand_post */ +	0xf000f802, +	0x07f10d97, +	0x03f04afc,  	0x0009d002,  	0x21f504bd, -	0xe7f00221, -	0x4721f503, -	0xfca7f102, -	0x02a3f046, -	0x0400aba0, -	0xf040a0d0, -	0xbcd001c7, -	0x1521f500, -	0x010c9202, -	0xf000acd0, -	0xbcd002c7, -	0x1521f500, -	0x3421f502, -	0x8087f102, -	0x0684b608, -	0xb70089cf, -	0x95220080, -/* 0x02ca: ctx_init_strand_loop */ +	0x00f8025e, +/* 0x0294: strand_set */ +	0xf10fc7f0, +	0xf04ffc07, +	0x0cd00203, +	0xf004bd00, +	0x07f10bc7, +	0x03f04afc, +	0x000cd002, +	0x07f104bd, +	0x03f04ffc, +	0x000ed002, +	0xc7f004bd, +	0xfc07f10a, +	0x0203f04a, +	0xbd000cd0, +	0x5e21f504, +/* 0x02d3: strand_ctx_init */ +	0xbd00f802, +	0x0399f094, +	0x370007f1, +	0xd00203f0, +	0x04bd0009, +	0x026a21f5, +	0xf503e7f0, +	0xbd029421, +	0xfc07f1c4, +	0x0203f047, +	0xbd000cd0, +	0x01c7f004, +	0x4afc07f1, +	0xd00203f0, +	0x04bd000c, +	0x025e21f5, +	0xf1010c92, +	0xf046fc07, +	0x0cd00203, +	0xf004bd00, +	0x07f102c7, +	0x03f04afc, +	0x000cd002, +	0x21f504bd, +	0x21f5025e, +	0x87f1027f, +	0x83f04200, +	0x0097f102, +	0x0293f020, +	0x950099cf, +/* 0x034a: ctx_init_strand_loop */  	0x8ed008fe,  	0x408ed000,  	0xb6808acf, @@ -428,7 +458,7 @@ uint32_t nvf0_grhub_code[] = {  	0x170007f1,  	0xd00203f0,  	0x04bd0009, -/* 0x02fe: error */ +/* 0x037e: error */  	0x07f100f8,  	0x03f00500,  	0x000fd002, @@ -436,82 +466,117 @@ uint32_t nvf0_grhub_code[] = {  	0x0007f101,  	0x0303f007,  	0xbd000fd0, -/* 0x031b: init */ +/* 0x039b: init */  	0xbd00f804, -	0x0004fe04, -	0xf10007fe, -	0xf0120017, -	0x12d00227, -	0xb117f100, -	0x0010fe05, -	0x040017f1, -	0xf1c010d0, -	0xb6040437, -	0x27f10634, -	0x32d02003, -	0x0427f100, -	0x0132d020, +	0x0007fe04, +	0x420017f1, +	0xcf0013f0, +	0x11e70011, +	0x14b60109, +	0x0014fe08, +	0xf10227f0, +	0xf0120007, +	0x02d00003, +	0xf104bd00, +	0xfe06c817, +	0x24bd0010, +	0x070007f1, +	0xd00003f0, +	0x04bd0002, +	0x200327f1, +	0x010007f1, +	0xd00103f0, +	0x04bd0002, +	0x200427f1, +	0x010407f1, +	0xd00103f0, +	0x04bd0002,  	0x200b27f1, -	0xf10232d0, -	0xd0200c27, -	0x27f10732, -	0x24b60c24, -	0x0003b906, -	0xf10023d0, +	0x010807f1, +	0xd00103f0, +	0x04bd0002, +	0x200c27f1, +	0x011c07f1, +	0xd00103f0, +	0x04bd0002, +	0xf1010392, +	0xf0090007, +	0x03d00303, +	0xf104bd00,  	0xf0870427, -	0x12d00023, -	0x0012b700, -	0x0427f001, -	0xf40012d0, -	0xe7f11031, -	0xe3f09604, -	0x6821f440, -	0x8090f1c7, -	0xf4f00301, -	0x020f801f, -	0xbb0117f0, -	0x12b6041f, -	0x0c27f101, -	0x0624b604, -	0xd00021d0, -	0x17f14021, -	0x0e980100, -	0x010f9800, -	0x014721f5, -	0x070037f1, -	0x950634b6, -	0x34d00814, -	0x4034d000, -	0x130030b7, -	0xb6001fbb, -	0x3fd002f5, -	0x0815b600, -	0xb60110b6, -	0x1fb90814, -	0x7121f502, -	0x001fbb02, -	0xf1020398, -	0xf0200047, -/* 0x03f6: init_gpc */ -	0x4ea05043, -	0x1fb90804, -	0x8d21f402, -	0x010c4ea0, -	0x21f4f4bd, -	0x044ea08d, -	0x8d21f401, -	0x01004ea0, -	0xf402f7f0, -	0x4ea08d21, -/* 0x041e: init_gpc_wait */ -	0x21f40800, -	0x1fffc868, -	0xa0fa0bf4, -	0xf408044e, -	0x1fbb6821, -	0x0040b700, -	0x0132b680, -	0xf1be1bf4, +	0x07f10023, +	0x03f00400, +	0x0002d000, +	0x27f004bd, +	0x0007f104, +	0x0003f003, +	0xbd0002d0, +	0x1031f404, +	0x9604e7f1, +	0xf440e3f0, +	0xfeb96821, +	0x90f1c702, +	0xf0030180, +	0x0f801ff4, +	0x0117f002, +	0xb6041fbb, +	0x07f10112, +	0x03f00300, +	0x0001d001, +	0x07f104bd, +	0x03f00400, +	0x0001d001, +	0x17f104bd, +	0xf7f00100, +	0xd721f502, +	0xe921f507, +	0x10f7f007, +	0x083621f5, +	0x98000e98, +	0x21f5010f, +	0x14950150, +	0x0007f108, +	0x0103f0c0, +	0xbd0004d0, +	0x0007f104, +	0x0103f0c1, +	0xbd0004d0, +	0x0030b704, +	0x001fbb13, +	0xf102f5b6, +	0xf0d30007, +	0x0fd00103, +	0xb604bd00, +	0x10b60815, +	0x0814b601, +	0xf5021fb9, +	0xbb02d321, +	0x0398001f, +	0x0047f102, +	0x5043f020, +/* 0x04f4: init_gpc */ +	0x08044ea0, +	0xf4021fb9, +	0x4ea09d21, +	0xf4bd010c, +	0xa09d21f4, +	0xf401044e, +	0x4ea09d21, +	0xf7f00100, +	0x9d21f402, +	0x08004ea0, +/* 0x051c: init_gpc_wait */ +	0xc86821f4, +	0x0bf41fff, +	0x044ea0fa, +	0x6821f408, +	0xb7001fbb, +	0xb6800040, +	0x1bf40132, +	0x00f7f0be, +	0x083621f5, +	0xf500f7f0, +	0xf107d721,  	0xf0010007,  	0x01d00203,  	0xbd04bd00, @@ -519,340 +584,401 @@ uint32_t nvf0_grhub_code[] = {  	0x300007f1,  	0xd00203f0,  	0x04bd0001, -/* 0x0458: main */ +/* 0x0564: main */  	0xf40031f4,  	0xd7f00028,  	0x3921f410,  	0xb1f401f4,  	0xf54001e4, -	0xbd00de1b, +	0xbd00e91b,  	0x0499f094,  	0x370007f1,  	0xd00203f0,  	0x04bd0009, -	0x0b0017f1, -	0xcf0614b6, -	0x11cf4012, -	0x1f13c800, -	0x00870bf5, -	0xf41f23c8, -	0x20f9620b, -	0xbd0212b9, -	0x0799f094, -	0x370007f1, -	0xd00203f0, -	0x04bd0009, -	0xf40132f4, -	0x21f50231, -	0x94bd0801, +	0xc00017f1, +	0xcf0213f0, +	0x27f10011, +	0x23f0c100, +	0x0022cf02, +	0xf51f13c8, +	0xc800890b, +	0x0bf41f23, +	0xb920f962, +	0x94bd0212,  	0xf10799f0, -	0xf0170007, +	0xf0370007,  	0x09d00203, -	0xfc04bd00, -	0xf094bd20, -	0x07f10699, -	0x03f03700, -	0x0009d002, -	0x31f404bd, -	0x0121f501, -	0xf094bd08, -	0x07f10699, +	0xf404bd00, +	0x31f40132, +	0x0221f502, +	0xf094bd0a, +	0x07f10799,  	0x03f01700,  	0x0009d002, -	0x0ef404bd, -/* 0x04f9: chsw_prev_no_next */ -	0xb920f931, -	0x32f40212, -	0x0232f401, -	0x080121f5, -	0x17f120fc, -	0x14b60b00, -	0x0012d006, -/* 0x0517: chsw_no_prev */ -	0xc8130ef4, -	0x0bf41f23, -	0x0131f40d, -	0xf50232f4, -/* 0x0527: chsw_done */ -	0xf1080121, -	0xb60b0c17, -	0x27f00614, -	0x0012d001, +	0x20fc04bd,  	0x99f094bd, -	0x0007f104, +	0x0007f106, +	0x0203f037, +	0xbd0009d0, +	0x0131f404, +	0x0a0221f5, +	0x99f094bd, +	0x0007f106,  	0x0203f017,  	0xbd0009d0, -	0x130ef504, -/* 0x0549: main_not_ctx_switch */ -	0x01e4b0ff, -	0xb90d1bf4, -	0x21f502f2, -	0x0ef40795, -/* 0x0559: main_not_ctx_chan */ -	0x02e4b046, -	0xbd321bf4, -	0x0799f094, -	0x370007f1, +	0x330ef404, +/* 0x060c: chsw_prev_no_next */ +	0x12b920f9, +	0x0132f402, +	0xf50232f4, +	0xfc0a0221, +	0x0007f120, +	0x0203f0c0, +	0xbd0002d0, +	0x130ef404, +/* 0x062c: chsw_no_prev */ +	0xf41f23c8, +	0x31f40d0b, +	0x0232f401, +	0x0a0221f5, +/* 0x063c: chsw_done */ +	0xf10127f0, +	0xf0c30007, +	0x02d00203, +	0xbd04bd00, +	0x0499f094, +	0x170007f1,  	0xd00203f0,  	0x04bd0009, -	0xf40132f4, -	0x21f50232, -	0x94bd0801, +	0xff080ef5, +/* 0x0660: main_not_ctx_switch */ +	0xf401e4b0, +	0xf2b90d1b, +	0x9a21f502, +	0x460ef409, +/* 0x0670: main_not_ctx_chan */ +	0xf402e4b0, +	0x94bd321b,  	0xf10799f0, -	0xf0170007, +	0xf0370007,  	0x09d00203,  	0xf404bd00, -/* 0x058e: main_not_ctx_save */ -	0xef94110e, -	0x01f5f010, -	0x02fe21f5, -	0xfec00ef5, -/* 0x059c: main_done */ -	0x29f024bd, -	0x0007f11f, -	0x0203f030, -	0xbd0002d0, -	0xab0ef504, -/* 0x05b1: ih */ -	0xfe80f9fe, -	0x80f90188, -	0xa0f990f9, -	0xd0f9b0f9, -	0xf0f9e0f9, -	0x0acf04bd, -	0x04abc480, -	0xf11d0bf4, -	0xf01900b7, -	0xbecf10d7, -	0x00bfcf40, +	0x32f40132, +	0x0221f502, +	0xf094bd0a, +	0x07f10799, +	0x03f01700, +	0x0009d002, +	0x0ef404bd, +/* 0x06a5: main_not_ctx_save */ +	0x10ef9411, +	0xf501f5f0, +	0xf5037e21, +/* 0x06b3: main_done */ +	0xbdfeb50e, +	0x1f29f024, +	0x300007f1, +	0xd00203f0, +	0x04bd0002, +	0xfea00ef5, +/* 0x06c8: ih */ +	0x88fe80f9, +	0xf980f901, +	0xf9a0f990, +	0xf9d0f9b0, +	0xbdf0f9e0, +	0x00a7f104, +	0x00a3f002, +	0xc400aacf, +	0x0bf404ab, +	0x10d7f030, +	0x1a00e7f1, +	0xcf00e3f0, +	0xf7f100ee, +	0xf3f01900, +	0x00ffcf00,  	0xb70421f4,  	0xf00400b0, -	0xbed001e7, -/* 0x05e9: ih_no_fifo */ -	0x00abe400, -	0x0d0bf401, -	0xf110d7f0, -	0xf44001e7, -/* 0x05fa: ih_no_ctxsw */ -	0xb7f10421, -	0xb0bd0104, -	0xf4b4abff, -	0xa7f10d0b, -	0xa4b60c1c, -	0x00abd006, -/* 0x0610: ih_no_other */ -	0xfc400ad0, +	0x07f101e7, +	0x03f01d00, +	0x000ed000, +/* 0x071a: ih_no_fifo */ +	0xabe404bd, +	0x0bf40100, +	0x10d7f00d, +	0x4001e7f1, +/* 0x072b: ih_no_ctxsw */ +	0xe40421f4, +	0xf40400ab, +	0xe7f16c0b, +	0xe3f00708, +	0x6821f440, +	0xf102ffb9, +	0xf0040007, +	0x0fd00203, +	0xf104bd00, +	0xf00704e7, +	0x21f440e3, +	0x02ffb968, +	0x030007f1, +	0xd00203f0, +	0x04bd000f, +	0x9450fec7, +	0xf7f102ee, +	0xf3f00700, +	0x00efbb40, +	0xf16821f4, +	0xf0020007, +	0x0fd00203, +	0xf004bd00, +	0x21f503f7, +	0xb7f1037e, +	0xbfb90100, +	0x44e7f102, +	0x40e3f001, +/* 0x079b: ih_no_fwmthd */ +	0xf19d21f4, +	0xbd0504b7, +	0xb4abffb0, +	0xf10f0bf4, +	0xf0070007, +	0x0bd00303, +/* 0x07b3: ih_no_other */ +	0xf104bd00, +	0xf0010007, +	0x0ad00003, +	0xfc04bd00,  	0xfce0fcf0,  	0xfcb0fcd0,  	0xfc90fca0,  	0x0088fe80,  	0x32f480fc, -/* 0x062b: ctx_4170s */ -	0xf101f800, -	0xf04170e7, -	0xf5f040e3, -	0x8d21f410, -/* 0x063a: ctx_4170w */ +/* 0x07d7: ctx_4170s */ +	0xf001f800, +	0xffb910f5, +	0x70e7f102, +	0x40e3f041, +	0xf89d21f4, +/* 0x07e9: ctx_4170w */ +	0x70e7f100, +	0x40e3f041, +	0xb96821f4, +	0xf4f002ff, +	0xf01bf410, +/* 0x07fe: ctx_redswitch */  	0xe7f100f8, -	0xe3f04170, -	0x6821f440, -	0xf410f4f0, +	0xe5f00200, +	0x20e5f040, +	0xf110e5f0, +	0xf0850007, +	0x0ed00103, +	0xf004bd00, +/* 0x081a: ctx_redswitch_delay */ +	0xf2b608f7, +	0xfd1bf401, +	0x0400e5f1, +	0x0100e5f1, +	0x850007f1, +	0xd00103f0, +	0x04bd000e, +/* 0x0836: ctx_86c */ +	0x07f100f8, +	0x03f02300, +	0x000fd002, +	0xffb904bd, +	0x14e7f102, +	0x40e3f08a, +	0xb99d21f4, +	0xe7f102ff, +	0xe3f0a88c, +	0x9d21f441, +/* 0x085e: ctx_mem */ +	0x07f100f8, +	0x03f08400, +	0x000fd002, +/* 0x086a: ctx_mem_wait */ +	0xf7f104bd, +	0xf3f08400, +	0x00ffcf02, +	0xf405fffd,  	0x00f8f31b, -/* 0x064c: ctx_redswitch */ -	0x0614e7f1, -	0xf106e4b6, -	0xd00270f7, -	0xf7f000ef, -/* 0x065d: ctx_redswitch_delay */ -	0x01f2b608, -	0xf1fd1bf4, -	0xd00770f7, -	0x00f800ef, -/* 0x066c: ctx_86c */ -	0x086ce7f1, -	0xd006e4b6, -	0xe7f100ef, -	0xe3f08a14, -	0x8d21f440, -	0xa86ce7f1, -	0xf441e3f0, -	0x00f88d21, -/* 0x068c: ctx_load */ +/* 0x087c: ctx_load */  	0x99f094bd,  	0x0007f105,  	0x0203f037,  	0xbd0009d0,  	0x0ca7f004, -	0xf1c921f4, -	0xb60a2417, -	0x10d00614, -	0x0037f100, -	0x0634b60b, -	0xf14032d0, -	0xb60a0c17, -	0x47f00614, -	0x0012d007, -/* 0x06c7: ctx_chan_wait_0 */ -	0xcf4014d0, -	0x44f04014, -	0xfa1bf41f, -	0xfe0032d0, -	0x2af0000b, -	0x0424b61f, -	0xbd0220b6, +	0xbdd021f4, +	0x0007f1f4, +	0x0203f089, +	0xbd000fd0, +	0x0007f104, +	0x0203f0c1, +	0xbd0002d0, +	0x0007f104, +	0x0203f083, +	0xbd0002d0, +	0x07f7f004, +	0x085e21f5, +	0xc00007f1, +	0xd00203f0, +	0x04bd0002, +	0xf0000bfe, +	0x24b61f2a, +	0x0220b604, +	0x99f094bd, +	0x0007f108, +	0x0203f037, +	0xbd0009d0, +	0x0007f104, +	0x0203f081, +	0xbd0002d0, +	0x0027f104, +	0x0023f100, +	0x0225f080, +	0x880007f1, +	0xd00203f0, +	0x04bd0002, +	0xf11017f0, +	0xf0020027, +	0x12fa0223, +	0xbd03f805,  	0x0899f094, -	0x370007f1, +	0x170007f1,  	0xd00203f0,  	0x04bd0009, -	0x0a0417f1, -	0xd00614b6, -	0x17f10012, -	0x14b60a20, -	0x0227f006, -	0x800023f1, -	0xf00012d0, -	0x27f11017, -	0x23f00200, -	0x0512fa02, -	0x94bd03f8, -	0xf10899f0, -	0xf0170007, +	0xb6810198, +	0x02981814, +	0x0825b680, +	0x800512fd, +	0x94bd1601, +	0xf10999f0, +	0xf0370007,  	0x09d00203, -	0x9804bd00, -	0x14b68101, -	0x80029818, -	0xfd0825b6, -	0x01800512, -	0xf094bd16, -	0x07f10999, -	0x03f03700, -	0x0009d002, -	0x27f104bd, -	0x24b60a04, -	0x0021d006, -	0xf10127f0, -	0xb60a2017, -	0x12d00614, -	0x0017f100, -	0x0613f001, -	0xf80501fa, -	0xf094bd03, -	0x07f10999, -	0x03f01700, -	0x0009d002, -	0x94bd04bd, -	0xf10599f0, +	0xf104bd00, +	0xf0810007, +	0x01d00203, +	0xf004bd00, +	0x07f10127, +	0x03f08800, +	0x0002d002, +	0x17f104bd, +	0x13f00100, +	0x0501fa06, +	0x94bd03f8, +	0xf10999f0,  	0xf0170007,  	0x09d00203, -	0xf804bd00, -/* 0x0795: ctx_chan */ -	0x8c21f500, -	0x0ca7f006, -	0xf1c921f4, -	0xb60a1017, -	0x27f00614, -	0x0012d005, -/* 0x07ac: ctx_chan_wait */ -	0xfd0012cf, -	0x1bf40522, -/* 0x07b7: ctx_mmio_exec */ -	0x9800f8fa, -	0x27f14103, -	0x24b60a04, -	0x0023d006, -/* 0x07c6: ctx_mmio_loop */ +	0xbd04bd00, +	0x0599f094, +	0x170007f1, +	0xd00203f0, +	0x04bd0009, +/* 0x099a: ctx_chan */ +	0x21f500f8, +	0xa7f0087c, +	0xd021f40c, +	0xf505f7f0, +	0xf8085e21, +/* 0x09ad: ctx_mmio_exec */ +	0x41039800, +	0x810007f1, +	0xd00203f0, +	0x04bd0003, +/* 0x09be: ctx_mmio_loop */  	0x34c434bd,  	0x0f1bf4ff,  	0x020057f1,  	0xfa0653f0,  	0x03f80535, -/* 0x07d8: ctx_mmio_pull */ +/* 0x09d0: ctx_mmio_pull */  	0x98804e98,  	0x21f4814f, -	0x0830b68d, +	0x0830b69d,  	0xf40112b6, -/* 0x07ea: ctx_mmio_done */ +/* 0x09e2: ctx_mmio_done */  	0x0398df1b, -	0x0023d016, -	0xf1400080, -	0xf0010017, -	0x01fa0613, -	0xf803f806, -/* 0x0801: ctx_xfer */ -	0x00f7f100, -	0x06f4b60c, -	0xd004e7f0, -/* 0x080e: ctx_xfer_idle */ -	0xfecf80fe, -	0x00e4f100, -	0xf91bf420, -	0xf40611f4, -/* 0x081e: ctx_xfer_pre */ -	0xf7f00d02, -	0x6c21f510, -	0x1c11f406, -/* 0x0828: ctx_xfer_pre_load */ -	0xf502f7f0, -	0xf5062b21, -	0xf5063a21, -	0xbd064c21, -	0x2b21f5f4, -	0x8c21f506, -/* 0x0841: ctx_xfer_exec */ -	0x16019806, -	0x041427f1, -	0xd00624b6, -	0xe7f10020, -	0xe3f0a500, -	0x021fb941, -	0xb68d21f4, -	0xfcf004e0, -	0x022cf001, -	0xfd0124b6, -	0x21f405f2, -	0xfc17f18d, -	0x0213f04a, -	0xd00c27f0, -	0x21f50012, -	0x27f10215, -	0x23f047fc, -	0x0020d002, +	0x0007f116, +	0x0203f081, +	0xbd0003d0, +	0x40008004, +	0x010017f1, +	0xfa0613f0, +	0x03f80601, +/* 0x0a02: ctx_xfer */ +	0xe7f000f8, +	0x0007f104, +	0x0303f002, +	0xbd000ed0, +/* 0x0a11: ctx_xfer_idle */ +	0x00e7f104, +	0x03e3f000, +	0xf100eecf, +	0xf42000e4, +	0x11f4f21b, +	0x0d02f406, +/* 0x0a28: ctx_xfer_pre */ +	0xf510f7f0, +	0xf4083621, +/* 0x0a32: ctx_xfer_pre_load */ +	0xf7f01c11, +	0xd721f502, +	0xe921f507, +	0xfe21f507, +	0xf5f4bd07, +	0xf507d721, +/* 0x0a4b: ctx_xfer_exec */ +	0x98087c21, +	0x24bd1601, +	0x050007f1, +	0xd00103f0, +	0x04bd0002, +	0xf1021fb9, +	0xf0a500e7, +	0x21f441e3, +	0x01fcf09d, +	0xb6022cf0, +	0xf2fd0124, +	0x02ffb905, +	0xa504e7f1, +	0xf441e3f0, +	0x21f59d21, +	0x24bd026a, +	0x47fc07f1, +	0xd00203f0, +	0x04bd0002,  	0xb6012cf0, -	0x12d00320, -	0x01acf000, -	0xf006a5f0, -	0x0c9800b7, -	0x010d9800, -	0xf500e7f0, -	0xf0016621, -	0x21f508a7, -	0x21f50109, -	0x01f40215, -	0x0ca7f022, -	0xf1c921f4, -	0xb60a1017, -	0x27f00614, -	0x0012d005, -/* 0x08c8: ctx_xfer_post_save_wait */ -	0xfd0012cf, -	0x1bf40522, -	0x2e02f4fa, -/* 0x08d4: ctx_xfer_post */ -	0xf502f7f0, -	0xbd062b21, -	0x6c21f5f4, -	0x3421f506, -	0x3a21f502, -	0xf5f4bd06, -	0xf4062b21, -	0x01981011, -	0x0511fd40, -	0xf5070bf4, -/* 0x08ff: ctx_xfer_no_post_mmio */ -/* 0x08ff: ctx_xfer_done */ -	0xf807b721, -	0x00000000, -	0x00000000, +	0x07f10320, +	0x03f04afc, +	0x0002d002, +	0xacf004bd, +	0x06a5f001, +	0x9800b7f0, +	0x0d98000c, +	0x00e7f001, +	0x016f21f5, +	0xf508a7f0, +	0xf5011021, +	0xf4025e21, +	0xa7f01301, +	0xd021f40c, +	0xf505f7f0, +	0xf4085e21, +/* 0x0ada: ctx_xfer_post */ +	0xf7f02e02, +	0xd721f502, +	0xf5f4bd07, +	0xf5083621, +	0xf5027f21, +	0xbd07e921, +	0xd721f5f4, +	0x1011f407, +	0xfd400198, +	0x0bf40511, +	0xad21f507, +/* 0x0b05: ctx_xfer_no_post_mmio */ +/* 0x0b05: ctx_xfer_done */ +	0x0000f809,  	0x00000000,  	0x00000000,  	0x00000000, diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc index 33a5a82eccb..2a0b0f84429 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/macros.fuc @@ -28,28 +28,142 @@  #define GF117 0xd7  #define GK100 0xe0  #define GK110 0xf0 +#define GK208 0x108 +#define NV_PGRAPH_TRAPPED_ADDR                                         0x400704 +#define NV_PGRAPH_TRAPPED_DATA_LO                                      0x400708 +#define NV_PGRAPH_TRAPPED_DATA_HI                                      0x40070c + +#define NV_PGRAPH_FE_OBJECT_TABLE(n)                        ((n) * 4 + 0x400700) + +#define NV_PGRAPH_FECS_INTR_ACK                                        0x409004 +#define NV_PGRAPH_FECS_INTR                                            0x409008 +#define NV_PGRAPH_FECS_INTR_FWMTHD                                   0x00000400 +#define NV_PGRAPH_FECS_INTR_CHSW                                     0x00000100 +#define NV_PGRAPH_FECS_INTR_FIFO                                     0x00000004 +#define NV_PGRAPH_FECS_INTR_MODE                                       0x40900c +#define NV_PGRAPH_FECS_INTR_MODE_FIFO                                0x00000004 +#define NV_PGRAPH_FECS_INTR_MODE_FIFO_LEVEL                          0x00000004 +#define NV_PGRAPH_FECS_INTR_MODE_FIFO_EDGE                           0x00000000 +#define NV_PGRAPH_FECS_INTR_EN_SET                                     0x409010 +#define NV_PGRAPH_FECS_INTR_EN_SET_FIFO                              0x00000004 +#define NV_PGRAPH_FECS_INTR_ROUTE                                      0x40901c +#define NV_PGRAPH_FECS_ACCESS                                          0x409048 +#define NV_PGRAPH_FECS_ACCESS_FIFO                                   0x00000002 +#define NV_PGRAPH_FECS_FIFO_DATA                                       0x409064 +#define NV_PGRAPH_FECS_FIFO_CMD                                        0x409068 +#define NV_PGRAPH_FECS_FIFO_ACK                                        0x409074 +#define NV_PGRAPH_FECS_CAPS                                            0x409108  #define NV_PGRAPH_FECS_SIGNAL                                          0x409400 +#define NV_PGRAPH_FECS_IROUTE                                          0x409404 +#define NV_PGRAPH_FECS_BAR_MASK0                                       0x40940c +#define NV_PGRAPH_FECS_BAR_MASK1                                       0x409410 +#define NV_PGRAPH_FECS_BAR                                             0x409414 +#define NV_PGRAPH_FECS_BAR_SET                                         0x409418 +#define NV_PGRAPH_FECS_RED_SWITCH                                      0x409614 +#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_ROP                         0x00000400 +#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_GPC                         0x00000200 +#define NV_PGRAPH_FECS_RED_SWITCH_ENABLE_MAIN                        0x00000100 +#define NV_PGRAPH_FECS_RED_SWITCH_POWER_ROP                          0x00000040 +#define NV_PGRAPH_FECS_RED_SWITCH_POWER_GPC                          0x00000020 +#define NV_PGRAPH_FECS_RED_SWITCH_POWER_MAIN                         0x00000010 +#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_GPC                          0x00000002 +#define NV_PGRAPH_FECS_RED_SWITCH_PAUSE_MAIN                         0x00000001 +#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700 +#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704 +#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c +#define NV_PGRAPH_FECS_MMCTX_SAVE_SWBASE                               0x409700 +#define NV_PGRAPH_FECS_MMCTX_LOAD_SWBASE                               0x409704 +#define NV_PGRAPH_FECS_MMCTX_BASE                                      0x409710 +#define NV_PGRAPH_FECS_MMCTX_CTRL                                      0x409714 +#define NV_PGRAPH_FECS_MMCTX_MULTI_STRIDE                              0x409718 +#define NV_PGRAPH_FECS_MMCTX_MULTI_MASK                                0x40971c +#define NV_PGRAPH_FECS_MMCTX_QUEUE                                     0x409720 +#define NV_PGRAPH_FECS_MMIO_CTRL                                       0x409728 +#define NV_PGRAPH_FECS_MMIO_RDVAL                                      0x40972c +#define NV_PGRAPH_FECS_MMIO_WRVAL                                      0x409730 +#define NV_PGRAPH_FECS_MMCTX_LOAD_COUNT                                0x40974c  #if CHIPSET < GK110  #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)  #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x409820)  #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840) +#define NV_PGRAPH_FECS_UNK86C                                          0x40986c  #else  #define NV_PGRAPH_FECS_CC_SCRATCH_VAL(n)                    ((n) * 4 + 0x409800)  #define NV_PGRAPH_FECS_CC_SCRATCH_CLR(n)                    ((n) * 4 + 0x409840) +#define NV_PGRAPH_FECS_UNK86C                                          0x40988c  #define NV_PGRAPH_FECS_CC_SCRATCH_SET(n)                    ((n) * 4 + 0x4098c0)  #endif +#define NV_PGRAPH_FECS_STRANDS_CNT                                     0x409880 +#define NV_PGRAPH_FECS_STRAND_SAVE_SWBASE                              0x409908 +#define NV_PGRAPH_FECS_STRAND_LOAD_SWBASE                              0x40990c +#define NV_PGRAPH_FECS_STRAND_WORDS                                    0x409910 +#define NV_PGRAPH_FECS_STRAND_DATA                                     0x409918 +#define NV_PGRAPH_FECS_STRAND_SELECT                                   0x40991c +#define NV_PGRAPH_FECS_STRAND_CMD                                      0x409928 +#define NV_PGRAPH_FECS_STRAND_CMD_SEEK                               0x00000001 +#define NV_PGRAPH_FECS_STRAND_CMD_GET_INFO                           0x00000002 +#define NV_PGRAPH_FECS_STRAND_CMD_SAVE                               0x00000003 +#define NV_PGRAPH_FECS_STRAND_CMD_LOAD                               0x00000004 +#define NV_PGRAPH_FECS_STRAND_CMD_ACTIVATE_FILTER                    0x0000000a +#define NV_PGRAPH_FECS_STRAND_CMD_DEACTIVATE_FILTER                  0x0000000b +#define NV_PGRAPH_FECS_STRAND_CMD_ENABLE                             0x0000000c +#define NV_PGRAPH_FECS_STRAND_CMD_DISABLE                            0x0000000d +#define NV_PGRAPH_FECS_STRAND_FILTER                                   0x40993c +#define NV_PGRAPH_FECS_MEM_BASE                                        0x409a04 +#define NV_PGRAPH_FECS_MEM_CHAN                                        0x409a0c +#define NV_PGRAPH_FECS_MEM_CMD                                         0x409a10 +#define NV_PGRAPH_FECS_MEM_CMD_LOAD_CHAN                             0x00000007 +#define NV_PGRAPH_FECS_MEM_TARGET                                      0x409a20 +#define NV_PGRAPH_FECS_MEM_TARGET_UNK31                              0x80000000 +#define NV_PGRAPH_FECS_MEM_TARGET_AS                                 0x0000001f +#define NV_PGRAPH_FECS_MEM_TARGET_AS_VM                              0x00000001 +#define NV_PGRAPH_FECS_MEM_TARGET_AS_VRAM                            0x00000002 +#define NV_PGRAPH_FECS_CHAN_ADDR                                       0x409b00 +#define NV_PGRAPH_FECS_CHAN_NEXT                                       0x409b04 +#define NV_PGRAPH_FECS_CHSW                                            0x409b0c +#define NV_PGRAPH_FECS_CHSW_ACK                                      0x00000001  #define NV_PGRAPH_FECS_INTR_UP_SET                                     0x409c1c +#define NV_PGRAPH_FECS_INTR_UP_EN                                      0x409c24 +#define NV_PGRAPH_GPCX_GPCCS_INTR_ACK                                  0x41a004 +#define NV_PGRAPH_GPCX_GPCCS_INTR                                      0x41a008 +#define NV_PGRAPH_GPCX_GPCCS_INTR_FIFO                               0x00000004 +#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET                               0x41a010 +#define NV_PGRAPH_GPCX_GPCCS_INTR_EN_SET_FIFO                        0x00000004 +#define NV_PGRAPH_GPCX_GPCCS_INTR_ROUTE                                0x41a01c +#define NV_PGRAPH_GPCX_GPCCS_ACCESS                                    0x41a048 +#define NV_PGRAPH_GPCX_GPCCS_ACCESS_FIFO                             0x00000002 +#define NV_PGRAPH_GPCX_GPCCS_FIFO_DATA                                 0x41a064 +#define NV_PGRAPH_GPCX_GPCCS_FIFO_CMD                                  0x41a068 +#define NV_PGRAPH_GPCX_GPCCS_FIFO_ACK                                  0x41a074 +#define NV_PGRAPH_GPCX_GPCCS_UNITS                                     0x41a608 +#define NV_PGRAPH_GPCX_GPCCS_CAPS                                      0x41a108 +#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH                                0x41a614 +#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_UNK11                        0x00000800 +#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_ENABLE                       0x00000200 +#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_POWER                        0x00000020 +#define NV_PGRAPH_GPCX_GPCCS_RED_SWITCH_PAUSE                        0x00000002 +#define NV_PGRAPH_GPCX_GPCCS_MYINDEX                                   0x41a618 +#define NV_PGRAPH_GPCX_GPCCS_MMCTX_SAVE_SWBASE                         0x41a700 +#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_SWBASE                         0x41a704 +#define NV_PGRAPH_GPCX_GPCCS_MMCTX_LOAD_COUNT                          0x41a74c  #if CHIPSET < GK110  #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)  #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a820)  #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840) +#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a86c  #else  #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_VAL(n)              ((n) * 4 + 0x41a800)  #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_CLR(n)              ((n) * 4 + 0x41a840) +#define NV_PGRAPH_GPCX_GPCCS_UNK86C                                    0x41a88c  #define NV_PGRAPH_GPCX_GPCCS_CC_SCRATCH_SET(n)              ((n) * 4 + 0x41a8c0)  #endif +#define NV_PGRAPH_GPCX_GPCCS_STRAND_SELECT                             0x41a91c +#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD                                0x41a928 +#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_SAVE                         0x00000003 +#define NV_PGRAPH_GPCX_GPCCS_STRAND_CMD_LOAD                         0x00000004 +#define NV_PGRAPH_GPCX_GPCCS_MEM_BASE                                  0x41aa04  #define mmctx_data(r,c) .b32 (((c - 1) << 26) | r)  #define queue_init      .skip 72 // (2 * 4) + ((8 * 4) * 2) @@ -65,24 +179,50 @@  #define T_LCHAN   8  #define T_LCTXH   9 -#define nv_mkmm(rv,r) /* -*/	movw rv  ((r) & 0x0000fffc) /* -*/	sethi rv ((r) & 0x00ff0000) +#if CHIPSET < GK208 +#define imm32(reg,val) /* +*/	movw reg  ((val) & 0x0000ffff) /* +*/	sethi reg ((val) & 0xffff0000) +#else +#define imm32(reg,val) /* +*/	mov reg (val) +#endif +  #define nv_mkio(rv,r,i) /* -*/	nv_mkmm(rv, (((r) & 0xffc) << 6) | ((i) << 2)) +*/	imm32(rv, (((r) & 0xffc) << 6) | ((i) << 2)) + +#define hash # +#define fn(a) a +#if CHIPSET < GK208 +#define call(a) call fn(hash)a +#else +#define call(a) lcall fn(hash)a +#endif  #define nv_iord(rv,r,i) /*  */	nv_mkio(rv,r,i) /*  */	iord rv I[rv] +  #define nv_iowr(r,i,rv) /*  */	nv_mkio($r0,r,i) /*  */	iowr I[$r0] rv /*  */	clear b32 $r0 +#define nv_rd32(reg,addr) /* +*/	imm32($r14, addr) /* +*/	call(nv_rd32) /* +*/	mov b32 reg $r15 + +#define nv_wr32(addr,reg) /* +*/	mov b32 $r15 reg /* +*/	imm32($r14, addr) /* +*/	call(nv_wr32) +  #define trace_set(bit) /*  */	clear b32 $r9 /*  */	bset $r9 bit /*  */	nv_iowr(NV_PGRAPH_FECS_CC_SCRATCH_SET(7), 0, $r9) +  #define trace_clr(bit) /*  */	clear b32 $r9 /*  */	bset $r9 bit /* diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/os.h b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/os.h index fd1d380de09..1718ae4e822 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/os.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/os.h @@ -3,5 +3,6 @@  #define E_BAD_COMMAND  0x00000001  #define E_CMD_OVERFLOW 0x00000002 +#define E_BAD_FWMTHD   0x00000003  #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c new file mode 100644 index 00000000000..83048a56430 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/gk20a.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "nvc0.h" +#include "ctxnvc0.h" + +static struct nouveau_oclass +gk20a_graph_sclass[] = { +	{ 0x902d, &nouveau_object_ofuncs }, +	{ 0xa040, &nouveau_object_ofuncs }, +	{ 0xa297, &nouveau_object_ofuncs }, +	{ 0xa0c0, &nouveau_object_ofuncs }, +	{} +}; + +struct nouveau_oclass * +gk20a_graph_oclass = &(struct nvc0_graph_oclass) { +	.base.handle = NV_ENGINE(GR, 0xea), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_graph_ctor, +		.dtor = nvc0_graph_dtor, +		.init = nve4_graph_init, +		.fini = nve4_graph_fini, +	}, +	.cclass = &gk20a_grctx_oclass, +	.sclass = gk20a_graph_sclass, +	.mmio = nve4_graph_pack_mmio, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c new file mode 100644 index 00000000000..21c5f31d607 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/gm107.c @@ -0,0 +1,465 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include <subdev/bios.h> +#include <subdev/bios/P0260.h> + +#include "nvc0.h" +#include "ctxnvc0.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +gm107_graph_sclass[] = { +	{ 0x902d, &nouveau_object_ofuncs }, +	{ 0xa140, &nouveau_object_ofuncs }, +	{ 0xb097, &nouveau_object_ofuncs }, +	{ 0xb0c0, &nouveau_object_ofuncs }, +	{} +}; + +/******************************************************************************* + * PGRAPH register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +gm107_graph_init_main_0[] = { +	{ 0x400080,   1, 0x04, 0x003003c2 }, +	{ 0x400088,   1, 0x04, 0x0001bfe7 }, +	{ 0x40008c,   1, 0x04, 0x00060000 }, +	{ 0x400090,   1, 0x04, 0x00000030 }, +	{ 0x40013c,   1, 0x04, 0x003901f3 }, +	{ 0x400140,   1, 0x04, 0x00000100 }, +	{ 0x400144,   1, 0x04, 0x00000000 }, +	{ 0x400148,   1, 0x04, 0x00000110 }, +	{ 0x400138,   1, 0x04, 0x00000000 }, +	{ 0x400130,   2, 0x04, 0x00000000 }, +	{ 0x400124,   1, 0x04, 0x00000002 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_ds_0[] = { +	{ 0x405844,   1, 0x04, 0x00ffffff }, +	{ 0x405850,   1, 0x04, 0x00000000 }, +	{ 0x405900,   1, 0x04, 0x00000000 }, +	{ 0x405908,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_scc_0[] = { +	{ 0x40803c,   1, 0x04, 0x00000010 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_sked_0[] = { +	{ 0x407010,   1, 0x04, 0x00000000 }, +	{ 0x407040,   1, 0x04, 0x40440424 }, +	{ 0x407048,   1, 0x04, 0x0000000a }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_prop_0[] = { +	{ 0x418408,   1, 0x04, 0x00000000 }, +	{ 0x4184a0,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_setup_1[] = { +	{ 0x4188c8,   2, 0x04, 0x00000000 }, +	{ 0x4188d0,   1, 0x04, 0x00010000 }, +	{ 0x4188d4,   1, 0x04, 0x00010201 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_zcull_0[] = { +	{ 0x418910,   1, 0x04, 0x00010001 }, +	{ 0x418914,   1, 0x04, 0x00000301 }, +	{ 0x418918,   1, 0x04, 0x00800000 }, +	{ 0x418930,   2, 0x04, 0x00000000 }, +	{ 0x418980,   1, 0x04, 0x77777770 }, +	{ 0x418984,   3, 0x04, 0x77777777 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_gpc_unk_1[] = { +	{ 0x418d00,   1, 0x04, 0x00000000 }, +	{ 0x418f00,   1, 0x04, 0x00000400 }, +	{ 0x418f08,   1, 0x04, 0x00000000 }, +	{ 0x418e08,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_tpccs_0[] = { +	{ 0x419dc4,   1, 0x04, 0x00000000 }, +	{ 0x419dc8,   1, 0x04, 0x00000501 }, +	{ 0x419dd0,   1, 0x04, 0x00000000 }, +	{ 0x419dd4,   1, 0x04, 0x00000100 }, +	{ 0x419dd8,   1, 0x04, 0x00000001 }, +	{ 0x419ddc,   1, 0x04, 0x00000002 }, +	{ 0x419de0,   1, 0x04, 0x00000001 }, +	{ 0x419d0c,   1, 0x04, 0x00000000 }, +	{ 0x419d10,   1, 0x04, 0x00000014 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_tex_0[] = { +	{ 0x419ab0,   1, 0x04, 0x00000000 }, +	{ 0x419ab8,   1, 0x04, 0x000000e7 }, +	{ 0x419abc,   1, 0x04, 0x00000000 }, +	{ 0x419acc,   1, 0x04, 0x000000ff }, +	{ 0x419ac0,   1, 0x04, 0x00000000 }, +	{ 0x419aa8,   2, 0x04, 0x00000000 }, +	{ 0x419ad0,   2, 0x04, 0x00000000 }, +	{ 0x419ae0,   2, 0x04, 0x00000000 }, +	{ 0x419af0,   4, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_pe_0[] = { +	{ 0x419900,   1, 0x04, 0x000000ff }, +	{ 0x41980c,   1, 0x04, 0x00000010 }, +	{ 0x419844,   1, 0x04, 0x00000000 }, +	{ 0x419838,   1, 0x04, 0x000000ff }, +	{ 0x419850,   1, 0x04, 0x00000004 }, +	{ 0x419854,   2, 0x04, 0x00000000 }, +	{ 0x419894,   3, 0x04, 0x00100401 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_l1c_0[] = { +	{ 0x419c98,   1, 0x04, 0x00000000 }, +	{ 0x419cc0,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_sm_0[] = { +	{ 0x419e30,   1, 0x04, 0x000000ff }, +	{ 0x419e00,   1, 0x04, 0x00000000 }, +	{ 0x419ea0,   1, 0x04, 0x00000000 }, +	{ 0x419ee4,   1, 0x04, 0x00000000 }, +	{ 0x419ea4,   1, 0x04, 0x00000100 }, +	{ 0x419ea8,   1, 0x04, 0x01000000 }, +	{ 0x419ee8,   1, 0x04, 0x00000091 }, +	{ 0x419eb4,   1, 0x04, 0x00000000 }, +	{ 0x419ebc,   2, 0x04, 0x00000000 }, +	{ 0x419edc,   1, 0x04, 0x000c1810 }, +	{ 0x419ed8,   1, 0x04, 0x00000000 }, +	{ 0x419ee0,   1, 0x04, 0x00000000 }, +	{ 0x419f74,   1, 0x04, 0x00005155 }, +	{ 0x419f80,   4, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_l1c_1[] = { +	{ 0x419ccc,   2, 0x04, 0x00000000 }, +	{ 0x419c80,   1, 0x04, 0x3f006022 }, +	{ 0x419c88,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_pes_0[] = { +	{ 0x41be50,   1, 0x04, 0x000000ff }, +	{ 0x41be04,   1, 0x04, 0x00000000 }, +	{ 0x41be08,   1, 0x04, 0x00000004 }, +	{ 0x41be0c,   1, 0x04, 0x00000008 }, +	{ 0x41be10,   1, 0x04, 0x0e3b8bc7 }, +	{ 0x41be14,   2, 0x04, 0x00000000 }, +	{ 0x41be3c,   5, 0x04, 0x00100401 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_wwdx_0[] = { +	{ 0x41bfd4,   1, 0x04, 0x00800000 }, +	{ 0x41bfdc,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_cbm_0[] = { +	{ 0x41becc,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_be_0[] = { +	{ 0x408890,   1, 0x04, 0x000000ff }, +	{ 0x40880c,   1, 0x04, 0x00000000 }, +	{ 0x408850,   1, 0x04, 0x00000004 }, +	{ 0x408878,   1, 0x04, 0x00c81603 }, +	{ 0x40887c,   1, 0x04, 0x80543432 }, +	{ 0x408880,   1, 0x04, 0x0010581e }, +	{ 0x408884,   1, 0x04, 0x00001205 }, +	{ 0x408974,   1, 0x04, 0x000000ff }, +	{ 0x408910,   9, 0x04, 0x00000000 }, +	{ 0x408950,   1, 0x04, 0x00000000 }, +	{ 0x408954,   1, 0x04, 0x0000ffff }, +	{ 0x408958,   1, 0x04, 0x00000034 }, +	{ 0x40895c,   1, 0x04, 0x8531a003 }, +	{ 0x408960,   1, 0x04, 0x0561985a }, +	{ 0x408964,   1, 0x04, 0x04e15c4f }, +	{ 0x408968,   1, 0x04, 0x02808833 }, +	{ 0x40896c,   1, 0x04, 0x01f02438 }, +	{ 0x408970,   1, 0x04, 0x00012c00 }, +	{ 0x408984,   1, 0x04, 0x00000000 }, +	{ 0x408988,   1, 0x04, 0x08040201 }, +	{ 0x40898c,   1, 0x04, 0x80402010 }, +	{} +}; + +static const struct nvc0_graph_init +gm107_graph_init_sm_1[] = { +	{ 0x419e5c,   1, 0x04, 0x00000000 }, +	{ 0x419e58,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +gm107_graph_pack_mmio[] = { +	{ gm107_graph_init_main_0 }, +	{ nvf0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvc0_graph_init_pd_0 }, +	{ gm107_graph_init_ds_0 }, +	{ gm107_graph_init_scc_0 }, +	{ gm107_graph_init_sked_0 }, +	{ nvf0_graph_init_cwd_0 }, +	{ gm107_graph_init_prop_0 }, +	{ nv108_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ gm107_graph_init_setup_1 }, +	{ gm107_graph_init_zcull_0 }, +	{ nvc0_graph_init_gpm_0 }, +	{ gm107_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ gm107_graph_init_tpccs_0 }, +	{ gm107_graph_init_tex_0 }, +	{ gm107_graph_init_pe_0 }, +	{ gm107_graph_init_l1c_0 }, +	{ nvc0_graph_init_mpc_0 }, +	{ gm107_graph_init_sm_0 }, +	{ gm107_graph_init_l1c_1 }, +	{ gm107_graph_init_pes_0 }, +	{ gm107_graph_init_wwdx_0 }, +	{ gm107_graph_init_cbm_0 }, +	{ gm107_graph_init_be_0 }, +	{ gm107_graph_init_sm_1 }, +	{} +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static void +gm107_graph_init_bios(struct nvc0_graph_priv *priv) +{ +	static const struct { +		u32 ctrl; +		u32 data; +	} regs[] = { +		{ 0x419ed8, 0x419ee0 }, +		{ 0x419ad0, 0x419ad4 }, +		{ 0x419ae0, 0x419ae4 }, +		{ 0x419af0, 0x419af4 }, +		{ 0x419af8, 0x419afc }, +	}; +	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvbios_P0260E infoE; +	struct nvbios_P0260X infoX; +	int E = -1, X; +	u8 ver, hdr; + +	while (nvbios_P0260Ep(bios, ++E, &ver, &hdr, &infoE)) { +		if (X = -1, E < ARRAY_SIZE(regs)) { +			nv_wr32(priv, regs[E].ctrl, infoE.data); +			while (nvbios_P0260Xp(bios, ++X, &ver, &hdr, &infoX)) +				nv_wr32(priv, regs[E].data, infoX.data); +		} +	} +} + +int +gm107_graph_init(struct nouveau_object *object) +{ +	struct nvc0_graph_oclass *oclass = (void *)object->oclass; +	struct nvc0_graph_priv *priv = (void *)object; +	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total); +	u32 data[TPC_MAX / 8] = {}; +	u8  tpcnr[GPC_MAX]; +	int gpc, tpc, ppc, rop; +	int ret, i; + +	ret = nouveau_graph_init(&priv->base); +	if (ret) +		return ret; + +	nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000); +	nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000); +	nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000); +	nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8); +	nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); + +	nvc0_graph_mmio(priv, oclass->mmio); + +	gm107_graph_init_bios(priv); + +	nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); + +	memset(data, 0x00, sizeof(data)); +	memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr)); +	for (i = 0, gpc = -1; i < priv->tpc_total; i++) { +		do { +			gpc = (gpc + 1) % priv->gpc_nr; +		} while (!tpcnr[gpc]); +		tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--; + +		data[i / 8] |= tpc << ((i % 8) * 4); +	} + +	nv_wr32(priv, GPC_BCAST(0x0980), data[0]); +	nv_wr32(priv, GPC_BCAST(0x0984), data[1]); +	nv_wr32(priv, GPC_BCAST(0x0988), data[2]); +	nv_wr32(priv, GPC_BCAST(0x098c), data[3]); + +	for (gpc = 0; gpc < priv->gpc_nr; gpc++) { +		nv_wr32(priv, GPC_UNIT(gpc, 0x0914), +			priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]); +		nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 | +			priv->tpc_total); +		nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); +	} + +	nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); +	nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); + +	nv_wr32(priv, 0x400500, 0x00010001); + +	nv_wr32(priv, 0x400100, 0xffffffff); +	nv_wr32(priv, 0x40013c, 0xffffffff); +	nv_wr32(priv, 0x400124, 0x00000002); +	nv_wr32(priv, 0x409c24, 0x000e0000); + +	nv_wr32(priv, 0x404000, 0xc0000000); +	nv_wr32(priv, 0x404600, 0xc0000000); +	nv_wr32(priv, 0x408030, 0xc0000000); +	nv_wr32(priv, 0x404490, 0xc0000000); +	nv_wr32(priv, 0x406018, 0xc0000000); +	nv_wr32(priv, 0x407020, 0x40000000); +	nv_wr32(priv, 0x405840, 0xc0000000); +	nv_wr32(priv, 0x405844, 0x00ffffff); +	nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008); + +	for (gpc = 0; gpc < priv->gpc_nr; gpc++) { +		for (ppc = 0; ppc < 2 /* priv->ppc_nr[gpc] */; ppc++) +			nv_wr32(priv, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000); +		nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); +		nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); +		nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); +		nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); +		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) { +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x430), 0xc0000000); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x00dffffe); +			nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x00000005); +		} +		nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff); +		nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff); +	} + +	for (rop = 0; rop < priv->rop_nr; rop++) { +		nv_wr32(priv, ROP_UNIT(rop, 0x144), 0x40000000); +		nv_wr32(priv, ROP_UNIT(rop, 0x070), 0x40000000); +		nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff); +		nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff); +	} + +	nv_wr32(priv, 0x400108, 0xffffffff); +	nv_wr32(priv, 0x400138, 0xffffffff); +	nv_wr32(priv, 0x400118, 0xffffffff); +	nv_wr32(priv, 0x400130, 0xffffffff); +	nv_wr32(priv, 0x40011c, 0xffffffff); +	nv_wr32(priv, 0x400134, 0xffffffff); + +	nv_wr32(priv, 0x400054, 0x2c350f63); +	return nvc0_graph_init_ctxctl(priv); +} + +#include "fuc/hubgm107.fuc5.h" + +static struct nvc0_graph_ucode +gm107_graph_fecs_ucode = { +	.code.data = gm107_grhub_code, +	.code.size = sizeof(gm107_grhub_code), +	.data.data = gm107_grhub_data, +	.data.size = sizeof(gm107_grhub_data), +}; + +#include "fuc/gpcgm107.fuc5.h" + +static struct nvc0_graph_ucode +gm107_graph_gpccs_ucode = { +	.code.data = gm107_grgpc_code, +	.code.size = sizeof(gm107_grgpc_code), +	.data.data = gm107_grgpc_data, +	.data.size = sizeof(gm107_grgpc_data), +}; + +struct nouveau_oclass * +gm107_graph_oclass = &(struct nvc0_graph_oclass) { +	.base.handle = NV_ENGINE(GR, 0x07), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_graph_ctor, +		.dtor = nvc0_graph_dtor, +		.init = gm107_graph_init, +		.fini = _nouveau_graph_fini, +	}, +	.cclass = &gm107_grctx_oclass, +	.sclass =  gm107_graph_sclass, +	.mmio = gm107_graph_pack_mmio, +	.fecs.ucode = 0 ? &gm107_graph_fecs_ucode : NULL, +	.gpccs.ucode = &gm107_graph_gpccs_ucode, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index 23c143aaa55..4532f7e5618 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -945,7 +945,8 @@ nv10_graph_load_context(struct nv10_graph_chan *chan, int chid)  	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)  		nv_wr32(priv, nv10_graph_ctx_regs[i], chan->nv10[i]); -	if (nv_device(priv)->chipset >= 0x17) { +	if (nv_device(priv)->card_type >= NV_11 && +	    nv_device(priv)->chipset >= 0x17) {  		for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)  			nv_wr32(priv, nv17_graph_ctx_regs[i], chan->nv17[i]);  	} @@ -970,7 +971,8 @@ nv10_graph_unload_context(struct nv10_graph_chan *chan)  	for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)  		chan->nv10[i] = nv_rd32(priv, nv10_graph_ctx_regs[i]); -	if (nv_device(priv)->chipset >= 0x17) { +	if (nv_device(priv)->card_type >= NV_11 && +	    nv_device(priv)->chipset >= 0x17) {  		for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)  			chan->nv17[i] = nv_rd32(priv, nv17_graph_ctx_regs[i]);  	} @@ -1052,7 +1054,8 @@ nv10_graph_context_ctor(struct nouveau_object *parent,  	NV_WRITE_CTX(0x00400e14, 0x00001000);  	NV_WRITE_CTX(0x00400e30, 0x00080008);  	NV_WRITE_CTX(0x00400e34, 0x00080008); -	if (nv_device(priv)->chipset >= 0x17) { +	if (nv_device(priv)->card_type >= NV_11 && +	    nv_device(priv)->chipset >= 0x17) {  		/* is it really needed ??? */  		NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,  					nv_rd32(priv, NV10_PGRAPH_DEBUG_4)); @@ -1231,7 +1234,7 @@ nv10_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		nv_engine(priv)->sclass = nv10_graph_sclass;  	else  	if (nv_device(priv)->chipset <  0x17 || -	    nv_device(priv)->chipset == 0x1a) +	    nv_device(priv)->card_type < NV_11)  		nv_engine(priv)->sclass = nv15_graph_sclass;  	else  		nv_engine(priv)->sclass = nv17_graph_sclass; @@ -1270,7 +1273,8 @@ nv10_graph_init(struct nouveau_object *object)  	nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);  	nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31)); -	if (nv_device(priv)->chipset >= 0x17) { +	if (nv_device(priv)->card_type >= NV_11 && +	    nv_device(priv)->chipset >= 0x17) {  		nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000);  		nv_wr32(priv, 0x400a10, 0x03ff3fb6);  		nv_wr32(priv, 0x400838, 0x002f8684); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c new file mode 100644 index 00000000000..00ea1a08982 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv108.c @@ -0,0 +1,223 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include "nvc0.h" +#include "ctxnvc0.h" + +/******************************************************************************* + * Graphics object classes + ******************************************************************************/ + +static struct nouveau_oclass +nv108_graph_sclass[] = { +	{ 0x902d, &nouveau_object_ofuncs }, +	{ 0xa140, &nouveau_object_ofuncs }, +	{ 0xa197, &nouveau_object_ofuncs }, +	{ 0xa1c0, &nouveau_object_ofuncs }, +	{} +}; + +/******************************************************************************* + * PGRAPH register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nv108_graph_init_main_0[] = { +	{ 0x400080,   1, 0x04, 0x003083c2 }, +	{ 0x400088,   1, 0x04, 0x0001bfe7 }, +	{ 0x40008c,   1, 0x04, 0x00000000 }, +	{ 0x400090,   1, 0x04, 0x00000030 }, +	{ 0x40013c,   1, 0x04, 0x003901f7 }, +	{ 0x400140,   1, 0x04, 0x00000100 }, +	{ 0x400144,   1, 0x04, 0x00000000 }, +	{ 0x400148,   1, 0x04, 0x00000110 }, +	{ 0x400138,   1, 0x04, 0x00000000 }, +	{ 0x400130,   2, 0x04, 0x00000000 }, +	{ 0x400124,   1, 0x04, 0x00000002 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_graph_init_ds_0[] = { +	{ 0x405844,   1, 0x04, 0x00ffffff }, +	{ 0x405850,   1, 0x04, 0x00000000 }, +	{ 0x405900,   1, 0x04, 0x00000000 }, +	{ 0x405908,   1, 0x04, 0x00000000 }, +	{ 0x405928,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nv108_graph_init_gpc_unk_0[] = { +	{ 0x418604,   1, 0x04, 0x00000000 }, +	{ 0x418680,   1, 0x04, 0x00000000 }, +	{ 0x418714,   1, 0x04, 0x00000000 }, +	{ 0x418384,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_graph_init_setup_1[] = { +	{ 0x4188c8,   2, 0x04, 0x00000000 }, +	{ 0x4188d0,   1, 0x04, 0x00010000 }, +	{ 0x4188d4,   1, 0x04, 0x00000201 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_graph_init_tex_0[] = { +	{ 0x419ab0,   1, 0x04, 0x00000000 }, +	{ 0x419ac8,   1, 0x04, 0x00000000 }, +	{ 0x419ab8,   1, 0x04, 0x000000e7 }, +	{ 0x419abc,   2, 0x04, 0x00000000 }, +	{ 0x419ab4,   1, 0x04, 0x00000000 }, +	{ 0x419aa8,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nv108_graph_init_l1c_0[] = { +	{ 0x419c98,   1, 0x04, 0x00000000 }, +	{ 0x419ca8,   1, 0x04, 0x00000000 }, +	{ 0x419cb0,   1, 0x04, 0x01000000 }, +	{ 0x419cb4,   1, 0x04, 0x00000000 }, +	{ 0x419cb8,   1, 0x04, 0x00b08bea }, +	{ 0x419c84,   1, 0x04, 0x00010384 }, +	{ 0x419cbc,   1, 0x04, 0x281b3646 }, +	{ 0x419cc0,   2, 0x04, 0x00000000 }, +	{ 0x419c80,   1, 0x04, 0x00000230 }, +	{ 0x419ccc,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +nv108_graph_pack_mmio[] = { +	{ nv108_graph_init_main_0 }, +	{ nvf0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvd9_graph_init_pd_0 }, +	{ nv108_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvf0_graph_init_sked_0 }, +	{ nvf0_graph_init_cwd_0 }, +	{ nvd9_graph_init_prop_0 }, +	{ nv108_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nv108_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvd9_graph_init_gpm_0 }, +	{ nvf0_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nve4_graph_init_tpccs_0 }, +	{ nv108_graph_init_tex_0 }, +	{ nve4_graph_init_pe_0 }, +	{ nv108_graph_init_l1c_0 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvf0_graph_init_sm_0 }, +	{ nvd7_graph_init_pes_0 }, +	{ nvd7_graph_init_wwdx_0 }, +	{ nvd7_graph_init_cbm_0 }, +	{ nve4_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{} +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +static int +nv108_graph_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvc0_graph_priv *priv = (void *)object; +	static const struct { +		u32 addr; +		u32 data; +	} magic[] = { +		{ 0x020520, 0xfffffffc }, +		{ 0x020524, 0xfffffffe }, +		{ 0x020524, 0xfffffffc }, +		{ 0x020524, 0xfffffff8 }, +		{ 0x020524, 0xffffffe0 }, +		{ 0x020530, 0xfffffffe }, +		{ 0x02052c, 0xfffffffa }, +		{ 0x02052c, 0xfffffff0 }, +		{ 0x02052c, 0xffffffc0 }, +		{ 0x02052c, 0xffffff00 }, +		{ 0x02052c, 0xfffffc00 }, +		{ 0x02052c, 0xfffcfc00 }, +		{ 0x02052c, 0xfff0fc00 }, +		{ 0x02052c, 0xff80fc00 }, +		{ 0x020528, 0xfffffffe }, +		{ 0x020528, 0xfffffffc }, +	}; +	int i; + +	nv_mask(priv, 0x000200, 0x08001000, 0x00000000); +	nv_mask(priv, 0x0206b4, 0x00000000, 0x00000000); +	for (i = 0; i < ARRAY_SIZE(magic); i++) { +		nv_wr32(priv, magic[i].addr, magic[i].data); +		nv_wait(priv, magic[i].addr, 0x80000000, 0x00000000); +	} + +	return nouveau_graph_fini(&priv->base, suspend); +} + +#include "fuc/hubnv108.fuc5.h" + +static struct nvc0_graph_ucode +nv108_graph_fecs_ucode = { +	.code.data = nv108_grhub_code, +	.code.size = sizeof(nv108_grhub_code), +	.data.data = nv108_grhub_data, +	.data.size = sizeof(nv108_grhub_data), +}; + +#include "fuc/gpcnv108.fuc5.h" + +static struct nvc0_graph_ucode +nv108_graph_gpccs_ucode = { +	.code.data = nv108_grgpc_code, +	.code.size = sizeof(nv108_grgpc_code), +	.data.data = nv108_grgpc_data, +	.data.size = sizeof(nv108_grgpc_data), +}; + +struct nouveau_oclass * +nv108_graph_oclass = &(struct nvc0_graph_oclass) { +	.base.handle = NV_ENGINE(GR, 0x08), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_graph_ctor, +		.dtor = nvc0_graph_dtor, +		.init = nve4_graph_init, +		.fini = nv108_graph_fini, +	}, +	.cclass = &nv108_grctx_oclass, +	.sclass =  nv108_graph_sclass, +	.mmio = nv108_graph_pack_mmio, +	.fecs.ucode = &nv108_graph_fecs_ucode, +	.gpccs.ucode = &nv108_graph_gpccs_ucode, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index b2455931590..d145e080899 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -349,7 +349,7 @@ nv20_graph_init(struct nouveau_object *object)  	nv_wr32(priv, NV10_PGRAPH_SURFACE, tmp);  	/* begin RAM config */ -	vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; +	vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;  	nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200));  	nv_wr32(priv, 0x4009A8, nv_rd32(priv, 0x100204));  	nv_wr32(priv, NV10_PGRAPH_RDI_INDEX, 0x00EA0000); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 193a5de1b48..6477fbf6a55 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -484,7 +484,7 @@ nv40_graph_init(struct nouveau_object *object)  		engine->tile_prog(engine, i);  	/* begin RAM config */ -	vramsz = pci_resource_len(nv_device(priv)->pdev, 0) - 1; +	vramsz = nv_device_resource_len(nv_device(priv), 0) - 1;  	switch (nv_device(priv)->chipset) {  	case 0x40:  		nv_wr32(priv, 0x4009A4, nv_rd32(priv, 0x100200)); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 03de5175dd9..20665c21d80 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -197,34 +197,35 @@ static const struct nouveau_bitfield nv50_pgraph_status[] = {  	{ 0x00000080, "UNK7" },  	{ 0x00000100, "CTXPROG" },  	{ 0x00000200, "VFETCH" }, -	{ 0x00000400, "CCACHE_UNK4" }, -	{ 0x00000800, "STRMOUT_GSCHED_UNK5" }, -	{ 0x00001000, "UNK14XX" }, -	{ 0x00002000, "UNK24XX_CSCHED" }, -	{ 0x00004000, "UNK1CXX" }, +	{ 0x00000400, "CCACHE_PREGEOM" }, +	{ 0x00000800, "STRMOUT_VATTR_POSTGEOM" }, +	{ 0x00001000, "VCLIP" }, +	{ 0x00002000, "RATTR_APLANE" }, +	{ 0x00004000, "TRAST" },  	{ 0x00008000, "CLIPID" },  	{ 0x00010000, "ZCULL" },  	{ 0x00020000, "ENG2D" }, -	{ 0x00040000, "UNK34XX" }, -	{ 0x00080000, "TPRAST" }, -	{ 0x00100000, "TPROP" }, -	{ 0x00200000, "TEX" }, -	{ 0x00400000, "TPVP" }, -	{ 0x00800000, "MP" }, +	{ 0x00040000, "RMASK" }, +	{ 0x00080000, "TPC_RAST" }, +	{ 0x00100000, "TPC_PROP" }, +	{ 0x00200000, "TPC_TEX" }, +	{ 0x00400000, "TPC_GEOM" }, +	{ 0x00800000, "TPC_MP" },  	{ 0x01000000, "ROP" },  	{}  };  static const char *const nv50_pgraph_vstatus_0[] = { -	"VFETCH", "CCACHE", "UNK4", "UNK5", "GSCHED", "STRMOUT", "UNK14XX", NULL +	"VFETCH", "CCACHE", "PREGEOM", "POSTGEOM", "VATTR", "STRMOUT", "VCLIP", +	NULL  };  static const char *const nv50_pgraph_vstatus_1[] = { -	"TPRAST", "TPROP", "TEXTURE", "TPVP", "MP", NULL +	"TPC_RAST", "TPC_PROP", "TPC_TEX", "TPC_GEOM", "TPC_MP", NULL  };  static const char *const nv50_pgraph_vstatus_2[] = { -	"UNK24XX", "CSCHED", "UNK1CXX", "CLIPID", "ZCULL", "ENG2D", "UNK34XX", +	"RATTR", "APLANE", "TRAST", "CLIPID", "ZCULL", "ENG2D", "RMASK",  	"ROP", NULL  }; @@ -304,12 +305,37 @@ nv84_graph_tlb_flush(struct nouveau_engine *engine)  	return timeout ? -EBUSY : 0;  } -static const struct nouveau_enum nv50_mp_exec_error_names[] = { -	{ 3, "STACK_UNDERFLOW", NULL }, -	{ 4, "QUADON_ACTIVE", NULL }, -	{ 8, "TIMEOUT", NULL }, -	{ 0x10, "INVALID_OPCODE", NULL }, -	{ 0x40, "BREAKPOINT", NULL }, +static const struct nouveau_bitfield nv50_mp_exec_errors[] = { +	{ 0x01, "STACK_UNDERFLOW" }, +	{ 0x02, "STACK_MISMATCH" }, +	{ 0x04, "QUADON_ACTIVE" }, +	{ 0x08, "TIMEOUT" }, +	{ 0x10, "INVALID_OPCODE" }, +	{ 0x20, "PM_OVERFLOW" }, +	{ 0x40, "BREAKPOINT" }, +	{} +}; + +static const struct nouveau_bitfield nv50_mpc_traps[] = { +	{ 0x0000001, "LOCAL_LIMIT_READ" }, +	{ 0x0000010, "LOCAL_LIMIT_WRITE" }, +	{ 0x0000040, "STACK_LIMIT" }, +	{ 0x0000100, "GLOBAL_LIMIT_READ" }, +	{ 0x0001000, "GLOBAL_LIMIT_WRITE" }, +	{ 0x0010000, "MP0" }, +	{ 0x0020000, "MP1" }, +	{ 0x0040000, "GLOBAL_LIMIT_RED" }, +	{ 0x0400000, "GLOBAL_LIMIT_ATOM" }, +	{ 0x4000000, "MP2" }, +	{} +}; + +static const struct nouveau_bitfield nv50_tex_traps[] = { +	{ 0x00000001, "" }, /* any bit set? */ +	{ 0x00000002, "FAULT" }, +	{ 0x00000004, "STORAGE_TYPE_MISMATCH" }, +	{ 0x00000008, "LINEAR_MISMATCH" }, +	{ 0x00000020, "WRONG_MEMTYPE" },  	{}  }; @@ -396,6 +422,60 @@ static const struct nouveau_bitfield nv50_graph_intr_name[] = {  	{}  }; +static const struct nouveau_bitfield nv50_graph_trap_prop[] = { +	{ 0x00000004, "SURF_WIDTH_OVERRUN" }, +	{ 0x00000008, "SURF_HEIGHT_OVERRUN" }, +	{ 0x00000010, "DST2D_FAULT" }, +	{ 0x00000020, "ZETA_FAULT" }, +	{ 0x00000040, "RT_FAULT" }, +	{ 0x00000080, "CUDA_FAULT" }, +	{ 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" }, +	{ 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" }, +	{ 0x00000400, "RT_STORAGE_TYPE_MISMATCH" }, +	{ 0x00000800, "DST2D_LINEAR_MISMATCH" }, +	{ 0x00001000, "RT_LINEAR_MISMATCH" }, +	{} +}; + +static void +nv50_priv_prop_trap(struct nv50_graph_priv *priv, +		    u32 ustatus_addr, u32 ustatus, u32 tp) +{ +	u32 e0c = nv_rd32(priv, ustatus_addr + 0x04); +	u32 e10 = nv_rd32(priv, ustatus_addr + 0x08); +	u32 e14 = nv_rd32(priv, ustatus_addr + 0x0c); +	u32 e18 = nv_rd32(priv, ustatus_addr + 0x10); +	u32 e1c = nv_rd32(priv, ustatus_addr + 0x14); +	u32 e20 = nv_rd32(priv, ustatus_addr + 0x18); +	u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c); + +	/* CUDA memory: l[], g[] or stack. */ +	if (ustatus & 0x00000080) { +		if (e18 & 0x80000000) { +			/* g[] read fault? */ +			nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n", +					 tp, e14, e10 | ((e18 >> 24) & 0x1f)); +			e18 &= ~0x1f000000; +		} else if (e18 & 0xc) { +			/* g[] write fault? */ +			nv_error(priv, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n", +				 tp, e14, e10 | ((e18 >> 7) & 0x1f)); +			e18 &= ~0x00000f80; +		} else { +			nv_error(priv, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n", +				 tp, e14, e10); +		} +		ustatus &= ~0x00000080; +	} +	if (ustatus) { +		nv_error(priv, "TRAP_PROP - TP %d -", tp); +		nouveau_bitfield_print(nv50_graph_trap_prop, ustatus); +		pr_cont(" - Address %02x%08x\n", e14, e10); +	} +	nv_error(priv, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", +		 tp, e0c, e18, e1c, e20, e24); +} +  static void  nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)  { @@ -420,8 +500,8 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display)  			oplow = nv_rd32(priv, addr + 0x70);  			ophigh = nv_rd32(priv, addr + 0x74);  			nv_error(priv, "TRAP_MP_EXEC - " -					"TP %d MP %d: ", tpid, i); -			nouveau_enum_print(nv50_mp_exec_error_names, status); +					"TP %d MP %d:", tpid, i); +			nouveau_bitfield_print(nv50_mp_exec_errors, status);  			pr_cont(" at %06x warp %d, opcode %08x %08x\n",  					pc&0xffffff, pc >> 24,  					oplow, ophigh); @@ -461,6 +541,13 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,  				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)  					nv_error(priv, "\t0x%08x: 0x%08x\n", r,  						nv_rd32(priv, r)); +				if (ustatus) { +					nv_error(priv, "%s - TP%d:", name, i); +					nouveau_bitfield_print(nv50_tex_traps, +							       ustatus); +					pr_cont("\n"); +					ustatus = 0; +				}  			}  			break;  		case 7: /* MP error */ @@ -468,60 +555,19 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old,  				nv50_priv_mp_trap(priv, i, display);  				ustatus &= ~0x04030000;  			} -			break; -		case 8: /* TPDMA error */ -			{ -			u32 e0c = nv_rd32(priv, ustatus_addr + 4); -			u32 e10 = nv_rd32(priv, ustatus_addr + 8); -			u32 e14 = nv_rd32(priv, ustatus_addr + 0xc); -			u32 e18 = nv_rd32(priv, ustatus_addr + 0x10); -			u32 e1c = nv_rd32(priv, ustatus_addr + 0x14); -			u32 e20 = nv_rd32(priv, ustatus_addr + 0x18); -			u32 e24 = nv_rd32(priv, ustatus_addr + 0x1c); -			/* 2d engine destination */ -			if (ustatus & 0x00000010) { -				if (display) { -					nv_error(priv, "TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", -							i, e14, e10); -					nv_error(priv, "TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -							i, e0c, e18, e1c, e20, e24); -				} -				ustatus &= ~0x00000010; -			} -			/* Render target */ -			if (ustatus & 0x00000040) { -				if (display) { -					nv_error(priv, "TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", -							i, e14, e10); -					nv_error(priv, "TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -							i, e0c, e18, e1c, e20, e24); -				} -				ustatus &= ~0x00000040; -			} -			/* CUDA memory: l[], g[] or stack. */ -			if (ustatus & 0x00000080) { -				if (display) { -					if (e18 & 0x80000000) { -						/* g[] read fault? */ -						nv_error(priv, "TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", -								i, e14, e10 | ((e18 >> 24) & 0x1f)); -						e18 &= ~0x1f000000; -					} else if (e18 & 0xc) { -						/* g[] write fault? */ -						nv_error(priv, "TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", -								i, e14, e10 | ((e18 >> 7) & 0x1f)); -						e18 &= ~0x00000f80; -					} else { -						nv_error(priv, "TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", -								i, e14, e10); -					} -					nv_error(priv, "TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", -							i, e0c, e18, e1c, e20, e24); -				} -				ustatus &= ~0x00000080; -			} +			if (ustatus && display) { +				nv_error(priv, "%s - TP%d:", name, i); +				nouveau_bitfield_print(nv50_mpc_traps, ustatus); +				pr_cont("\n"); +				ustatus = 0;  			}  			break; +		case 8: /* PROP error */ +			if (display) +				nv50_priv_prop_trap( +						priv, ustatus_addr, ustatus, i); +			ustatus = 0; +			break;  		}  		if (ustatus) {  			if (display) @@ -727,11 +773,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display,  		status &= ~0x080;  	} -	/* TPDMA:  Handles TP-initiated uncached memory accesses: +	/* PROP:  Handles TP-initiated uncached memory accesses:  	 * l[], g[], stack, 2d surfaces, render targets. */  	if (status & 0x100) {  		nv50_priv_tp_trap(priv, 8, 0x408e08, 0x408708, display, -				    "TRAP_TPDMA"); +				    "TRAP_PROP");  		nv_wr32(priv, 0x400108, 0x100);  		status &= ~0x100;  	} @@ -760,7 +806,7 @@ nv50_graph_intr(struct nouveau_subdev *subdev)  	u32 mthd = (addr & 0x00001ffc);  	u32 data = nv_rd32(priv, 0x400708);  	u32 class = nv_rd32(priv, 0x400814); -	u32 show = stat; +	u32 show = stat, show_bitfield = stat;  	int chid;  	engctx = nouveau_engctx_get(engine, inst); @@ -778,21 +824,26 @@ nv50_graph_intr(struct nouveau_subdev *subdev)  		nv_error(priv, "DATA_ERROR ");  		nouveau_enum_print(nv50_data_error_names, ecode);  		pr_cont("\n"); +		show_bitfield &= ~0x00100000;  	}  	if (stat & 0x00200000) {  		if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12,  				engctx))  			show &= ~0x00200000; +		show_bitfield &= ~0x00200000;  	}  	nv_wr32(priv, 0x400100, stat);  	nv_wr32(priv, 0x400500, 0x00010001);  	if (show) { -		nv_error(priv, "%s", ""); -		nouveau_bitfield_print(nv50_graph_intr_name, show); -		pr_cont("\n"); +		show &= show_bitfield; +		if (show) { +			nv_error(priv, "%s", ""); +			nouveau_bitfield_print(nv50_graph_intr_name, show); +			pr_cont("\n"); +		}  		nv_error(priv,  			 "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",  			 chid, (u64)inst << 12, nouveau_client_name(engctx), @@ -850,7 +901,7 @@ nv50_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		nv_engine(priv)->sclass = nvaf_graph_sclass;  		break; -	}; +	}  	/* unfortunate hw bug workaround... */  	if (nv_device(priv)->chipset != 0x50 && @@ -925,7 +976,6 @@ nv50_graph_init(struct nouveau_object *object)  		break;  	case 0xa0:  	default: -		nv_wr32(priv, 0x402cc0, 0x00000000);  		if (nv_device(priv)->chipset == 0xa0 ||  		    nv_device(priv)->chipset == 0xaa ||  		    nv_device(priv)->chipset == 0xac) { @@ -940,10 +990,10 @@ nv50_graph_init(struct nouveau_object *object)  	/* zero out zcull regions */  	for (i = 0; i < 8; i++) { -		nv_wr32(priv, 0x402c20 + (i * 8), 0x00000000); -		nv_wr32(priv, 0x402c24 + (i * 8), 0x00000000); -		nv_wr32(priv, 0x402c28 + (i * 8), 0x00000000); -		nv_wr32(priv, 0x402c2c + (i * 8), 0x00000000); +		nv_wr32(priv, 0x402c20 + (i * 0x10), 0x00000000); +		nv_wr32(priv, 0x402c24 + (i * 0x10), 0x00000000); +		nv_wr32(priv, 0x402c28 + (i * 0x10), 0x00000000); +		nv_wr32(priv, 0x402c2c + (i * 0x10), 0x00000000);  	}  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 3f4f35cc384..aa083891635 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -23,6 +23,7 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /*******************************************************************************   * Graphics object classes @@ -146,11 +147,11 @@ nvc0_graph_context_dtor(struct nouveau_object *object)  }  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -struct nvc0_graph_init -nvc0_graph_init_regs[] = { +const struct nvc0_graph_init +nvc0_graph_init_main_0[] = {  	{ 0x400080,   1, 0x04, 0x003083c2 },  	{ 0x400088,   1, 0x04, 0x00006fe7 },  	{ 0x40008c,   1, 0x04, 0x00000000 }, @@ -165,95 +166,170 @@ nvc0_graph_init_regs[] = {  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk40xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_fe_0[] = {  	{ 0x40415c,   1, 0x04, 0x00000000 },  	{ 0x404170,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk44xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_pri_0[] = {  	{ 0x404488,   2, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk78xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_rstr2d_0[] = {  	{ 0x407808,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk60xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_pd_0[] = {  	{ 0x406024,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk58xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_ds_0[] = {  	{ 0x405844,   1, 0x04, 0x00ffffff },  	{ 0x405850,   1, 0x04, 0x00000000 },  	{ 0x405908,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk80xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_scc_0[] = {  	{ 0x40803c,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_gpc[] = { +const struct nvc0_graph_init +nvc0_graph_init_prop_0[] = {  	{ 0x4184a0,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_gpc_unk_0[] = {  	{ 0x418604,   1, 0x04, 0x00000000 },  	{ 0x418680,   1, 0x04, 0x00000000 },  	{ 0x418714,   1, 0x04, 0x80000000 },  	{ 0x418384,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_setup_0[] = {  	{ 0x418814,   3, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_crstr_0[] = {  	{ 0x418b04,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_setup_1[] = {  	{ 0x4188c8,   1, 0x04, 0x80000000 },  	{ 0x4188cc,   1, 0x04, 0x00000000 },  	{ 0x4188d0,   1, 0x04, 0x00010000 },  	{ 0x4188d4,   1, 0x04, 0x00000001 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_zcull_0[] = {  	{ 0x418910,   1, 0x04, 0x00010001 },  	{ 0x418914,   1, 0x04, 0x00000301 },  	{ 0x418918,   1, 0x04, 0x00800000 },  	{ 0x418980,   1, 0x04, 0x77777770 },  	{ 0x418984,   3, 0x04, 0x77777777 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_gpm_0[] = {  	{ 0x418c04,   1, 0x04, 0x00000000 },  	{ 0x418c88,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_gpc_unk_1[] = {  	{ 0x418d00,   1, 0x04, 0x00000000 },  	{ 0x418f08,   1, 0x04, 0x00000000 },  	{ 0x418e00,   1, 0x04, 0x00000050 },  	{ 0x418e08,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_gcc_0[] = {  	{ 0x41900c,   1, 0x04, 0x00000000 },  	{ 0x419018,   1, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvc0_graph_init_tpc[] = { +const struct nvc0_graph_init +nvc0_graph_init_tpccs_0[] = {  	{ 0x419d08,   2, 0x04, 0x00000000 },  	{ 0x419d10,   1, 0x04, 0x00000014 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_tex_0[] = {  	{ 0x419ab0,   1, 0x04, 0x00000000 },  	{ 0x419ab8,   1, 0x04, 0x000000e7 },  	{ 0x419abc,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_pe_0[] = {  	{ 0x41980c,   3, 0x04, 0x00000000 },  	{ 0x419844,   1, 0x04, 0x00000000 },  	{ 0x41984c,   1, 0x04, 0x00005bc5 },  	{ 0x419850,   4, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_l1c_0[] = {  	{ 0x419c98,   1, 0x04, 0x00000000 },  	{ 0x419ca8,   1, 0x04, 0x80000000 },  	{ 0x419cb4,   1, 0x04, 0x00000000 },  	{ 0x419cb8,   1, 0x04, 0x00008bf4 },  	{ 0x419cbc,   1, 0x04, 0x28137606 },  	{ 0x419cc0,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_wwdx_0[] = {  	{ 0x419bd4,   1, 0x04, 0x00800000 },  	{ 0x419bdc,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_tpccs_1[] = {  	{ 0x419d2c,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_mpc_0[] = {  	{ 0x419c0c,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc0_graph_init_sm_0[] = {  	{ 0x419e00,   1, 0x04, 0x00000000 },  	{ 0x419ea0,   1, 0x04, 0x00000000 },  	{ 0x419ea4,   1, 0x04, 0x00000100 }, @@ -270,8 +346,8 @@ nvc0_graph_init_tpc[] = {  	{}  }; -struct nvc0_graph_init -nvc0_graph_init_unk88xx[] = { +const struct nvc0_graph_init +nvc0_graph_init_be_0[] = {  	{ 0x40880c,   1, 0x04, 0x00000000 },  	{ 0x408910,   9, 0x04, 0x00000000 },  	{ 0x408950,   1, 0x04, 0x00000000 }, @@ -282,18 +358,64 @@ nvc0_graph_init_unk88xx[] = {  	{}  }; -struct nvc0_graph_init -nvc0_graph_tpc_0[] = { -	{ 0x50405c,   1, 0x04, 0x00000001 }, +const struct nvc0_graph_init +nvc0_graph_init_fe_1[] = { +	{ 0x4040f0,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc0_graph_init_pe_1[] = { +	{ 0x419880,   1, 0x04, 0x00000002 },  	{}  }; +static const struct nvc0_graph_pack +nvc0_graph_pack_mmio[] = { +	{ nvc0_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvc0_graph_init_pd_0 }, +	{ nvc0_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvc0_graph_init_prop_0 }, +	{ nvc0_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc0_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvc0_graph_init_gpm_0 }, +	{ nvc0_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nvc0_graph_init_tpccs_0 }, +	{ nvc0_graph_init_tex_0 }, +	{ nvc0_graph_init_pe_0 }, +	{ nvc0_graph_init_l1c_0 }, +	{ nvc0_graph_init_wwdx_0 }, +	{ nvc0_graph_init_tpccs_1 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvc0_graph_init_sm_0 }, +	{ nvc0_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{ nvc0_graph_init_pe_1 }, +	{} +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ +  void -nvc0_graph_mmio(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init) +nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)  { -	for (; init && init->count; init++) { -		u32 addr = init->addr, i; -		for (i = 0; i < init->count; i++) { +	const struct nvc0_graph_pack *pack; +	const struct nvc0_graph_init *init; + +	pack_for_each_init(init, pack, p) { +		u32 next = init->addr + init->count * init->pitch; +		u32 addr = init->addr; +		while (addr < next) {  			nv_wr32(priv, addr, init->data);  			addr += init->pitch;  		} @@ -301,49 +423,53 @@ nvc0_graph_mmio(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init)  }  void -nvc0_graph_icmd(struct nvc0_graph_priv *priv, struct nvc0_graph_init *init) +nvc0_graph_icmd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)  { -	u32 addr, data; -	int i, j; +	const struct nvc0_graph_pack *pack; +	const struct nvc0_graph_init *init; +	u32 data = 0;  	nv_wr32(priv, 0x400208, 0x80000000); -	for (i = 0; init->count; init++, i++) { -		if (!i || data != init->data) { + +	pack_for_each_init(init, pack, p) { +		u32 next = init->addr + init->count * init->pitch; +		u32 addr = init->addr; + +		if ((pack == p && init == p->init) || data != init->data) {  			nv_wr32(priv, 0x400204, init->data);  			data = init->data;  		} -		addr = init->addr; -		for (j = 0; j < init->count; j++) { +		while (addr < next) {  			nv_wr32(priv, 0x400200, addr); +			nv_wait(priv, 0x400700, 0x00000002, 0x00000000);  			addr += init->pitch; -			while (nv_rd32(priv, 0x400700) & 0x00000002) {}  		}  	} +  	nv_wr32(priv, 0x400208, 0x00000000);  }  void -nvc0_graph_mthd(struct nvc0_graph_priv *priv, struct nvc0_graph_mthd *mthds) +nvc0_graph_mthd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)  { -	struct nvc0_graph_mthd *mthd; -	struct nvc0_graph_init *init; -	int i = 0, j; -	u32 data; - -	while ((mthd = &mthds[i++]) && (init = mthd->init)) { -		u32  addr = 0x80000000 | mthd->oclass; -		for (data = 0; init->count; init++) { -			if (data != init->data) { -				nv_wr32(priv, 0x40448c, init->data); -				data = init->data; -			} +	const struct nvc0_graph_pack *pack; +	const struct nvc0_graph_init *init; +	u32 data = 0; -			addr = (addr & 0x8000ffff) | (init->addr << 14); -			for (j = 0; j < init->count; j++) { -				nv_wr32(priv, 0x404488, addr); -				addr += init->pitch << 14; -			} +	pack_for_each_init(init, pack, p) { +		u32 ctrl = 0x80000000 | pack->type; +		u32 next = init->addr + init->count * init->pitch; +		u32 addr = init->addr; + +		if ((pack == p && init == p->init) || data != init->data) { +			nv_wr32(priv, 0x40448c, init->data); +			data = init->data; +		} + +		while (addr < next) { +			nv_wr32(priv, 0x404488, ctrl | (addr << 14)); +			addr += init->pitch;  		}  	}  } @@ -663,17 +789,40 @@ nvc0_graph_ctxctl_debug(struct nvc0_graph_priv *priv)  static void  nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)  { -	u32 ustat = nv_rd32(priv, 0x409c18); +	u32 stat = nv_rd32(priv, 0x409c18); + +	if (stat & 0x00000001) { +		u32 code = nv_rd32(priv, 0x409814); +		if (code == E_BAD_FWMTHD) { +			u32 class = nv_rd32(priv, 0x409808); +			u32  addr = nv_rd32(priv, 0x40980c); +			u32  subc = (addr & 0x00070000) >> 16; +			u32  mthd = (addr & 0x00003ffc); +			u32  data = nv_rd32(priv, 0x409810); + +			nv_error(priv, "FECS MTHD subc %d class 0x%04x " +				       "mthd 0x%04x data 0x%08x\n", +				 subc, class, mthd, data); -	if (ustat & 0x00000001) -		nv_error(priv, "CTXCTL ucode error\n"); -	if (ustat & 0x00080000) -		nv_error(priv, "CTXCTL watchdog timeout\n"); -	if (ustat & ~0x00080001) -		nv_error(priv, "CTXCTL 0x%08x\n", ustat); +			nv_wr32(priv, 0x409c20, 0x00000001); +			stat &= ~0x00000001; +		} else { +			nv_error(priv, "FECS ucode error %d\n", code); +		} +	} + +	if (stat & 0x00080000) { +		nv_error(priv, "FECS watchdog timeout\n"); +		nvc0_graph_ctxctl_debug(priv); +		nv_wr32(priv, 0x409c20, 0x00080000); +		stat &= ~0x00080000; +	} -	nvc0_graph_ctxctl_debug(priv); -	nv_wr32(priv, 0x409c20, ustat); +	if (stat) { +		nv_error(priv, "FECS 0x%08x\n", stat); +		nvc0_graph_ctxctl_debug(priv); +		nv_wr32(priv, 0x409c20, stat); +	}  }  static void @@ -768,15 +917,20 @@ nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base,  			nv_wr32(priv, fuc_base + 0x0188, i >> 6);  		nv_wr32(priv, fuc_base + 0x0184, code->data[i]);  	} + +	/* code must be padded to 0x40 words */ +	for (; i & 0x3f; i++) +		nv_wr32(priv, fuc_base + 0x0184, 0);  }  static void  nvc0_graph_init_csdata(struct nvc0_graph_priv *priv, -		       struct nvc0_graph_init *init, +		       const struct nvc0_graph_pack *pack,  		       u32 falcon, u32 starstar, u32 base)  { -	u32 addr = init->addr; -	u32 next = addr; +	const struct nvc0_graph_pack *iter; +	const struct nvc0_graph_init *init; +	u32 addr = ~0, prev = ~0, xfer = 0;  	u32 star, temp;  	nv_wr32(priv, falcon + 0x01c0, 0x02000000 + starstar); @@ -786,22 +940,28 @@ nvc0_graph_init_csdata(struct nvc0_graph_priv *priv,  		star = temp;  	nv_wr32(priv, falcon + 0x01c0, 0x01000000 + star); -	do { -		if (init->addr != next) { -			while (addr < next) { -				u32 nr = min((int)(next - addr) / 4, 32); -				nv_wr32(priv, falcon + 0x01c4, -					((nr - 1) << 26) | (addr - base)); -				addr += nr * 4; -				star += 4; +	pack_for_each_init(init, iter, pack) { +		u32 head = init->addr - base; +		u32 tail = head + init->count * init->pitch; +		while (head < tail) { +			if (head != prev + 4 || xfer >= 32) { +				if (xfer) { +					u32 data = ((--xfer << 26) | addr); +					nv_wr32(priv, falcon + 0x01c4, data); +					star += 4; +				} +				addr = head; +				xfer = 0;  			} -			addr = next = init->addr; +			prev = head; +			xfer = xfer + 1; +			head = head + init->pitch;  		} -		next += init->count * 4; -	} while ((init++)->count); +	} +	nv_wr32(priv, falcon + 0x01c4, (--xfer << 26) | addr);  	nv_wr32(priv, falcon + 0x01c0, 0x01000004 + starstar); -	nv_wr32(priv, falcon + 0x01c4, star); +	nv_wr32(priv, falcon + 0x01c4, star + 4);  }  int @@ -809,7 +969,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)  {  	struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;  	struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass; -	struct nvc0_graph_init *init;  	u32 r000260;  	int i; @@ -901,6 +1060,9 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)  		}  		return 0; +	} else +	if (!oclass->fecs.ucode) { +		return -ENOSYS;  	}  	/* load HUB microcode */ @@ -916,10 +1078,6 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)  		nv_wr32(priv, 0x409184, oclass->fecs.ucode->code.data[i]);  	} -	for (i = 0; (init = cclass->hub[i]); i++) { -		nvc0_graph_init_csdata(priv, init, 0x409000, 0x000, 0x000000); -	} -  	/* load GPC microcode */  	nv_wr32(priv, 0x41a1c0, 0x01000000);  	for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++) @@ -933,12 +1091,11 @@ nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)  	}  	nv_wr32(priv, 0x000260, r000260); -	if ((init = cclass->gpc[0])) -		nvc0_graph_init_csdata(priv, init, 0x41a000, 0x000, 0x418000); -	if ((init = cclass->gpc[2])) -		nvc0_graph_init_csdata(priv, init, 0x41a000, 0x004, 0x419800); -	if ((init = cclass->gpc[3])) -		nvc0_graph_init_csdata(priv, init, 0x41a000, 0x008, 0x41be00); +	/* load register lists */ +	nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000); +	nvc0_graph_init_csdata(priv, cclass->gpc, 0x41a000, 0x000, 0x418000); +	nvc0_graph_init_csdata(priv, cclass->tpc, 0x41a000, 0x004, 0x419800); +	nvc0_graph_init_csdata(priv, cclass->ppc, 0x41a000, 0x008, 0x41be00);  	/* start HUB ucode running, it'll init the GPCs */  	nv_wr32(priv, 0x40910c, 0x00000000); @@ -985,8 +1142,7 @@ nvc0_graph_init(struct nouveau_object *object)  	nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);  	nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); -	for (i = 0; oclass->mmio[i]; i++) -		nvc0_graph_mmio(priv, oclass->mmio[i]); +	nvc0_graph_mmio(priv, oclass->mmio);  	memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));  	for (i = 0, gpc = -1; i < priv->tpc_total; i++) { @@ -1088,10 +1244,10 @@ nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname,  	int ret;  	snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); -	ret = request_firmware(&fw, f, &device->pdev->dev); +	ret = request_firmware(&fw, f, nv_device_base(device));  	if (ret) {  		snprintf(f, sizeof(f), "nouveau/%s", fwname); -		ret = request_firmware(&fw, f, &device->pdev->dev); +		ret = request_firmware(&fw, f, nv_device_base(device));  		if (ret) {  			nv_error(priv, "failed to load %s\n", fwname);  			return ret; @@ -1130,20 +1286,24 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nvc0_graph_oclass *oclass = (void *)bclass;  	struct nouveau_device *device = nv_device(parent);  	struct nvc0_graph_priv *priv; +	bool use_ext_fw, enable;  	int ret, i; -	ret = nouveau_graph_create(parent, engine, bclass, -				   (oclass->fecs.ucode != NULL), &priv); +	use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW", +				     oclass->fecs.ucode == NULL); +	enable = use_ext_fw || oclass->fecs.ucode != NULL; + +	ret = nouveau_graph_create(parent, engine, bclass, enable, &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; -	nv_subdev(priv)->unit = 0x18001000; +	nv_subdev(priv)->unit = 0x08001000;  	nv_subdev(priv)->intr = nvc0_graph_intr;  	priv->base.units = nvc0_graph_units; -	if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { +	if (use_ext_fw) {  		nv_info(priv, "using external firmware\n");  		if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||  		    nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) || @@ -1217,22 +1377,6 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -struct nvc0_graph_init * -nvc0_graph_init_mmio[] = { -	nvc0_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvc0_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvc0_graph_init_gpc, -	nvc0_graph_init_tpc, -	nvc0_graph_init_unk88xx, -	nvc0_graph_tpc_0, -	NULL -}; -  #include "fuc/hubnvc0.fuc.h"  struct nvc0_graph_ucode @@ -1264,7 +1408,7 @@ nvc0_graph_oclass = &(struct nvc0_graph_oclass) {  	},  	.cclass = &nvc0_grctx_oclass,  	.sclass =  nvc0_graph_sclass, -	.mmio = nvc0_graph_init_mmio, +	.mmio = nvc0_graph_pack_mmio,  	.fecs.ucode = &nvc0_graph_fecs_ucode,  	.gpccs.ucode = &nvc0_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index ea17a80ad7f..ffc289198dd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -38,6 +38,8 @@  #include <engine/fifo.h>  #include <engine/graph.h> +#include "fuc/os.h" +  #define GPC_MAX 32  #define TPC_MAX (GPC_MAX * 8) @@ -45,6 +47,7 @@  #define ROP_UNIT(u, r)    (0x410000 + (u) * 0x400 + (r))  #define GPC_BCAST(r)      (0x418000 + (r))  #define GPC_UNIT(t, r)    (0x500000 + (t) * 0x8000 + (r)) +#define PPC_UNIT(t, m, r) (0x503000 + (t) * 0x8000 + (m) * 0x200 + (r))  #define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))  struct nvc0_graph_data { @@ -102,8 +105,6 @@ struct nvc0_graph_chan {  	} data[4];  }; -int  nvc0_grctx_generate(struct nvc0_graph_priv *); -  int  nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *,  			     struct nouveau_oclass *, void *, u32,  			     struct nouveau_object **); @@ -117,6 +118,7 @@ int  nvc0_graph_ctor(struct nouveau_object *, struct nouveau_object *,  		     struct nouveau_object **);  void nvc0_graph_dtor(struct nouveau_object *);  int  nvc0_graph_init(struct nouveau_object *); +int  nve4_graph_fini(struct nouveau_object *, bool);  int  nve4_graph_init(struct nouveau_object *);  extern struct nouveau_oclass nvc0_graph_sclass[]; @@ -130,34 +132,14 @@ struct nvc0_graph_init {  	u32 data;  }; -struct nvc0_graph_mthd { -	u16 oclass; -	struct nvc0_graph_init *init; +struct nvc0_graph_pack { +	const struct nvc0_graph_init *init; +	u32 type;  }; -struct nvc0_grctx { -	struct nvc0_graph_priv *priv; -	struct nvc0_graph_data *data; -	struct nvc0_graph_mmio *mmio; -	int buffer_nr; -	u64 buffer[4]; -	u64 addr; -}; - -struct nvc0_grctx_oclass { -	struct nouveau_oclass base; -	/* main context generation function */ -	void  (*main)(struct nvc0_graph_priv *, struct nvc0_grctx *); -	/* context-specific modify-on-first-load list generation function */ -	void  (*mods)(struct nvc0_graph_priv *, struct nvc0_grctx *); -	void  (*unkn)(struct nvc0_graph_priv *); -	/* mmio context data */ -	struct nvc0_graph_init **hub; -	struct nvc0_graph_init **gpc; -	/* indirect context data, generated with icmds/mthds */ -	struct nvc0_graph_init *icmd; -	struct nvc0_graph_mthd *mthd; -}; +#define pack_for_each_init(init, pack, head)                                   \ +	for (pack = head; pack && pack->init; pack++)                          \ +		  for (init = pack->init; init && init->count; init++)  struct nvc0_graph_ucode {  	struct nvc0_graph_fuc code; @@ -171,7 +153,7 @@ struct nvc0_graph_oclass {  	struct nouveau_oclass base;  	struct nouveau_oclass **cclass;  	struct nouveau_oclass *sclass; -	struct nvc0_graph_init **mmio; +	const struct nvc0_graph_pack *mmio;  	struct {  		struct nvc0_graph_ucode *ucode;  	} fecs; @@ -180,109 +162,73 @@ struct nvc0_graph_oclass {  	} gpccs;  }; -void nvc0_graph_mmio(struct nvc0_graph_priv *, struct nvc0_graph_init *); -void nvc0_graph_icmd(struct nvc0_graph_priv *, struct nvc0_graph_init *); -void nvc0_graph_mthd(struct nvc0_graph_priv *, struct nvc0_graph_mthd *); +void nvc0_graph_mmio(struct nvc0_graph_priv *, const struct nvc0_graph_pack *); +void nvc0_graph_icmd(struct nvc0_graph_priv *, const struct nvc0_graph_pack *); +void nvc0_graph_mthd(struct nvc0_graph_priv *, const struct nvc0_graph_pack *);  int  nvc0_graph_init_ctxctl(struct nvc0_graph_priv *); -extern struct nvc0_graph_init nvc0_graph_init_regs[]; -extern struct nvc0_graph_init nvc0_graph_init_unk40xx[]; -extern struct nvc0_graph_init nvc0_graph_init_unk44xx[]; -extern struct nvc0_graph_init nvc0_graph_init_unk78xx[]; -extern struct nvc0_graph_init nvc0_graph_init_unk60xx[]; -extern struct nvc0_graph_init nvc0_graph_init_unk58xx[]; -extern struct nvc0_graph_init nvc0_graph_init_unk80xx[]; -extern struct nvc0_graph_init nvc0_graph_init_gpc[]; -extern struct nvc0_graph_init nvc0_graph_init_unk88xx[]; -extern struct nvc0_graph_init nvc0_graph_tpc_0[]; - -extern struct nvc0_graph_init nvc3_graph_init_unk58xx[]; - -extern struct nvc0_graph_init nvd9_graph_init_unk58xx[]; -extern struct nvc0_graph_init nvd9_graph_init_unk64xx[]; - -extern struct nvc0_graph_init nve4_graph_init_regs[]; -extern struct nvc0_graph_init nve4_graph_init_unk[]; -extern struct nvc0_graph_init nve4_graph_init_unk88xx[]; - -int  nvc0_grctx_generate(struct nvc0_graph_priv *); -void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *); -void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); -void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *); -void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *); -void nvc0_grctx_generate_r406028(struct nvc0_graph_priv *); -void nvc0_grctx_generate_r4060a8(struct nvc0_graph_priv *); -void nvc0_grctx_generate_r418bb8(struct nvc0_graph_priv *); -void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *); -void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *); - -extern struct nouveau_oclass *nvc0_grctx_oclass; -extern struct nvc0_graph_init *nvc0_grctx_init_hub[]; -extern struct nvc0_graph_init nvc0_grctx_init_base[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk40xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk44xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk46xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk47xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk60xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk64xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk78xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_unk80xx[]; -extern struct nvc0_graph_init nvc0_grctx_init_gpc_0[]; -extern struct nvc0_graph_init nvc0_grctx_init_gpc_1[]; -extern struct nvc0_graph_init nvc0_grctx_init_tpc[]; -extern struct nvc0_graph_init nvc0_grctx_init_icmd[]; -extern struct nvc0_graph_init nvd9_grctx_init_icmd[]; // - -extern struct nvc0_graph_mthd nvc0_grctx_init_mthd[]; -extern struct nvc0_graph_init nvc0_grctx_init_902d[]; -extern struct nvc0_graph_init nvc0_grctx_init_9039[]; -extern struct nvc0_graph_init nvc0_grctx_init_90c0[]; -extern struct nvc0_graph_init nvc0_grctx_init_mthd_magic[]; - -void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *); -void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *); -extern struct nouveau_oclass *nvc1_grctx_oclass; -extern struct nvc0_graph_init nvc1_grctx_init_9097[]; - -extern struct nouveau_oclass *nvc3_grctx_oclass; - -extern struct nouveau_oclass *nvc8_grctx_oclass; -extern struct nvc0_graph_init nvc8_grctx_init_9197[]; -extern struct nvc0_graph_init nvc8_grctx_init_9297[]; - -extern struct nouveau_oclass *nvd7_grctx_oclass; - -extern struct nouveau_oclass *nvd9_grctx_oclass; -extern struct nvc0_graph_init nvd9_grctx_init_rop[]; -extern struct nvc0_graph_mthd nvd9_grctx_init_mthd[]; - -void nve4_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *); -void nve4_grctx_generate_unkn(struct nvc0_graph_priv *); -extern struct nouveau_oclass *nve4_grctx_oclass; -extern struct nvc0_graph_init nve4_grctx_init_unk46xx[]; -extern struct nvc0_graph_init nve4_grctx_init_unk47xx[]; -extern struct nvc0_graph_init nve4_grctx_init_unk58xx[]; -extern struct nvc0_graph_init nve4_grctx_init_unk80xx[]; -extern struct nvc0_graph_init nve4_grctx_init_unk90xx[]; - -extern struct nouveau_oclass *nvf0_grctx_oclass; - -#define mmio_data(s,a,p) do {                                                  \ -	info->buffer[info->buffer_nr] = round_up(info->addr, (a));             \ -	info->addr = info->buffer[info->buffer_nr++] + (s);                    \ -	info->data->size = (s);                                                \ -	info->data->align = (a);                                               \ -	info->data->access = (p);                                              \ -	info->data++;                                                          \ -} while(0) - -#define mmio_list(r,d,s,b) do {                                                \ -	info->mmio->addr = (r);                                                \ -	info->mmio->data = (d);                                                \ -	info->mmio->shift = (s);                                               \ -	info->mmio->buffer = (b);                                              \ -	info->mmio++;                                                          \ -	nv_wr32(priv, (r), (d) | ((s) ? (info->buffer[(b)] >> (s)) : 0));      \ -} while(0) +/* register init value lists */ + +extern const struct nvc0_graph_init nvc0_graph_init_main_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_fe_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_pri_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_rstr2d_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_pd_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_ds_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_scc_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_prop_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_gpc_unk_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_setup_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_crstr_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_setup_1[]; +extern const struct nvc0_graph_init nvc0_graph_init_zcull_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_gpm_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_gpc_unk_1[]; +extern const struct nvc0_graph_init nvc0_graph_init_gcc_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_tpccs_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_tex_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_pe_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_l1c_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_wwdx_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_tpccs_1[]; +extern const struct nvc0_graph_init nvc0_graph_init_mpc_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_be_0[]; +extern const struct nvc0_graph_init nvc0_graph_init_fe_1[]; +extern const struct nvc0_graph_init nvc0_graph_init_pe_1[]; + +extern const struct nvc0_graph_init nvc4_graph_init_ds_0[]; +extern const struct nvc0_graph_init nvc4_graph_init_tex_0[]; +extern const struct nvc0_graph_init nvc4_graph_init_sm_0[]; + +extern const struct nvc0_graph_init nvc1_graph_init_gpc_unk_0[]; +extern const struct nvc0_graph_init nvc1_graph_init_setup_1[]; + +extern const struct nvc0_graph_init nvd9_graph_init_pd_0[]; +extern const struct nvc0_graph_init nvd9_graph_init_ds_0[]; +extern const struct nvc0_graph_init nvd9_graph_init_prop_0[]; +extern const struct nvc0_graph_init nvd9_graph_init_gpm_0[]; +extern const struct nvc0_graph_init nvd9_graph_init_gpc_unk_1[]; +extern const struct nvc0_graph_init nvd9_graph_init_tex_0[]; +extern const struct nvc0_graph_init nvd9_graph_init_sm_0[]; +extern const struct nvc0_graph_init nvd9_graph_init_fe_1[]; + +extern const struct nvc0_graph_init nvd7_graph_init_pes_0[]; +extern const struct nvc0_graph_init nvd7_graph_init_wwdx_0[]; +extern const struct nvc0_graph_init nvd7_graph_init_cbm_0[]; + +extern const struct nvc0_graph_init nve4_graph_init_main_0[]; +extern const struct nvc0_graph_init nve4_graph_init_tpccs_0[]; +extern const struct nvc0_graph_init nve4_graph_init_pe_0[]; +extern const struct nvc0_graph_init nve4_graph_init_be_0[]; +extern const struct nvc0_graph_pack nve4_graph_pack_mmio[]; + +extern const struct nvc0_graph_init nvf0_graph_init_fe_0[]; +extern const struct nvc0_graph_init nvf0_graph_init_sked_0[]; +extern const struct nvc0_graph_init nvf0_graph_init_cwd_0[]; +extern const struct nvc0_graph_init nvf0_graph_init_gpc_unk_1[]; +extern const struct nvc0_graph_init nvf0_graph_init_sm_0[]; + +extern const struct nvc0_graph_init nv108_graph_init_gpc_unk_0[]; +  #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c index bc4a469b86c..30cab0b2eba 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc1.c @@ -23,6 +23,7 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /*******************************************************************************   * Graphics object classes @@ -39,94 +40,82 @@ nvc1_graph_sclass[] = {  };  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -static struct nvc0_graph_init -nvc1_graph_init_gpc[] = { -	{ 0x4184a0,   1, 0x04, 0x00000000 }, +const struct nvc0_graph_init +nvc1_graph_init_gpc_unk_0[] = {  	{ 0x418604,   1, 0x04, 0x00000000 },  	{ 0x418680,   1, 0x04, 0x00000000 },  	{ 0x418714,   1, 0x04, 0x00000000 },  	{ 0x418384,   1, 0x04, 0x00000000 }, -	{ 0x418814,   3, 0x04, 0x00000000 }, -	{ 0x418b04,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc1_graph_init_setup_1[] = {  	{ 0x4188c8,   2, 0x04, 0x00000000 },  	{ 0x4188d0,   1, 0x04, 0x00010000 },  	{ 0x4188d4,   1, 0x04, 0x00000001 }, -	{ 0x418910,   1, 0x04, 0x00010001 }, -	{ 0x418914,   1, 0x04, 0x00000301 }, -	{ 0x418918,   1, 0x04, 0x00800000 }, -	{ 0x418980,   1, 0x04, 0x77777770 }, -	{ 0x418984,   3, 0x04, 0x77777777 }, -	{ 0x418c04,   1, 0x04, 0x00000000 }, -	{ 0x418c88,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc1_graph_init_gpc_unk_1[] = {  	{ 0x418d00,   1, 0x04, 0x00000000 },  	{ 0x418f08,   1, 0x04, 0x00000000 },  	{ 0x418e00,   1, 0x04, 0x00000003 },  	{ 0x418e08,   1, 0x04, 0x00000000 }, -	{ 0x41900c,   1, 0x04, 0x00000000 }, -	{ 0x419018,   1, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvc1_graph_init_tpc[] = { -	{ 0x419d08,   2, 0x04, 0x00000000 }, -	{ 0x419d10,   1, 0x04, 0x00000014 }, -	{ 0x419ab0,   1, 0x04, 0x00000000 }, -	{ 0x419ac8,   1, 0x04, 0x00000000 }, -	{ 0x419ab8,   1, 0x04, 0x000000e7 }, -	{ 0x419abc,   2, 0x04, 0x00000000 }, -	{ 0x41980c,   2, 0x04, 0x00000000 }, +static const struct nvc0_graph_init +nvc1_graph_init_pe_0[] = { +	{ 0x41980c,   1, 0x04, 0x00000010 }, +	{ 0x419810,   1, 0x04, 0x00000000 },  	{ 0x419814,   1, 0x04, 0x00000004 },  	{ 0x419844,   1, 0x04, 0x00000000 },  	{ 0x41984c,   1, 0x04, 0x00005bc5 },  	{ 0x419850,   4, 0x04, 0x00000000 },  	{ 0x419880,   1, 0x04, 0x00000002 }, -	{ 0x419c98,   1, 0x04, 0x00000000 }, -	{ 0x419ca8,   1, 0x04, 0x80000000 }, -	{ 0x419cb4,   1, 0x04, 0x00000000 }, -	{ 0x419cb8,   1, 0x04, 0x00008bf4 }, -	{ 0x419cbc,   1, 0x04, 0x28137606 }, -	{ 0x419cc0,   2, 0x04, 0x00000000 }, -	{ 0x419bd4,   1, 0x04, 0x00800000 }, -	{ 0x419bdc,   1, 0x04, 0x00000000 }, -	{ 0x419d2c,   1, 0x04, 0x00000000 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, -	{ 0x419e00,   1, 0x04, 0x00000000 }, -	{ 0x419ea0,   1, 0x04, 0x00000000 }, -	{ 0x419ea4,   1, 0x04, 0x00000100 }, -	{ 0x419ea8,   1, 0x04, 0x00001100 }, -	{ 0x419eac,   1, 0x04, 0x11100702 }, -	{ 0x419eb0,   1, 0x04, 0x00000003 }, -	{ 0x419eb4,   4, 0x04, 0x00000000 }, -	{ 0x419ec8,   1, 0x04, 0x0e063818 }, -	{ 0x419ecc,   1, 0x04, 0x0e060e06 }, -	{ 0x419ed0,   1, 0x04, 0x00003818 }, -	{ 0x419ed4,   1, 0x04, 0x011104f1 }, -	{ 0x419edc,   1, 0x04, 0x00000000 }, -	{ 0x419f00,   1, 0x04, 0x00000000 }, -	{ 0x419f2c,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init * -nvc1_graph_init_mmio[] = { -	nvc0_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvc3_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvc1_graph_init_gpc, -	nvc1_graph_init_tpc, -	nvc0_graph_init_unk88xx, -	nvc0_graph_tpc_0, -	NULL +static const struct nvc0_graph_pack +nvc1_graph_pack_mmio[] = { +	{ nvc0_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvc0_graph_init_pd_0 }, +	{ nvc4_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvc0_graph_init_prop_0 }, +	{ nvc1_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc1_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvc0_graph_init_gpm_0 }, +	{ nvc1_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nvc0_graph_init_tpccs_0 }, +	{ nvc4_graph_init_tex_0 }, +	{ nvc1_graph_init_pe_0 }, +	{ nvc0_graph_init_l1c_0 }, +	{ nvc0_graph_init_wwdx_0 }, +	{ nvc0_graph_init_tpccs_1 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvc4_graph_init_sm_0 }, +	{ nvc0_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{}  }; +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ +  struct nouveau_oclass *  nvc1_graph_oclass = &(struct nvc0_graph_oclass) {  	.base.handle = NV_ENGINE(GR, 0xc1), @@ -138,7 +127,7 @@ nvc1_graph_oclass = &(struct nvc0_graph_oclass) {  	},  	.cclass = &nvc1_grctx_oclass,  	.sclass = nvc1_graph_sclass, -	.mmio = nvc1_graph_init_mmio, +	.mmio = nvc1_graph_pack_mmio,  	.fecs.ucode = &nvc0_graph_fecs_ucode,  	.gpccs.ucode = &nvc0_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c index d44b3b3ee80..e82e70c5313 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc3.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc4.c @@ -23,13 +23,14 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -struct nvc0_graph_init -nvc3_graph_init_unk58xx[] = { +const struct nvc0_graph_init +nvc4_graph_init_ds_0[] = {  	{ 0x405844,   1, 0x04, 0x00ffffff },  	{ 0x405850,   1, 0x04, 0x00000000 },  	{ 0x405900,   1, 0x04, 0x00002834 }, @@ -37,29 +38,27 @@ nvc3_graph_init_unk58xx[] = {  	{}  }; -static struct nvc0_graph_init -nvc3_graph_init_tpc[] = { -	{ 0x419d08,   2, 0x04, 0x00000000 }, -	{ 0x419d10,   1, 0x04, 0x00000014 }, +const struct nvc0_graph_init +nvc4_graph_init_tex_0[] = {  	{ 0x419ab0,   1, 0x04, 0x00000000 },  	{ 0x419ac8,   1, 0x04, 0x00000000 },  	{ 0x419ab8,   1, 0x04, 0x000000e7 },  	{ 0x419abc,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvc4_graph_init_pe_0[] = {  	{ 0x41980c,   3, 0x04, 0x00000000 },  	{ 0x419844,   1, 0x04, 0x00000000 },  	{ 0x41984c,   1, 0x04, 0x00005bc5 },  	{ 0x419850,   4, 0x04, 0x00000000 },  	{ 0x419880,   1, 0x04, 0x00000002 }, -	{ 0x419c98,   1, 0x04, 0x00000000 }, -	{ 0x419ca8,   1, 0x04, 0x80000000 }, -	{ 0x419cb4,   1, 0x04, 0x00000000 }, -	{ 0x419cb8,   1, 0x04, 0x00008bf4 }, -	{ 0x419cbc,   1, 0x04, 0x28137606 }, -	{ 0x419cc0,   2, 0x04, 0x00000000 }, -	{ 0x419bd4,   1, 0x04, 0x00800000 }, -	{ 0x419bdc,   1, 0x04, 0x00000000 }, -	{ 0x419d2c,   1, 0x04, 0x00000000 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvc4_graph_init_sm_0[] = {  	{ 0x419e00,   1, 0x04, 0x00000000 },  	{ 0x419ea0,   1, 0x04, 0x00000000 },  	{ 0x419ea4,   1, 0x04, 0x00000100 }, @@ -77,24 +76,43 @@ nvc3_graph_init_tpc[] = {  	{}  }; -static struct nvc0_graph_init * -nvc3_graph_init_mmio[] = { -	nvc0_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvc3_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvc0_graph_init_gpc, -	nvc3_graph_init_tpc, -	nvc0_graph_init_unk88xx, -	nvc0_graph_tpc_0, -	NULL +static const struct nvc0_graph_pack +nvc4_graph_pack_mmio[] = { +	{ nvc0_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvc0_graph_init_pd_0 }, +	{ nvc4_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvc0_graph_init_prop_0 }, +	{ nvc0_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc0_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvc0_graph_init_gpm_0 }, +	{ nvc0_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nvc0_graph_init_tpccs_0 }, +	{ nvc4_graph_init_tex_0 }, +	{ nvc4_graph_init_pe_0 }, +	{ nvc0_graph_init_l1c_0 }, +	{ nvc0_graph_init_wwdx_0 }, +	{ nvc0_graph_init_tpccs_1 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvc4_graph_init_sm_0 }, +	{ nvc0_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{}  }; +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ +  struct nouveau_oclass * -nvc3_graph_oclass = &(struct nvc0_graph_oclass) { +nvc4_graph_oclass = &(struct nvc0_graph_oclass) {  	.base.handle = NV_ENGINE(GR, 0xc3),  	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvc0_graph_ctor, @@ -102,9 +120,9 @@ nvc3_graph_oclass = &(struct nvc0_graph_oclass) {  		.init = nvc0_graph_init,  		.fini = _nouveau_graph_fini,  	}, -	.cclass = &nvc3_grctx_oclass, +	.cclass = &nvc4_grctx_oclass,  	.sclass = nvc0_graph_sclass, -	.mmio = nvc3_graph_init_mmio, +	.mmio = nvc4_graph_pack_mmio,  	.fecs.ucode = &nvc0_graph_fecs_ucode,  	.gpccs.ucode = &nvc0_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c index 02845e56731..a6bf783e125 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc8.c @@ -23,6 +23,7 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /*******************************************************************************   * Graphics object classes @@ -40,58 +41,11 @@ nvc8_graph_sclass[] = {  };  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -static struct nvc0_graph_init -nvc8_graph_init_gpc[] = { -	{ 0x4184a0,   1, 0x04, 0x00000000 }, -	{ 0x418604,   1, 0x04, 0x00000000 }, -	{ 0x418680,   1, 0x04, 0x00000000 }, -	{ 0x418714,   1, 0x04, 0x80000000 }, -	{ 0x418384,   1, 0x04, 0x00000000 }, -	{ 0x418814,   3, 0x04, 0x00000000 }, -	{ 0x418b04,   1, 0x04, 0x00000000 }, -	{ 0x4188c8,   2, 0x04, 0x00000000 }, -	{ 0x4188d0,   1, 0x04, 0x00010000 }, -	{ 0x4188d4,   1, 0x04, 0x00000001 }, -	{ 0x418910,   1, 0x04, 0x00010001 }, -	{ 0x418914,   1, 0x04, 0x00000301 }, -	{ 0x418918,   1, 0x04, 0x00800000 }, -	{ 0x418980,   1, 0x04, 0x77777770 }, -	{ 0x418984,   3, 0x04, 0x77777777 }, -	{ 0x418c04,   1, 0x04, 0x00000000 }, -	{ 0x418c88,   1, 0x04, 0x00000000 }, -	{ 0x418d00,   1, 0x04, 0x00000000 }, -	{ 0x418f08,   1, 0x04, 0x00000000 }, -	{ 0x418e00,   1, 0x04, 0x00000050 }, -	{ 0x418e08,   1, 0x04, 0x00000000 }, -	{ 0x41900c,   1, 0x04, 0x00000000 }, -	{ 0x419018,   1, 0x04, 0x00000000 }, -	{} -}; - -static struct nvc0_graph_init -nvc8_graph_init_tpc[] = { -	{ 0x419d08,   2, 0x04, 0x00000000 }, -	{ 0x419d10,   1, 0x04, 0x00000014 }, -	{ 0x419ab0,   1, 0x04, 0x00000000 }, -	{ 0x419ab8,   1, 0x04, 0x000000e7 }, -	{ 0x419abc,   2, 0x04, 0x00000000 }, -	{ 0x41980c,   3, 0x04, 0x00000000 }, -	{ 0x419844,   1, 0x04, 0x00000000 }, -	{ 0x41984c,   1, 0x04, 0x00005bc5 }, -	{ 0x419850,   4, 0x04, 0x00000000 }, -	{ 0x419c98,   1, 0x04, 0x00000000 }, -	{ 0x419ca8,   1, 0x04, 0x80000000 }, -	{ 0x419cb4,   1, 0x04, 0x00000000 }, -	{ 0x419cb8,   1, 0x04, 0x00008bf4 }, -	{ 0x419cbc,   1, 0x04, 0x28137606 }, -	{ 0x419cc0,   2, 0x04, 0x00000000 }, -	{ 0x419bd4,   1, 0x04, 0x00800000 }, -	{ 0x419bdc,   1, 0x04, 0x00000000 }, -	{ 0x419d2c,   1, 0x04, 0x00000000 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, +static const struct nvc0_graph_init +nvc8_graph_init_sm_0[] = {  	{ 0x419e00,   1, 0x04, 0x00000000 },  	{ 0x419ea0,   1, 0x04, 0x00000000 },  	{ 0x419ea4,   1, 0x04, 0x00000100 }, @@ -108,22 +62,42 @@ nvc8_graph_init_tpc[] = {  	{}  }; -static struct nvc0_graph_init * -nvc8_graph_init_mmio[] = { -	nvc0_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvc0_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvc8_graph_init_gpc, -	nvc8_graph_init_tpc, -	nvc0_graph_init_unk88xx, -	nvc0_graph_tpc_0, -	NULL +static const struct nvc0_graph_pack +nvc8_graph_pack_mmio[] = { +	{ nvc0_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvc0_graph_init_pd_0 }, +	{ nvc0_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvc0_graph_init_prop_0 }, +	{ nvc0_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc1_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvc0_graph_init_gpm_0 }, +	{ nvc0_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nvc0_graph_init_tpccs_0 }, +	{ nvc0_graph_init_tex_0 }, +	{ nvc0_graph_init_pe_0 }, +	{ nvc0_graph_init_l1c_0 }, +	{ nvc0_graph_init_wwdx_0 }, +	{ nvc0_graph_init_tpccs_1 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvc8_graph_init_sm_0 }, +	{ nvc0_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{ nvc0_graph_init_pe_1 }, +	{}  }; +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ +  struct nouveau_oclass *  nvc8_graph_oclass = &(struct nvc0_graph_oclass) {  	.base.handle = NV_ENGINE(GR, 0xc8), @@ -135,7 +109,7 @@ nvc8_graph_oclass = &(struct nvc0_graph_oclass) {  	},  	.cclass = &nvc8_grctx_oclass,  	.sclass = nvc8_graph_sclass, -	.mmio = nvc8_graph_init_mmio, +	.mmio = nvc8_graph_pack_mmio,  	.fecs.ucode = &nvc0_graph_fecs_ucode,  	.gpccs.ucode = &nvc0_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c index 5052d7ab4d7..2a6a94e2a04 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvd7.c @@ -23,6 +23,77 @@   */  #include "nvc0.h" +#include "ctxnvc0.h" + +/******************************************************************************* + * PGRAPH register lists + ******************************************************************************/ + +static const struct nvc0_graph_init +nvd7_graph_init_pe_0[] = { +	{ 0x41980c,   1, 0x04, 0x00000010 }, +	{ 0x419844,   1, 0x04, 0x00000000 }, +	{ 0x41984c,   1, 0x04, 0x00005bc8 }, +	{ 0x419850,   3, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd7_graph_init_pes_0[] = { +	{ 0x41be04,   1, 0x04, 0x00000000 }, +	{ 0x41be08,   1, 0x04, 0x00000004 }, +	{ 0x41be0c,   1, 0x04, 0x00000000 }, +	{ 0x41be10,   1, 0x04, 0x003b8bc7 }, +	{ 0x41be14,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd7_graph_init_wwdx_0[] = { +	{ 0x41bfd4,   1, 0x04, 0x00800000 }, +	{ 0x41bfdc,   1, 0x04, 0x00000000 }, +	{ 0x41bff8,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd7_graph_init_cbm_0[] = { +	{ 0x41becc,   1, 0x04, 0x00000000 }, +	{ 0x41bee8,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_pack +nvd7_graph_pack_mmio[] = { +	{ nvc0_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvd9_graph_init_pd_0 }, +	{ nvd9_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvd9_graph_init_prop_0 }, +	{ nvc1_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc1_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvd9_graph_init_gpm_0 }, +	{ nvd9_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nvc0_graph_init_tpccs_0 }, +	{ nvd9_graph_init_tex_0 }, +	{ nvd7_graph_init_pe_0 }, +	{ nvc0_graph_init_l1c_0 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvd9_graph_init_sm_0 }, +	{ nvd7_graph_init_pes_0 }, +	{ nvd7_graph_init_wwdx_0 }, +	{ nvd7_graph_init_cbm_0 }, +	{ nvc0_graph_init_be_0 }, +	{ nvd9_graph_init_fe_1 }, +	{} +};  /*******************************************************************************   * PGRAPH engine/subdev functions @@ -48,108 +119,6 @@ nvd7_graph_gpccs_ucode = {  	.data.size = sizeof(nvd7_grgpc_data),  }; -static struct nvc0_graph_init -nvd7_graph_init_gpc[] = { -	{ 0x418408,   1, 0x04, 0x00000000 }, -	{ 0x4184a0,   1, 0x04, 0x00000000 }, -	{ 0x4184a4,   2, 0x04, 0x00000000 }, -	{ 0x418604,   1, 0x04, 0x00000000 }, -	{ 0x418680,   1, 0x04, 0x00000000 }, -	{ 0x418714,   1, 0x04, 0x00000000 }, -	{ 0x418384,   1, 0x04, 0x00000000 }, -	{ 0x418814,   3, 0x04, 0x00000000 }, -	{ 0x418b04,   1, 0x04, 0x00000000 }, -	{ 0x4188c8,   2, 0x04, 0x00000000 }, -	{ 0x4188d0,   1, 0x04, 0x00010000 }, -	{ 0x4188d4,   1, 0x04, 0x00000001 }, -	{ 0x418910,   1, 0x04, 0x00010001 }, -	{ 0x418914,   1, 0x04, 0x00000301 }, -	{ 0x418918,   1, 0x04, 0x00800000 }, -	{ 0x418980,   1, 0x04, 0x77777770 }, -	{ 0x418984,   3, 0x04, 0x77777777 }, -	{ 0x418c04,   1, 0x04, 0x00000000 }, -	{ 0x418c64,   1, 0x04, 0x00000000 }, -	{ 0x418c68,   1, 0x04, 0x00000000 }, -	{ 0x418c88,   1, 0x04, 0x00000000 }, -	{ 0x418cb4,   2, 0x04, 0x00000000 }, -	{ 0x418d00,   1, 0x04, 0x00000000 }, -	{ 0x418d28,   1, 0x04, 0x00000000 }, -	{ 0x418f00,   1, 0x04, 0x00000000 }, -	{ 0x418f08,   1, 0x04, 0x00000000 }, -	{ 0x418f20,   2, 0x04, 0x00000000 }, -	{ 0x418e00,   1, 0x04, 0x00000003 }, -	{ 0x418e08,   1, 0x04, 0x00000000 }, -	{ 0x418e1c,   1, 0x04, 0x00000000 }, -	{ 0x418e20,   1, 0x04, 0x00000000 }, -	{ 0x41900c,   1, 0x04, 0x00000000 }, -	{ 0x419018,   1, 0x04, 0x00000000 }, -	{} -}; - -static struct nvc0_graph_init -nvd7_graph_init_tpc[] = { -	{ 0x419d08,   2, 0x04, 0x00000000 }, -	{ 0x419d10,   1, 0x04, 0x00000014 }, -	{ 0x419ab0,   1, 0x04, 0x00000000 }, -	{ 0x419ac8,   1, 0x04, 0x00000000 }, -	{ 0x419ab8,   1, 0x04, 0x000000e7 }, -	{ 0x419abc,   2, 0x04, 0x00000000 }, -	{ 0x419ab4,   1, 0x04, 0x00000000 }, -	{ 0x41980c,   1, 0x04, 0x00000010 }, -	{ 0x419844,   1, 0x04, 0x00000000 }, -	{ 0x41984c,   1, 0x04, 0x00005bc8 }, -	{ 0x419850,   2, 0x04, 0x00000000 }, -	{ 0x419c98,   1, 0x04, 0x00000000 }, -	{ 0x419ca8,   1, 0x04, 0x80000000 }, -	{ 0x419cb4,   1, 0x04, 0x00000000 }, -	{ 0x419cb8,   1, 0x04, 0x00008bf4 }, -	{ 0x419cbc,   1, 0x04, 0x28137606 }, -	{ 0x419cc0,   2, 0x04, 0x00000000 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, -	{ 0x419e00,   1, 0x04, 0x00000000 }, -	{ 0x419ea0,   1, 0x04, 0x00000000 }, -	{ 0x419ea4,   1, 0x04, 0x00000100 }, -	{ 0x419ea8,   1, 0x04, 0x02001100 }, -	{ 0x419eac,   1, 0x04, 0x11100702 }, -	{ 0x419eb0,   1, 0x04, 0x00000003 }, -	{ 0x419eb4,   4, 0x04, 0x00000000 }, -	{ 0x419ec8,   1, 0x04, 0x0e063818 }, -	{ 0x419ecc,   1, 0x04, 0x0e060e06 }, -	{ 0x419ed0,   1, 0x04, 0x00003818 }, -	{ 0x419ed4,   1, 0x04, 0x011104f1 }, -	{ 0x419edc,   1, 0x04, 0x00000000 }, -	{ 0x419f00,   1, 0x04, 0x00000000 }, -	{ 0x419f2c,   1, 0x04, 0x00000000 }, -	{} -}; - -static struct nvc0_graph_init -nvd7_graph_init_tpc_0[] = { -	{ 0x40402c,   1, 0x04, 0x00000000 }, -	{ 0x4040f0,   1, 0x04, 0x00000000 }, -	{ 0x404174,   1, 0x04, 0x00000000 }, -	{ 0x503018,   1, 0x04, 0x00000001 }, -	{} -}; - -static struct nvc0_graph_init * -nvd7_graph_init_mmio[] = { -	nvc0_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvd9_graph_init_unk64xx, -	nvd9_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvd7_graph_init_gpc, -	nvd7_graph_init_tpc, -	nve4_graph_init_unk, -	nvc0_graph_init_unk88xx, -	nvd7_graph_init_tpc_0, -	NULL -}; -  struct nouveau_oclass *  nvd7_graph_oclass = &(struct nvc0_graph_oclass) {  	.base.handle = NV_ENGINE(GR, 0xd7), @@ -161,7 +130,7 @@ nvd7_graph_oclass = &(struct nvc0_graph_oclass) {  	},  	.cclass = &nvd7_grctx_oclass,  	.sclass = nvc8_graph_sclass, -	.mmio = nvd7_graph_init_mmio, +	.mmio = nvd7_graph_pack_mmio,  	.fecs.ucode = &nvd7_graph_fecs_ucode,  	.gpccs.ucode = &nvd7_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c index 652098e0df3..00fdf202fb9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvd9.c @@ -23,76 +23,70 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -struct nvc0_graph_init -nvd9_graph_init_unk64xx[] = { +const struct nvc0_graph_init +nvd9_graph_init_pd_0[] = { +	{ 0x406024,   1, 0x04, 0x00000000 },  	{ 0x4064f0,   3, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nvd9_graph_init_unk58xx[] = { +const struct nvc0_graph_init +nvd9_graph_init_ds_0[] = {  	{ 0x405844,   1, 0x04, 0x00ffffff },  	{ 0x405850,   1, 0x04, 0x00000000 },  	{ 0x405900,   1, 0x04, 0x00002834 },  	{ 0x405908,   1, 0x04, 0x00000000 }, -	{ 0x405928,   1, 0x04, 0x00000000 }, -	{ 0x40592c,   1, 0x04, 0x00000000 }, +	{ 0x405928,   2, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvd9_graph_init_gpc[] = { +const struct nvc0_graph_init +nvd9_graph_init_prop_0[] = {  	{ 0x418408,   1, 0x04, 0x00000000 }, -	{ 0x4184a0,   1, 0x04, 0x00000000 }, -	{ 0x4184a4,   2, 0x04, 0x00000000 }, -	{ 0x418604,   1, 0x04, 0x00000000 }, -	{ 0x418680,   1, 0x04, 0x00000000 }, -	{ 0x418714,   1, 0x04, 0x00000000 }, -	{ 0x418384,   1, 0x04, 0x00000000 }, -	{ 0x418814,   3, 0x04, 0x00000000 }, -	{ 0x418b04,   1, 0x04, 0x00000000 }, -	{ 0x4188c8,   2, 0x04, 0x00000000 }, -	{ 0x4188d0,   1, 0x04, 0x00010000 }, -	{ 0x4188d4,   1, 0x04, 0x00000001 }, -	{ 0x418910,   1, 0x04, 0x00010001 }, -	{ 0x418914,   1, 0x04, 0x00000301 }, -	{ 0x418918,   1, 0x04, 0x00800000 }, -	{ 0x418980,   1, 0x04, 0x77777770 }, -	{ 0x418984,   3, 0x04, 0x77777777 }, +	{ 0x4184a0,   3, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_graph_init_gpm_0[] = {  	{ 0x418c04,   1, 0x04, 0x00000000 }, -	{ 0x418c64,   1, 0x04, 0x00000000 }, -	{ 0x418c68,   1, 0x04, 0x00000000 }, +	{ 0x418c64,   2, 0x04, 0x00000000 },  	{ 0x418c88,   1, 0x04, 0x00000000 },  	{ 0x418cb4,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_graph_init_gpc_unk_1[] = {  	{ 0x418d00,   1, 0x04, 0x00000000 }, -	{ 0x418d28,   1, 0x04, 0x00000000 }, -	{ 0x418d2c,   1, 0x04, 0x00000000 }, +	{ 0x418d28,   2, 0x04, 0x00000000 },  	{ 0x418f00,   1, 0x04, 0x00000000 },  	{ 0x418f08,   1, 0x04, 0x00000000 },  	{ 0x418f20,   2, 0x04, 0x00000000 },  	{ 0x418e00,   1, 0x04, 0x00000003 },  	{ 0x418e08,   1, 0x04, 0x00000000 }, -	{ 0x418e1c,   1, 0x04, 0x00000000 }, -	{ 0x418e20,   1, 0x04, 0x00000000 }, -	{ 0x41900c,   1, 0x04, 0x00000000 }, -	{ 0x419018,   1, 0x04, 0x00000000 }, +	{ 0x418e1c,   2, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvd9_graph_init_tpc[] = { -	{ 0x419d08,   2, 0x04, 0x00000000 }, -	{ 0x419d10,   1, 0x04, 0x00000014 }, +const struct nvc0_graph_init +nvd9_graph_init_tex_0[] = {  	{ 0x419ab0,   1, 0x04, 0x00000000 },  	{ 0x419ac8,   1, 0x04, 0x00000000 },  	{ 0x419ab8,   1, 0x04, 0x000000e7 },  	{ 0x419abc,   2, 0x04, 0x00000000 },  	{ 0x419ab4,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_graph_init_pe_0[] = {  	{ 0x41980c,   1, 0x04, 0x00000010 },  	{ 0x419810,   1, 0x04, 0x00000000 },  	{ 0x419814,   1, 0x04, 0x00000004 }, @@ -100,20 +94,26 @@ nvd9_graph_init_tpc[] = {  	{ 0x41984c,   1, 0x04, 0x0000a918 },  	{ 0x419850,   4, 0x04, 0x00000000 },  	{ 0x419880,   1, 0x04, 0x00000002 }, -	{ 0x419c98,   1, 0x04, 0x00000000 }, -	{ 0x419ca8,   1, 0x04, 0x80000000 }, -	{ 0x419cb4,   1, 0x04, 0x00000000 }, -	{ 0x419cb8,   1, 0x04, 0x00008bf4 }, -	{ 0x419cbc,   1, 0x04, 0x28137606 }, -	{ 0x419cc0,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_graph_init_wwdx_0[] = {  	{ 0x419bd4,   1, 0x04, 0x00800000 },  	{ 0x419bdc,   1, 0x04, 0x00000000 }, -	{ 0x419bf8,   1, 0x04, 0x00000000 }, -	{ 0x419bfc,   1, 0x04, 0x00000000 }, +	{ 0x419bf8,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvd9_graph_init_tpccs_1[] = {  	{ 0x419d2c,   1, 0x04, 0x00000000 }, -	{ 0x419d48,   1, 0x04, 0x00000000 }, -	{ 0x419d4c,   1, 0x04, 0x00000000 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, +	{ 0x419d48,   2, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvd9_graph_init_sm_0[] = {  	{ 0x419e00,   1, 0x04, 0x00000000 },  	{ 0x419ea0,   1, 0x04, 0x00000000 },  	{ 0x419ea4,   1, 0x04, 0x00000100 }, @@ -131,23 +131,49 @@ nvd9_graph_init_tpc[] = {  	{}  }; -static struct nvc0_graph_init * -nvd9_graph_init_mmio[] = { -	nvc0_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvd9_graph_init_unk64xx, -	nvd9_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvd9_graph_init_gpc, -	nvd9_graph_init_tpc, -	nvc0_graph_init_unk88xx, -	nvc0_graph_tpc_0, -	NULL +const struct nvc0_graph_init +nvd9_graph_init_fe_1[] = { +	{ 0x40402c,   1, 0x04, 0x00000000 }, +	{ 0x4040f0,   1, 0x04, 0x00000000 }, +	{ 0x404174,   1, 0x04, 0x00000000 }, +	{}  }; +static const struct nvc0_graph_pack +nvd9_graph_pack_mmio[] = { +	{ nvc0_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvd9_graph_init_pd_0 }, +	{ nvd9_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvd9_graph_init_prop_0 }, +	{ nvc1_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc1_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvd9_graph_init_gpm_0 }, +	{ nvd9_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nvc0_graph_init_tpccs_0 }, +	{ nvd9_graph_init_tex_0 }, +	{ nvd9_graph_init_pe_0 }, +	{ nvc0_graph_init_l1c_0 }, +	{ nvd9_graph_init_wwdx_0 }, +	{ nvd9_graph_init_tpccs_1 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvd9_graph_init_sm_0 }, +	{ nvc0_graph_init_be_0 }, +	{ nvd9_graph_init_fe_1 }, +	{} +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ +  struct nouveau_oclass *  nvd9_graph_oclass = &(struct nvc0_graph_oclass) {  	.base.handle = NV_ENGINE(GR, 0xd9), @@ -159,7 +185,7 @@ nvd9_graph_oclass = &(struct nvc0_graph_oclass) {  	},  	.cclass = &nvd9_grctx_oclass,  	.sclass = nvc8_graph_sclass, -	.mmio = nvd9_graph_init_mmio, +	.mmio = nvd9_graph_pack_mmio,  	.fecs.ucode = &nvc0_graph_fecs_ucode,  	.gpccs.ucode = &nvc0_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c index 05ec09c8851..51e0c075ad3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve4.c @@ -23,6 +23,7 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /*******************************************************************************   * Graphics object classes @@ -38,11 +39,11 @@ nve4_graph_sclass[] = {  };  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -struct nvc0_graph_init -nve4_graph_init_regs[] = { +const struct nvc0_graph_init +nve4_graph_init_main_0[] = {  	{ 0x400080,   1, 0x04, 0x003083c2 },  	{ 0x400088,   1, 0x04, 0x0001ffe7 },  	{ 0x40008c,   1, 0x04, 0x00000000 }, @@ -57,81 +58,59 @@ nve4_graph_init_regs[] = {  	{}  }; -static struct nvc0_graph_init -nve4_graph_init_unk58xx[] = { +static const struct nvc0_graph_init +nve4_graph_init_ds_0[] = {  	{ 0x405844,   1, 0x04, 0x00ffffff },  	{ 0x405850,   1, 0x04, 0x00000000 },  	{ 0x405900,   1, 0x04, 0x0000ff34 },  	{ 0x405908,   1, 0x04, 0x00000000 }, -	{ 0x405928,   1, 0x04, 0x00000000 }, -	{ 0x40592c,   1, 0x04, 0x00000000 }, +	{ 0x405928,   2, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nve4_graph_init_unk70xx[] = { +static const struct nvc0_graph_init +nve4_graph_init_sked_0[] = {  	{ 0x407010,   1, 0x04, 0x00000000 },  	{}  }; -struct nvc0_graph_init -nve4_graph_init_unk5bxx[] = { +static const struct nvc0_graph_init +nve4_graph_init_cwd_0[] = {  	{ 0x405b50,   1, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nve4_graph_init_gpc[] = { -	{ 0x418408,   1, 0x04, 0x00000000 }, -	{ 0x4184a0,   1, 0x04, 0x00000000 }, -	{ 0x4184a4,   2, 0x04, 0x00000000 }, -	{ 0x418604,   1, 0x04, 0x00000000 }, -	{ 0x418680,   1, 0x04, 0x00000000 }, -	{ 0x418714,   1, 0x04, 0x00000000 }, -	{ 0x418384,   1, 0x04, 0x00000000 }, -	{ 0x418814,   3, 0x04, 0x00000000 }, -	{ 0x418b04,   1, 0x04, 0x00000000 }, -	{ 0x4188c8,   2, 0x04, 0x00000000 }, -	{ 0x4188d0,   1, 0x04, 0x00010000 }, -	{ 0x4188d4,   1, 0x04, 0x00000001 }, -	{ 0x418910,   1, 0x04, 0x00010001 }, -	{ 0x418914,   1, 0x04, 0x00000301 }, -	{ 0x418918,   1, 0x04, 0x00800000 }, -	{ 0x418980,   1, 0x04, 0x77777770 }, -	{ 0x418984,   3, 0x04, 0x77777777 }, -	{ 0x418c04,   1, 0x04, 0x00000000 }, -	{ 0x418c64,   1, 0x04, 0x00000000 }, -	{ 0x418c68,   1, 0x04, 0x00000000 }, -	{ 0x418c88,   1, 0x04, 0x00000000 }, -	{ 0x418cb4,   2, 0x04, 0x00000000 }, +static const struct nvc0_graph_init +nve4_graph_init_gpc_unk_1[] = {  	{ 0x418d00,   1, 0x04, 0x00000000 }, -	{ 0x418d28,   1, 0x04, 0x00000000 }, -	{ 0x418d2c,   1, 0x04, 0x00000000 }, +	{ 0x418d28,   2, 0x04, 0x00000000 },  	{ 0x418f00,   1, 0x04, 0x00000000 },  	{ 0x418f08,   1, 0x04, 0x00000000 },  	{ 0x418f20,   2, 0x04, 0x00000000 },  	{ 0x418e00,   1, 0x04, 0x00000060 },  	{ 0x418e08,   1, 0x04, 0x00000000 }, -	{ 0x418e1c,   1, 0x04, 0x00000000 }, -	{ 0x418e20,   1, 0x04, 0x00000000 }, -	{ 0x41900c,   1, 0x04, 0x00000000 }, -	{ 0x419018,   1, 0x04, 0x00000000 }, +	{ 0x418e1c,   2, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nve4_graph_init_tpc[] = { +const struct nvc0_graph_init +nve4_graph_init_tpccs_0[] = {  	{ 0x419d0c,   1, 0x04, 0x00000000 },  	{ 0x419d10,   1, 0x04, 0x00000014 }, -	{ 0x419ab0,   1, 0x04, 0x00000000 }, -	{ 0x419ac8,   1, 0x04, 0x00000000 }, -	{ 0x419ab8,   1, 0x04, 0x000000e7 }, -	{ 0x419abc,   2, 0x04, 0x00000000 }, -	{ 0x419ab4,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nve4_graph_init_pe_0[] = {  	{ 0x41980c,   1, 0x04, 0x00000010 },  	{ 0x419844,   1, 0x04, 0x00000000 },  	{ 0x419850,   1, 0x04, 0x00000004 },  	{ 0x419854,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_graph_init_l1c_0[] = {  	{ 0x419c98,   1, 0x04, 0x00000000 },  	{ 0x419ca8,   1, 0x04, 0x00000000 },  	{ 0x419cb0,   1, 0x04, 0x01000000 }, @@ -141,39 +120,25 @@ nve4_graph_init_tpc[] = {  	{ 0x419cbc,   1, 0x04, 0x28137646 },  	{ 0x419cc0,   2, 0x04, 0x00000000 },  	{ 0x419c80,   1, 0x04, 0x00020232 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nve4_graph_init_sm_0[] = {  	{ 0x419e00,   1, 0x04, 0x00000000 },  	{ 0x419ea0,   1, 0x04, 0x00000000 },  	{ 0x419ee4,   1, 0x04, 0x00000000 },  	{ 0x419ea4,   1, 0x04, 0x00000100 },  	{ 0x419ea8,   1, 0x04, 0x00000000 }, -	{ 0x419eb4,   1, 0x04, 0x00000000 }, -	{ 0x419eb8,   3, 0x04, 0x00000000 }, +	{ 0x419eb4,   4, 0x04, 0x00000000 },  	{ 0x419edc,   1, 0x04, 0x00000000 },  	{ 0x419f00,   1, 0x04, 0x00000000 },  	{ 0x419f74,   1, 0x04, 0x00000555 },  	{}  }; -struct nvc0_graph_init -nve4_graph_init_unk[] = { -	{ 0x41be04,   1, 0x04, 0x00000000 }, -	{ 0x41be08,   1, 0x04, 0x00000004 }, -	{ 0x41be0c,   1, 0x04, 0x00000000 }, -	{ 0x41be10,   1, 0x04, 0x003b8bc7 }, -	{ 0x41be14,   2, 0x04, 0x00000000 }, -	{ 0x41bfd4,   1, 0x04, 0x00800000 }, -	{ 0x41bfdc,   1, 0x04, 0x00000000 }, -	{ 0x41bff8,   1, 0x04, 0x00000000 }, -	{ 0x41bffc,   1, 0x04, 0x00000000 }, -	{ 0x41becc,   1, 0x04, 0x00000000 }, -	{ 0x41bee8,   1, 0x04, 0x00000000 }, -	{ 0x41beec,   1, 0x04, 0x00000000 }, -	{} -}; - -struct nvc0_graph_init -nve4_graph_init_unk88xx[] = { +const struct nvc0_graph_init +nve4_graph_init_be_0[] = {  	{ 0x40880c,   1, 0x04, 0x00000000 },  	{ 0x408850,   1, 0x04, 0x00000004 },  	{ 0x408910,   9, 0x04, 0x00000000 }, @@ -186,6 +151,67 @@ nve4_graph_init_unk88xx[] = {  	{}  }; +const struct nvc0_graph_pack +nve4_graph_pack_mmio[] = { +	{ nve4_graph_init_main_0 }, +	{ nvc0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvd9_graph_init_pd_0 }, +	{ nve4_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nve4_graph_init_sked_0 }, +	{ nve4_graph_init_cwd_0 }, +	{ nvd9_graph_init_prop_0 }, +	{ nvc1_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc1_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvd9_graph_init_gpm_0 }, +	{ nve4_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nve4_graph_init_tpccs_0 }, +	{ nvd9_graph_init_tex_0 }, +	{ nve4_graph_init_pe_0 }, +	{ nve4_graph_init_l1c_0 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nve4_graph_init_sm_0 }, +	{ nvd7_graph_init_pes_0 }, +	{ nvd7_graph_init_wwdx_0 }, +	{ nvd7_graph_init_cbm_0 }, +	{ nve4_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{} +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ + +int +nve4_graph_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvc0_graph_priv *priv = (void *)object; + +	/*XXX: this is a nasty hack to power on gr on certain boards +	 *     where it's disabled by therm, somehow.  ideally it'd +	 *     be nice to know when we should be doing this, and why, +	 *     but, it's yet to be determined.  for now we test for +	 *     the particular mmio error that occurs in the situation, +	 *     and then bash therm in the way nvidia do. +	 */ +	nv_mask(priv, 0x000200, 0x08001000, 0x08001000); +	nv_rd32(priv, 0x000200); +	if (nv_rd32(priv, 0x400700) == 0xbadf1000) { +		nv_mask(priv, 0x000200, 0x08001000, 0x00000000); +		nv_rd32(priv, 0x000200); +		nv_mask(priv, 0x020004, 0xc0000000, 0x40000000); +	} + +	return nouveau_graph_fini(&priv->base, suspend); +} +  int  nve4_graph_init(struct nouveau_object *object)  { @@ -210,8 +236,7 @@ nve4_graph_init(struct nouveau_object *object)  	nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);  	nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8); -	for (i = 0; oclass->mmio[i]; i++) -		nvc0_graph_mmio(priv, oclass->mmio[i]); +	nvc0_graph_mmio(priv, oclass->mmio);  	nv_wr32(priv, GPC_UNIT(0, 0x3018), 0x00000001); @@ -298,25 +323,6 @@ nve4_graph_init(struct nouveau_object *object)  	return nvc0_graph_init_ctxctl(priv);  } -static struct nvc0_graph_init * -nve4_graph_init_mmio[] = { -	nve4_graph_init_regs, -	nvc0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvd9_graph_init_unk64xx, -	nve4_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nve4_graph_init_unk70xx, -	nve4_graph_init_unk5bxx, -	nve4_graph_init_gpc, -	nve4_graph_init_tpc, -	nve4_graph_init_unk, -	nve4_graph_init_unk88xx, -	NULL -}; -  #include "fuc/hubnve0.fuc.h"  static struct nvc0_graph_ucode @@ -344,11 +350,11 @@ nve4_graph_oclass = &(struct nvc0_graph_oclass) {  		.ctor = nvc0_graph_ctor,  		.dtor = nvc0_graph_dtor,  		.init = nve4_graph_init, -		.fini = _nouveau_graph_fini, +		.fini = nve4_graph_fini,  	},  	.cclass = &nve4_grctx_oclass,  	.sclass = nve4_graph_sclass, -	.mmio = nve4_graph_init_mmio, +	.mmio = nve4_graph_pack_mmio,  	.fecs.ucode = &nve4_graph_fecs_ucode,  	.gpccs.ucode = &nve4_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c index 2f0ac783223..c96762122b9 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvf0.c @@ -23,6 +23,7 @@   */  #include "nvc0.h" +#include "ctxnvc0.h"  /*******************************************************************************   * Graphics object classes @@ -38,86 +39,57 @@ nvf0_graph_sclass[] = {  };  /******************************************************************************* - * PGRAPH engine/subdev functions + * PGRAPH register lists   ******************************************************************************/ -static struct nvc0_graph_init -nvf0_graph_init_unk40xx[] = { +const struct nvc0_graph_init +nvf0_graph_init_fe_0[] = {  	{ 0x40415c,   1, 0x04, 0x00000000 },  	{ 0x404170,   1, 0x04, 0x00000000 },  	{ 0x4041b4,   1, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvf0_graph_init_unk58xx[] = { +static const struct nvc0_graph_init +nvf0_graph_init_ds_0[] = {  	{ 0x405844,   1, 0x04, 0x00ffffff },  	{ 0x405850,   1, 0x04, 0x00000000 },  	{ 0x405900,   1, 0x04, 0x0000ff00 },  	{ 0x405908,   1, 0x04, 0x00000000 }, -	{ 0x405928,   1, 0x04, 0x00000000 }, -	{ 0x40592c,   1, 0x04, 0x00000000 }, +	{ 0x405928,   2, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvf0_graph_init_unk70xx[] = { +const struct nvc0_graph_init +nvf0_graph_init_sked_0[] = {  	{ 0x407010,   1, 0x04, 0x00000000 },  	{ 0x407040,   1, 0x04, 0x80440424 },  	{ 0x407048,   1, 0x04, 0x0000000a },  	{}  }; -static struct nvc0_graph_init -nvf0_graph_init_unk5bxx[] = { +const struct nvc0_graph_init +nvf0_graph_init_cwd_0[] = {  	{ 0x405b44,   1, 0x04, 0x00000000 },  	{ 0x405b50,   1, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvf0_graph_init_gpc[] = { -	{ 0x418408,   1, 0x04, 0x00000000 }, -	{ 0x4184a0,   1, 0x04, 0x00000000 }, -	{ 0x4184a4,   2, 0x04, 0x00000000 }, -	{ 0x418604,   1, 0x04, 0x00000000 }, -	{ 0x418680,   1, 0x04, 0x00000000 }, -	{ 0x418714,   1, 0x04, 0x00000000 }, -	{ 0x418384,   1, 0x04, 0x00000000 }, -	{ 0x418814,   3, 0x04, 0x00000000 }, -	{ 0x418b04,   1, 0x04, 0x00000000 }, -	{ 0x4188c8,   2, 0x04, 0x00000000 }, -	{ 0x4188d0,   1, 0x04, 0x00010000 }, -	{ 0x4188d4,   1, 0x04, 0x00000001 }, -	{ 0x418910,   1, 0x04, 0x00010001 }, -	{ 0x418914,   1, 0x04, 0x00000301 }, -	{ 0x418918,   1, 0x04, 0x00800000 }, -	{ 0x418980,   1, 0x04, 0x77777770 }, -	{ 0x418984,   3, 0x04, 0x77777777 }, -	{ 0x418c04,   1, 0x04, 0x00000000 }, -	{ 0x418c64,   1, 0x04, 0x00000000 }, -	{ 0x418c68,   1, 0x04, 0x00000000 }, -	{ 0x418c88,   1, 0x04, 0x00000000 }, -	{ 0x418cb4,   2, 0x04, 0x00000000 }, +const struct nvc0_graph_init +nvf0_graph_init_gpc_unk_1[] = {  	{ 0x418d00,   1, 0x04, 0x00000000 }, -	{ 0x418d28,   1, 0x04, 0x00000000 }, -	{ 0x418d2c,   1, 0x04, 0x00000000 }, +	{ 0x418d28,   2, 0x04, 0x00000000 },  	{ 0x418f00,   1, 0x04, 0x00000400 },  	{ 0x418f08,   1, 0x04, 0x00000000 }, -	{ 0x418f20,   1, 0x04, 0x00000000 }, -	{ 0x418f24,   1, 0x04, 0x00000000 }, +	{ 0x418f20,   2, 0x04, 0x00000000 },  	{ 0x418e00,   1, 0x04, 0x00000000 },  	{ 0x418e08,   1, 0x04, 0x00000000 },  	{ 0x418e1c,   2, 0x04, 0x00000000 }, -	{ 0x41900c,   1, 0x04, 0x00000000 }, -	{ 0x419018,   1, 0x04, 0x00000000 },  	{}  }; -static struct nvc0_graph_init -nvf0_graph_init_tpc[] = { -	{ 0x419d0c,   1, 0x04, 0x00000000 }, -	{ 0x419d10,   1, 0x04, 0x00000014 }, +static const struct nvc0_graph_init +nvf0_graph_init_tex_0[] = {  	{ 0x419ab0,   1, 0x04, 0x00000000 },  	{ 0x419ac8,   1, 0x04, 0x00000000 },  	{ 0x419ab8,   1, 0x04, 0x000000e7 }, @@ -125,10 +97,11 @@ nvf0_graph_init_tpc[] = {  	{ 0x419abc,   2, 0x04, 0x00000000 },  	{ 0x419ab4,   1, 0x04, 0x00000000 },  	{ 0x419aa8,   2, 0x04, 0x00000000 }, -	{ 0x41980c,   1, 0x04, 0x00000010 }, -	{ 0x419844,   1, 0x04, 0x00000000 }, -	{ 0x419850,   1, 0x04, 0x00000004 }, -	{ 0x419854,   2, 0x04, 0x00000000 }, +	{} +}; + +static const struct nvc0_graph_init +nvf0_graph_init_l1c_0[] = {  	{ 0x419c98,   1, 0x04, 0x00000000 },  	{ 0x419ca8,   1, 0x04, 0x00000000 },  	{ 0x419cb0,   1, 0x04, 0x01000000 }, @@ -139,7 +112,11 @@ nvf0_graph_init_tpc[] = {  	{ 0x419cc0,   2, 0x04, 0x00000000 },  	{ 0x419c80,   1, 0x04, 0x00020230 },  	{ 0x419ccc,   2, 0x04, 0x00000000 }, -	{ 0x419c0c,   1, 0x04, 0x00000000 }, +	{} +}; + +const struct nvc0_graph_init +nvf0_graph_init_sm_0[] = {  	{ 0x419e00,   1, 0x04, 0x00000080 },  	{ 0x419ea0,   1, 0x04, 0x00000000 },  	{ 0x419ee4,   1, 0x04, 0x00000000 }, @@ -155,6 +132,44 @@ nvf0_graph_init_tpc[] = {  	{}  }; +static const struct nvc0_graph_pack +nvf0_graph_pack_mmio[] = { +	{ nve4_graph_init_main_0 }, +	{ nvf0_graph_init_fe_0 }, +	{ nvc0_graph_init_pri_0 }, +	{ nvc0_graph_init_rstr2d_0 }, +	{ nvd9_graph_init_pd_0 }, +	{ nvf0_graph_init_ds_0 }, +	{ nvc0_graph_init_scc_0 }, +	{ nvf0_graph_init_sked_0 }, +	{ nvf0_graph_init_cwd_0 }, +	{ nvd9_graph_init_prop_0 }, +	{ nvc1_graph_init_gpc_unk_0 }, +	{ nvc0_graph_init_setup_0 }, +	{ nvc0_graph_init_crstr_0 }, +	{ nvc1_graph_init_setup_1 }, +	{ nvc0_graph_init_zcull_0 }, +	{ nvd9_graph_init_gpm_0 }, +	{ nvf0_graph_init_gpc_unk_1 }, +	{ nvc0_graph_init_gcc_0 }, +	{ nve4_graph_init_tpccs_0 }, +	{ nvf0_graph_init_tex_0 }, +	{ nve4_graph_init_pe_0 }, +	{ nvf0_graph_init_l1c_0 }, +	{ nvc0_graph_init_mpc_0 }, +	{ nvf0_graph_init_sm_0 }, +	{ nvd7_graph_init_pes_0 }, +	{ nvd7_graph_init_wwdx_0 }, +	{ nvd7_graph_init_cbm_0 }, +	{ nve4_graph_init_be_0 }, +	{ nvc0_graph_init_fe_1 }, +	{} +}; + +/******************************************************************************* + * PGRAPH engine/subdev functions + ******************************************************************************/ +  static int  nvf0_graph_fini(struct nouveau_object *object, bool suspend)  { @@ -192,25 +207,6 @@ nvf0_graph_fini(struct nouveau_object *object, bool suspend)  	return nouveau_graph_fini(&priv->base, suspend);  } -static struct nvc0_graph_init * -nvf0_graph_init_mmio[] = { -	nve4_graph_init_regs, -	nvf0_graph_init_unk40xx, -	nvc0_graph_init_unk44xx, -	nvc0_graph_init_unk78xx, -	nvc0_graph_init_unk60xx, -	nvd9_graph_init_unk64xx, -	nvf0_graph_init_unk58xx, -	nvc0_graph_init_unk80xx, -	nvf0_graph_init_unk70xx, -	nvf0_graph_init_unk5bxx, -	nvf0_graph_init_gpc, -	nvf0_graph_init_tpc, -	nve4_graph_init_unk, -	nve4_graph_init_unk88xx, -	NULL -}; -  #include "fuc/hubnvf0.fuc.h"  static struct nvc0_graph_ucode @@ -242,7 +238,7 @@ nvf0_graph_oclass = &(struct nvc0_graph_oclass) {  	},  	.cclass = &nvf0_grctx_oclass,  	.sclass =  nvf0_graph_sclass, -	.mmio = nvf0_graph_init_mmio, -	.fecs.ucode = 0 ? &nvf0_graph_fecs_ucode : NULL, +	.mmio = nvf0_graph_pack_mmio, +	.fecs.ucode = &nvf0_graph_fecs_ucode,  	.gpccs.ucode = &nvf0_graph_gpccs_ucode,  }.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index c1900430130..7eb6d94c84e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -34,16 +34,7 @@  #include <engine/fifo.h>  #include <engine/mpeg.h> -#include <engine/graph/nv40.h> - -struct nv31_mpeg_priv { -	struct nouveau_mpeg base; -	atomic_t refcount; -}; - -struct nv31_mpeg_chan { -	struct nouveau_object base; -}; +#include <engine/mpeg/nv31.h>  /*******************************************************************************   * MPEG object classes @@ -89,18 +80,18 @@ nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)  	if (mthd == 0x0190) {  		/* DMA_CMD */ -		nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000)); +		nv_mask(priv, 0x00b300, 0x00010000, (dma0 & 0x00030000) ? 0x00010000 : 0);  		nv_wr32(priv, 0x00b334, base);  		nv_wr32(priv, 0x00b324, size);  	} else  	if (mthd == 0x01a0) {  		/* DMA_DATA */ -		nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); +		nv_mask(priv, 0x00b300, 0x00020000, (dma0 & 0x00030000) ? 0x00020000 : 0);  		nv_wr32(priv, 0x00b360, base);  		nv_wr32(priv, 0x00b364, size);  	} else {  		/* DMA_IMAGE, VRAM only */ -		if (dma0 & 0x000c0000) +		if (dma0 & 0x00030000)  			return -EINVAL;  		nv_wr32(priv, 0x00b370, base); @@ -110,7 +101,7 @@ nv31_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)  	return 0;  } -static struct nouveau_ofuncs +struct nouveau_ofuncs  nv31_mpeg_ofuncs = {  	.ctor = nv31_mpeg_object_ctor,  	.dtor = _nouveau_gpuobj_dtor, @@ -146,16 +137,23 @@ nv31_mpeg_context_ctor(struct nouveau_object *parent,  {  	struct nv31_mpeg_priv *priv = (void *)engine;  	struct nv31_mpeg_chan *chan; +	unsigned long flags;  	int ret; -	if (!atomic_add_unless(&priv->refcount, 1, 1)) -		return -EBUSY; -  	ret = nouveau_object_create(parent, engine, oclass, 0, &chan);  	*pobject = nv_object(chan);  	if (ret)  		return ret; +	spin_lock_irqsave(&nv_engine(priv)->lock, flags); +	if (priv->chan) { +		spin_unlock_irqrestore(&nv_engine(priv)->lock, flags); +		nouveau_object_destroy(&chan->base); +		*pobject = NULL; +		return -EBUSY; +	} +	priv->chan = chan; +	spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);  	return 0;  } @@ -164,11 +162,15 @@ nv31_mpeg_context_dtor(struct nouveau_object *object)  {  	struct nv31_mpeg_priv *priv = (void *)object->engine;  	struct nv31_mpeg_chan *chan = (void *)object; -	atomic_dec(&priv->refcount); +	unsigned long flags; + +	spin_lock_irqsave(&nv_engine(priv)->lock, flags); +	priv->chan = NULL; +	spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);  	nouveau_object_destroy(&chan->base);  } -static struct nouveau_oclass +struct nouveau_oclass  nv31_mpeg_cclass = {  	.handle = NV_ENGCTX(MPEG, 0x31),  	.ofuncs = &(struct nouveau_ofuncs) { @@ -197,21 +199,19 @@ nv31_mpeg_tile_prog(struct nouveau_engine *engine, int i)  void  nv31_mpeg_intr(struct nouveau_subdev *subdev)  { +	struct nv31_mpeg_priv *priv = (void *)subdev;  	struct nouveau_fifo *pfifo = nouveau_fifo(subdev); -	struct nouveau_engine *engine = nv_engine(subdev); -	struct nouveau_object *engctx;  	struct nouveau_handle *handle; -	struct nv31_mpeg_priv *priv = (void *)subdev; -	u32 inst = nv_rd32(priv, 0x00b318) & 0x000fffff; +	struct nouveau_object *engctx;  	u32 stat = nv_rd32(priv, 0x00b100);  	u32 type = nv_rd32(priv, 0x00b230);  	u32 mthd = nv_rd32(priv, 0x00b234);  	u32 data = nv_rd32(priv, 0x00b238);  	u32 show = stat; -	int chid; +	unsigned long flags; -	engctx = nouveau_engctx_get(engine, inst); -	chid   = pfifo->chid(pfifo, engctx); +	spin_lock_irqsave(&nv_engine(priv)->lock, flags); +	engctx = nv_object(priv->chan);  	if (stat & 0x01000000) {  		/* happens on initial binding of the object */ @@ -220,7 +220,7 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev)  			show &= ~0x01000000;  		} -		if (type == 0x00000010) { +		if (type == 0x00000010 && engctx) {  			handle = nouveau_handle_get_class(engctx, 0x3174);  			if (handle && !nv_call(handle->object, mthd, data))  				show &= ~0x01000000; @@ -232,13 +232,12 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev)  	nv_wr32(priv, 0x00b230, 0x00000001);  	if (show) { -		nv_error(priv, -			 "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n", -			 chid, inst << 4, nouveau_client_name(engctx), stat, -			 type, mthd, data); +		nv_error(priv, "ch %d [%s] 0x%08x 0x%08x 0x%08x 0x%08x\n", +			 pfifo->chid(pfifo, engctx), +			 nouveau_client_name(engctx), stat, type, mthd, data);  	} -	nouveau_engctx_put(engctx); +	spin_unlock_irqrestore(&nv_engine(priv)->lock, flags);  }  static int @@ -284,10 +283,7 @@ nv31_mpeg_init(struct nouveau_object *object)  	/* PMPEG init */  	nv_wr32(priv, 0x00b32c, 0x00000000);  	nv_wr32(priv, 0x00b314, 0x00000100); -	if (nv_device(priv)->chipset >= 0x40 && nv44_graph_class(priv)) -		nv_wr32(priv, 0x00b220, 0x00000044); -	else -		nv_wr32(priv, 0x00b220, 0x00000031); +	nv_wr32(priv, 0x00b220, 0x00000031);  	nv_wr32(priv, 0x00b300, 0x02001ec1);  	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h new file mode 100644 index 00000000000..d08629d0b6a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.h @@ -0,0 +1,15 @@ +#ifndef __NV31_MPEG_H__ +#define __NV31_MPEG_H__ + +#include <engine/mpeg.h> + +struct nv31_mpeg_chan { +	struct nouveau_object base; +}; + +struct nv31_mpeg_priv { +	struct nouveau_mpeg base; +	struct nv31_mpeg_chan *chan; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c index dd6196072e9..d4e7ec0ba68 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c @@ -31,66 +31,63 @@  #include <subdev/instmem.h>  #include <engine/mpeg.h> -#include <engine/graph/nv40.h> - -struct nv40_mpeg_priv { -	struct nouveau_mpeg base; -}; - -struct nv40_mpeg_chan { -	struct nouveau_mpeg_chan base; -}; +#include <engine/mpeg/nv31.h>  /******************************************************************************* - * PMPEG context + * MPEG object classes   ******************************************************************************/  static int -nv40_mpeg_context_ctor(struct nouveau_object *parent, -		       struct nouveau_object *engine, -		       struct nouveau_oclass *oclass, void *data, u32 size, -		       struct nouveau_object **pobject) +nv40_mpeg_mthd_dma(struct nouveau_object *object, u32 mthd, void *arg, u32 len)  { -	struct nv40_mpeg_chan *chan; -	int ret; - -	ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL, -					  264 * 4, 16, -					  NVOBJ_FLAG_ZERO_ALLOC, &chan); -	*pobject = nv_object(chan); -	if (ret) -		return ret; +	struct nouveau_instmem *imem = nouveau_instmem(object); +	struct nv31_mpeg_priv *priv = (void *)object->engine; +	u32 inst = *(u32 *)arg << 4; +	u32 dma0 = nv_ro32(imem, inst + 0); +	u32 dma1 = nv_ro32(imem, inst + 4); +	u32 dma2 = nv_ro32(imem, inst + 8); +	u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); +	u32 size = dma1 + 1; + +	/* only allow linear DMA objects */ +	if (!(dma0 & 0x00002000)) +		return -EINVAL; + +	if (mthd == 0x0190) { +		/* DMA_CMD */ +		nv_mask(priv, 0x00b300, 0x00030000, (dma0 & 0x00030000)); +		nv_wr32(priv, 0x00b334, base); +		nv_wr32(priv, 0x00b324, size); +	} else +	if (mthd == 0x01a0) { +		/* DMA_DATA */ +		nv_mask(priv, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); +		nv_wr32(priv, 0x00b360, base); +		nv_wr32(priv, 0x00b364, size); +	} else { +		/* DMA_IMAGE, VRAM only */ +		if (dma0 & 0x00030000) +			return -EINVAL; + +		nv_wr32(priv, 0x00b370, base); +		nv_wr32(priv, 0x00b374, size); +	} -	nv_wo32(&chan->base.base, 0x78, 0x02001ec1);  	return 0;  } -static int -nv40_mpeg_context_fini(struct nouveau_object *object, bool suspend) -{ - -	struct nv40_mpeg_priv *priv = (void *)object->engine; -	struct nv40_mpeg_chan *chan = (void *)object; -	u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4; - -	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000); -	if (nv_rd32(priv, 0x00b318) == inst) -		nv_mask(priv, 0x00b318, 0x80000000, 0x00000000); -	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); -	return 0; -} +static struct nouveau_omthds +nv40_mpeg_omthds[] = { +	{ 0x0190, 0x0190, nv40_mpeg_mthd_dma }, +	{ 0x01a0, 0x01a0, nv40_mpeg_mthd_dma }, +	{ 0x01b0, 0x01b0, nv40_mpeg_mthd_dma }, +	{} +}; -static struct nouveau_oclass -nv40_mpeg_cclass = { -	.handle = NV_ENGCTX(MPEG, 0x40), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv40_mpeg_context_ctor, -		.dtor = _nouveau_mpeg_context_dtor, -		.init = _nouveau_mpeg_context_init, -		.fini = nv40_mpeg_context_fini, -		.rd32 = _nouveau_mpeg_context_rd32, -		.wr32 = _nouveau_mpeg_context_wr32, -	}, +struct nouveau_oclass +nv40_mpeg_sclass[] = { +	{ 0x3174, &nv31_mpeg_ofuncs, nv40_mpeg_omthds }, +	{}  };  /******************************************************************************* @@ -100,7 +97,7 @@ nv40_mpeg_cclass = {  static void  nv40_mpeg_intr(struct nouveau_subdev *subdev)  { -	struct nv40_mpeg_priv *priv = (void *)subdev; +	struct nv31_mpeg_priv *priv = (void *)subdev;  	u32 stat;  	if ((stat = nv_rd32(priv, 0x00b100))) @@ -117,7 +114,7 @@ nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size,  	       struct nouveau_object **pobject)  { -	struct nv40_mpeg_priv *priv; +	struct nv31_mpeg_priv *priv;  	int ret;  	ret = nouveau_mpeg_create(parent, engine, oclass, &priv); @@ -127,8 +124,8 @@ nv40_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	nv_subdev(priv)->unit = 0x00000002;  	nv_subdev(priv)->intr = nv40_mpeg_intr; -	nv_engine(priv)->cclass = &nv40_mpeg_cclass; -	nv_engine(priv)->sclass = nv31_mpeg_sclass; +	nv_engine(priv)->cclass = &nv31_mpeg_cclass; +	nv_engine(priv)->sclass = nv40_mpeg_sclass;  	nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c new file mode 100644 index 00000000000..3d8c2133e0e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv44.c @@ -0,0 +1,194 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <core/os.h> +#include <core/class.h> +#include <core/client.h> +#include <core/engctx.h> +#include <core/handle.h> + +#include <subdev/fb.h> +#include <subdev/timer.h> +#include <subdev/instmem.h> + +#include <engine/fifo.h> +#include <engine/mpeg.h> + +struct nv44_mpeg_priv { +	struct nouveau_mpeg base; +}; + +struct nv44_mpeg_chan { +	struct nouveau_mpeg_chan base; +}; + +/******************************************************************************* + * PMPEG context + ******************************************************************************/ + +static int +nv44_mpeg_context_ctor(struct nouveau_object *parent, +		       struct nouveau_object *engine, +		       struct nouveau_oclass *oclass, void *data, u32 size, +		       struct nouveau_object **pobject) +{ +	struct nv44_mpeg_chan *chan; +	int ret; + +	ret = nouveau_mpeg_context_create(parent, engine, oclass, NULL, +					  264 * 4, 16, +					  NVOBJ_FLAG_ZERO_ALLOC, &chan); +	*pobject = nv_object(chan); +	if (ret) +		return ret; + +	nv_wo32(&chan->base.base, 0x78, 0x02001ec1); +	return 0; +} + +static int +nv44_mpeg_context_fini(struct nouveau_object *object, bool suspend) +{ + +	struct nv44_mpeg_priv *priv = (void *)object->engine; +	struct nv44_mpeg_chan *chan = (void *)object; +	u32 inst = 0x80000000 | nv_gpuobj(chan)->addr >> 4; + +	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000000); +	if (nv_rd32(priv, 0x00b318) == inst) +		nv_mask(priv, 0x00b318, 0x80000000, 0x00000000); +	nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); +	return 0; +} + +static struct nouveau_oclass +nv44_mpeg_cclass = { +	.handle = NV_ENGCTX(MPEG, 0x44), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv44_mpeg_context_ctor, +		.dtor = _nouveau_mpeg_context_dtor, +		.init = _nouveau_mpeg_context_init, +		.fini = nv44_mpeg_context_fini, +		.rd32 = _nouveau_mpeg_context_rd32, +		.wr32 = _nouveau_mpeg_context_wr32, +	}, +}; + +/******************************************************************************* + * PMPEG engine/subdev functions + ******************************************************************************/ + +static void +nv44_mpeg_intr(struct nouveau_subdev *subdev) +{ +	struct nouveau_fifo *pfifo = nouveau_fifo(subdev); +	struct nouveau_engine *engine = nv_engine(subdev); +	struct nouveau_object *engctx; +	struct nouveau_handle *handle; +	struct nv44_mpeg_priv *priv = (void *)subdev; +	u32 inst = nv_rd32(priv, 0x00b318) & 0x000fffff; +	u32 stat = nv_rd32(priv, 0x00b100); +	u32 type = nv_rd32(priv, 0x00b230); +	u32 mthd = nv_rd32(priv, 0x00b234); +	u32 data = nv_rd32(priv, 0x00b238); +	u32 show = stat; +	int chid; + +	engctx = nouveau_engctx_get(engine, inst); +	chid   = pfifo->chid(pfifo, engctx); + +	if (stat & 0x01000000) { +		/* happens on initial binding of the object */ +		if (type == 0x00000020 && mthd == 0x0000) { +			nv_mask(priv, 0x00b308, 0x00000000, 0x00000000); +			show &= ~0x01000000; +		} + +		if (type == 0x00000010) { +			handle = nouveau_handle_get_class(engctx, 0x3174); +			if (handle && !nv_call(handle->object, mthd, data)) +				show &= ~0x01000000; +			nouveau_handle_put(handle); +		} +	} + +	nv_wr32(priv, 0x00b100, stat); +	nv_wr32(priv, 0x00b230, 0x00000001); + +	if (show) { +		nv_error(priv, +			 "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n", +			 chid, inst << 4, nouveau_client_name(engctx), stat, +			 type, mthd, data); +	} + +	nouveau_engctx_put(engctx); +} + +static void +nv44_mpeg_me_intr(struct nouveau_subdev *subdev) +{ +	struct nv44_mpeg_priv *priv = (void *)subdev; +	u32 stat; + +	if ((stat = nv_rd32(priv, 0x00b100))) +		nv44_mpeg_intr(subdev); + +	if ((stat = nv_rd32(priv, 0x00b800))) { +		nv_error(priv, "PMSRCH 0x%08x\n", stat); +		nv_wr32(priv, 0x00b800, stat); +	} +} + +static int +nv44_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct nv44_mpeg_priv *priv; +	int ret; + +	ret = nouveau_mpeg_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	nv_subdev(priv)->unit = 0x00000002; +	nv_subdev(priv)->intr = nv44_mpeg_me_intr; +	nv_engine(priv)->cclass = &nv44_mpeg_cclass; +	nv_engine(priv)->sclass = nv40_mpeg_sclass; +	nv_engine(priv)->tile_prog = nv31_mpeg_tile_prog; +	return 0; +} + +struct nouveau_oclass +nv44_mpeg_oclass = { +	.handle = NV_ENGINE(MPEG, 0x44), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv44_mpeg_ctor, +		.dtor = _nouveau_mpeg_dtor, +		.init = nv31_mpeg_init, +		.fini = _nouveau_mpeg_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c new file mode 100644 index 00000000000..e9c5e51943e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/base.c @@ -0,0 +1,449 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <core/option.h> +#include <core/class.h> + +#include <subdev/clock.h> + +#include "priv.h" + +#define QUAD_MASK 0x0f +#define QUAD_FREE 0x01 + +static struct nouveau_perfsig * +nouveau_perfsig_find_(struct nouveau_perfdom *dom, const char *name, u32 size) +{ +	char path[64]; +	int i; + +	if (name[0] != '/') { +		for (i = 0; i < dom->signal_nr; i++) { +			if ( dom->signal[i].name && +			    !strncmp(name, dom->signal[i].name, size)) +				return &dom->signal[i]; +		} +	} else { +		for (i = 0; i < dom->signal_nr; i++) { +			snprintf(path, sizeof(path), "/%s/%02x", dom->name, i); +			if (!strncmp(name, path, size)) +				return &dom->signal[i]; +		} +	} + +	return NULL; +} + +struct nouveau_perfsig * +nouveau_perfsig_find(struct nouveau_perfmon *ppm, const char *name, u32 size, +		     struct nouveau_perfdom **pdom) +{ +	struct nouveau_perfdom *dom = *pdom; +	struct nouveau_perfsig *sig; + +	if (dom == NULL) { +		list_for_each_entry(dom, &ppm->domains, head) { +			sig = nouveau_perfsig_find_(dom, name, size); +			if (sig) { +				*pdom = dom; +				return sig; +			} +		} + +		return NULL; +	} + +	return nouveau_perfsig_find_(dom, name, size); +} + +struct nouveau_perfctr * +nouveau_perfsig_wrap(struct nouveau_perfmon *ppm, const char *name, +		     struct nouveau_perfdom **pdom) +{ +	struct nouveau_perfsig *sig; +	struct nouveau_perfctr *ctr; + +	sig = nouveau_perfsig_find(ppm, name, strlen(name), pdom); +	if (!sig) +		return NULL; + +	ctr = kzalloc(sizeof(*ctr), GFP_KERNEL); +	if (ctr) { +		ctr->signal[0] = sig; +		ctr->logic_op = 0xaaaa; +	} + +	return ctr; +} + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ +static int +nouveau_perfctr_query(struct nouveau_object *object, u32 mthd, +		      void *data, u32 size) +{ +	struct nouveau_device *device = nv_device(object); +	struct nouveau_perfmon *ppm = (void *)object->engine; +	struct nouveau_perfdom *dom = NULL, *chk; +	struct nv_perfctr_query *args = data; +	const bool all = nouveau_boolopt(device->cfgopt, "NvPmShowAll", false); +	const bool raw = nouveau_boolopt(device->cfgopt, "NvPmUnnamed", all); +	const char *name; +	int tmp = 0, di, si; +	char path[64]; + +	if (size < sizeof(*args)) +		return -EINVAL; + +	di = (args->iter & 0xff000000) >> 24; +	si = (args->iter & 0x00ffffff) - 1; + +	list_for_each_entry(chk, &ppm->domains, head) { +		if (tmp++ == di) { +			dom = chk; +			break; +		} +	} + +	if (dom == NULL || si >= (int)dom->signal_nr) +		return -EINVAL; + +	if (si >= 0) { +		if (raw || !(name = dom->signal[si].name)) { +			snprintf(path, sizeof(path), "/%s/%02x", dom->name, si); +			name = path; +		} + +		if (args->name) +			strncpy(args->name, name, args->size); +		args->size = strlen(name) + 1; +	} + +	do { +		while (++si < dom->signal_nr) { +			if (all || dom->signal[si].name) { +				args->iter = (di << 24) | ++si; +				return 0; +			} +		} +		si = -1; +		di = di + 1; +		dom = list_entry(dom->head.next, typeof(*dom), head); +	} while (&dom->head != &ppm->domains); + +	args->iter = 0xffffffff; +	return 0; +} + +static int +nouveau_perfctr_sample(struct nouveau_object *object, u32 mthd, +		       void *data, u32 size) +{ +	struct nouveau_perfmon *ppm = (void *)object->engine; +	struct nouveau_perfctr *ctr, *tmp; +	struct nouveau_perfdom *dom; +	struct nv_perfctr_sample *args = data; + +	if (size < sizeof(*args)) +		return -EINVAL; +	ppm->sequence++; + +	list_for_each_entry(dom, &ppm->domains, head) { +		/* sample previous batch of counters */ +		if (dom->quad != QUAD_MASK) { +			dom->func->next(ppm, dom); +			tmp = NULL; +			while (!list_empty(&dom->list)) { +				ctr = list_first_entry(&dom->list, +							typeof(*ctr), head); +				if (ctr->slot < 0) break; +				if ( tmp && tmp == ctr) break; +				if (!tmp) tmp = ctr; +				dom->func->read(ppm, dom, ctr); +				ctr->slot  = -1; +				list_move_tail(&ctr->head, &dom->list); +			} +		} + +		dom->quad = QUAD_MASK; + +		/* setup next batch of counters for sampling */ +		list_for_each_entry(ctr, &dom->list, head) { +			ctr->slot = ffs(dom->quad) - 1; +			if (ctr->slot < 0) +				break; +			dom->quad &= ~(QUAD_FREE << ctr->slot); +			dom->func->init(ppm, dom, ctr); +		} + +		if (dom->quad != QUAD_MASK) +			dom->func->next(ppm, dom); +	} + +	return 0; +} + +static int +nouveau_perfctr_read(struct nouveau_object *object, u32 mthd, +		     void *data, u32 size) +{ +	struct nouveau_perfctr *ctr = (void *)object; +	struct nv_perfctr_read *args = data; + +	if (size < sizeof(*args)) +		return -EINVAL; +	if (!ctr->clk) +		return -EAGAIN; + +	args->clk = ctr->clk; +	args->ctr = ctr->ctr; +	return 0; +} + +static void +nouveau_perfctr_dtor(struct nouveau_object *object) +{ +	struct nouveau_perfctr *ctr = (void *)object; +	if (ctr->head.next) +		list_del(&ctr->head); +	nouveau_object_destroy(&ctr->base); +} + +static int +nouveau_perfctr_ctor(struct nouveau_object *parent, +		     struct nouveau_object *engine, +		     struct nouveau_oclass *oclass, void *data, u32 size, +		     struct nouveau_object **pobject) +{ +	struct nouveau_perfmon *ppm = (void *)engine; +	struct nouveau_perfdom *dom = NULL; +	struct nouveau_perfsig *sig[4] = {}; +	struct nouveau_perfctr *ctr; +	struct nv_perfctr_class *args = data; +	int ret, i; + +	if (size < sizeof(*args)) +		return -EINVAL; + +	for (i = 0; i < ARRAY_SIZE(args->signal) && args->signal[i].name; i++) { +		sig[i] = nouveau_perfsig_find(ppm, args->signal[i].name, +					      args->signal[i].size, &dom); +		if (!sig[i]) +			return -EINVAL; +	} + +	ret = nouveau_object_create(parent, engine, oclass, 0, &ctr); +	*pobject = nv_object(ctr); +	if (ret) +		return ret; + +	ctr->slot = -1; +	ctr->logic_op = args->logic_op; +	ctr->signal[0] = sig[0]; +	ctr->signal[1] = sig[1]; +	ctr->signal[2] = sig[2]; +	ctr->signal[3] = sig[3]; +	if (dom) +		list_add_tail(&ctr->head, &dom->list); +	return 0; +} + +static struct nouveau_ofuncs +nouveau_perfctr_ofuncs = { +	.ctor = nouveau_perfctr_ctor, +	.dtor = nouveau_perfctr_dtor, +	.init = nouveau_object_init, +	.fini = nouveau_object_fini, +}; + +static struct nouveau_omthds +nouveau_perfctr_omthds[] = { +	{ NV_PERFCTR_QUERY, NV_PERFCTR_QUERY, nouveau_perfctr_query }, +	{ NV_PERFCTR_SAMPLE, NV_PERFCTR_SAMPLE, nouveau_perfctr_sample }, +	{ NV_PERFCTR_READ, NV_PERFCTR_READ, nouveau_perfctr_read }, +	{} +}; + +struct nouveau_oclass +nouveau_perfmon_sclass[] = { +	{ .handle = NV_PERFCTR_CLASS, +	  .ofuncs = &nouveau_perfctr_ofuncs, +	  .omthds =  nouveau_perfctr_omthds, +	}, +	{}, +}; + +/******************************************************************************* + * PPM context + ******************************************************************************/ +static void +nouveau_perfctx_dtor(struct nouveau_object *object) +{ +	struct nouveau_perfmon *ppm = (void *)object->engine; +	mutex_lock(&nv_subdev(ppm)->mutex); +	ppm->context = NULL; +	mutex_unlock(&nv_subdev(ppm)->mutex); +} + +static int +nouveau_perfctx_ctor(struct nouveau_object *parent, +		     struct nouveau_object *engine, +		     struct nouveau_oclass *oclass, void *data, u32 size, +		     struct nouveau_object **pobject) +{ +	struct nouveau_perfmon *ppm = (void *)engine; +	struct nouveau_perfctx *ctx; +	int ret; + +	ret = nouveau_engctx_create(parent, engine, oclass, NULL, +				    0, 0, 0, &ctx); +	*pobject = nv_object(ctx); +	if (ret) +		return ret; + +	mutex_lock(&nv_subdev(ppm)->mutex); +	if (ppm->context == NULL) +		ppm->context = ctx; +	mutex_unlock(&nv_subdev(ppm)->mutex); + +	if (ctx != ppm->context) +		return -EBUSY; + +	return 0; +} + +struct nouveau_oclass +nouveau_perfmon_cclass = { +	.handle = NV_ENGCTX(PERFMON, 0x00), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nouveau_perfctx_ctor, +		.dtor = nouveau_perfctx_dtor, +		.init = _nouveau_engctx_init, +		.fini = _nouveau_engctx_fini, +	}, +}; + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ +int +nouveau_perfdom_new(struct nouveau_perfmon *ppm, const char *name, u32 mask, +		    u32 base, u32 size_unit, u32 size_domain, +		    const struct nouveau_specdom *spec) +{ +	const struct nouveau_specdom *sdom; +	const struct nouveau_specsig *ssig; +	struct nouveau_perfdom *dom; +	int i; + +	for (i = 0; i == 0 || mask; i++) { +		u32 addr = base + (i * size_unit); +		if (i && !(mask & (1 << i))) +			continue; + +		sdom = spec; +		while (sdom->signal_nr) { +			dom = kzalloc(sizeof(*dom) + sdom->signal_nr * +				      sizeof(*dom->signal), GFP_KERNEL); +			if (!dom) +				return -ENOMEM; + +			if (mask) { +				snprintf(dom->name, sizeof(dom->name), +					 "%s/%02x/%02x", name, i, +					 (int)(sdom - spec)); +			} else { +				snprintf(dom->name, sizeof(dom->name), +					 "%s/%02x", name, (int)(sdom - spec)); +			} + +			list_add_tail(&dom->head, &ppm->domains); +			INIT_LIST_HEAD(&dom->list); +			dom->func = sdom->func; +			dom->addr = addr; +			dom->quad = QUAD_MASK; +			dom->signal_nr = sdom->signal_nr; + +			ssig = (sdom++)->signal; +			while (ssig->name) { +				dom->signal[ssig->signal].name = ssig->name; +				ssig++; +			} + +			addr += size_domain; +		} + +		mask &= ~(1 << i); +	} + +	return 0; +} + +int +_nouveau_perfmon_fini(struct nouveau_object *object, bool suspend) +{ +	struct nouveau_perfmon *ppm = (void *)object; +	return nouveau_engine_fini(&ppm->base, suspend); +} + +int +_nouveau_perfmon_init(struct nouveau_object *object) +{ +	struct nouveau_perfmon *ppm = (void *)object; +	return nouveau_engine_init(&ppm->base); +} + +void +_nouveau_perfmon_dtor(struct nouveau_object *object) +{ +	struct nouveau_perfmon *ppm = (void *)object; +	struct nouveau_perfdom *dom, *tmp; + +	list_for_each_entry_safe(dom, tmp, &ppm->domains, head) { +		list_del(&dom->head); +		kfree(dom); +	} + +	nouveau_engine_destroy(&ppm->base); +} + +int +nouveau_perfmon_create_(struct nouveau_object *parent, +			struct nouveau_object *engine, +			struct nouveau_oclass *oclass, +			int length, void **pobject) +{ +	struct nouveau_perfmon *ppm; +	int ret; + +	ret = nouveau_engine_create_(parent, engine, oclass, true, "PPM", +				     "perfmon", length, pobject); +	ppm = *pobject; +	if (ret) +		return ret; + +	INIT_LIST_HEAD(&ppm->domains); +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c new file mode 100644 index 00000000000..50696cc7b7d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/daemon.c @@ -0,0 +1,109 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "priv.h" + +static void +pwr_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, +		 struct nouveau_perfctr *ctr) +{ +	u32 mask = 0x00000000; +	u32 ctrl = 0x00000001; +	int i; + +	for (i = 0; i < ARRAY_SIZE(ctr->signal) && ctr->signal[i]; i++) +		mask |= 1 << (ctr->signal[i] - dom->signal); + +	nv_wr32(ppm, 0x10a504 + (ctr->slot * 0x10), mask); +	nv_wr32(ppm, 0x10a50c + (ctr->slot * 0x10), ctrl); +	nv_wr32(ppm, 0x10a50c + (ppm->last * 0x10), 0x00000003); +} + +static void +pwr_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, +		 struct nouveau_perfctr *ctr) +{ +	ctr->ctr = ppm->pwr[ctr->slot]; +	ctr->clk = ppm->pwr[ppm->last]; +} + +static void +pwr_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom) +{ +	int i; + +	for (i = 0; i <= ppm->last; i++) { +		ppm->pwr[i] = nv_rd32(ppm, 0x10a508 + (i * 0x10)); +		nv_wr32(ppm, 0x10a508 + (i * 0x10), 0x80000000); +	} +} + +static const struct nouveau_funcdom +pwr_perfctr_func = { +	.init = pwr_perfctr_init, +	.read = pwr_perfctr_read, +	.next = pwr_perfctr_next, +}; + +const struct nouveau_specdom +nva3_perfmon_pwr[] = { +	{ 0x20, (const struct nouveau_specsig[]) { +			{ 0x00, "pwr_gr_idle" }, +			{ 0x04, "pwr_bsp_idle" }, +			{ 0x05, "pwr_vp_idle" }, +			{ 0x06, "pwr_ppp_idle" }, +			{ 0x13, "pwr_ce0_idle" }, +			{} +		}, &pwr_perfctr_func }, +	{} +}; + +const struct nouveau_specdom +nvc0_perfmon_pwr[] = { +	{ 0x20, (const struct nouveau_specsig[]) { +			{ 0x00, "pwr_gr_idle" }, +			{ 0x04, "pwr_bsp_idle" }, +			{ 0x05, "pwr_vp_idle" }, +			{ 0x06, "pwr_ppp_idle" }, +			{ 0x13, "pwr_ce0_idle" }, +			{ 0x14, "pwr_ce1_idle" }, +			{} +		}, &pwr_perfctr_func }, +	{} +}; + +const struct nouveau_specdom +nve0_perfmon_pwr[] = { +	{ 0x20, (const struct nouveau_specsig[]) { +			{ 0x00, "pwr_gr_idle" }, +			{ 0x04, "pwr_bsp_idle" }, +			{ 0x05, "pwr_vp_idle" }, +			{ 0x06, "pwr_ppp_idle" }, +			{ 0x13, "pwr_ce0_idle" }, +			{ 0x14, "pwr_ce1_idle" }, +			{ 0x15, "pwr_ce2_idle" }, +			{} +		}, &pwr_perfctr_func }, +	{} +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c new file mode 100644 index 00000000000..b2a10785adb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.c @@ -0,0 +1,143 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv40.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static void +nv40_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, +		  struct nouveau_perfctr *ctr) +{ +	struct nv40_perfmon_priv *priv = (void *)ppm; +	struct nv40_perfmon_cntr *cntr = (void *)ctr; +	u32 log = ctr->logic_op; +	u32 src = 0x00000000; +	int i; + +	for (i = 0; i < 4 && ctr->signal[i]; i++) +		src |= (ctr->signal[i] - dom->signal) << (i * 8); + +	nv_wr32(priv, 0x00a7c0 + dom->addr, 0x00000001); +	nv_wr32(priv, 0x00a400 + dom->addr + (cntr->base.slot * 0x40), src); +	nv_wr32(priv, 0x00a420 + dom->addr + (cntr->base.slot * 0x40), log); +} + +static void +nv40_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, +		  struct nouveau_perfctr *ctr) +{ +	struct nv40_perfmon_priv *priv = (void *)ppm; +	struct nv40_perfmon_cntr *cntr = (void *)ctr; + +	switch (cntr->base.slot) { +	case 0: cntr->base.ctr = nv_rd32(priv, 0x00a700 + dom->addr); break; +	case 1: cntr->base.ctr = nv_rd32(priv, 0x00a6c0 + dom->addr); break; +	case 2: cntr->base.ctr = nv_rd32(priv, 0x00a680 + dom->addr); break; +	case 3: cntr->base.ctr = nv_rd32(priv, 0x00a740 + dom->addr); break; +	} +	cntr->base.clk = nv_rd32(priv, 0x00a600 + dom->addr); +} + +static void +nv40_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom) +{ +	struct nv40_perfmon_priv *priv = (void *)ppm; +	if (priv->sequence != ppm->sequence) { +		nv_wr32(priv, 0x400084, 0x00000020); +		priv->sequence = ppm->sequence; +	} +} + +const struct nouveau_funcdom +nv40_perfctr_func = { +	.init = nv40_perfctr_init, +	.read = nv40_perfctr_read, +	.next = nv40_perfctr_next, +}; + +static const struct nouveau_specdom +nv40_perfmon[] = { +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{} +}; + +int +nv40_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **pobject) +{ +	struct nv40_perfmon_oclass *mclass = (void *)oclass; +	struct nv40_perfmon_priv *priv; +	int ret; + +	ret = nouveau_perfmon_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	ret = nouveau_perfdom_new(&priv->base, "pm", 0, 0, 0, 4, mclass->doms); +	if (ret) +		return ret; + +	nv_engine(priv)->cclass = &nouveau_perfmon_cclass; +	nv_engine(priv)->sclass =  nouveau_perfmon_sclass; +	return 0; +} + +struct nouveau_oclass * +nv40_perfmon_oclass = &(struct nv40_perfmon_oclass) { +	.base.handle = NV_ENGINE(PERFMON, 0x40), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv40_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = _nouveau_perfmon_fini, +	}, +	.doms = nv40_perfmon, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h new file mode 100644 index 00000000000..1b5792d1df1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv40.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_PM_NV40_H__ +#define __NVKM_PM_NV40_H__ + +#include "priv.h" + +struct nv40_perfmon_oclass { +	struct nouveau_oclass base; +	const struct nouveau_specdom *doms; +}; + +struct nv40_perfmon_priv { +	struct nouveau_perfmon base; +	u32 sequence; +}; + +int nv40_perfmon_ctor(struct nouveau_object *, struct nouveau_object *, +		      struct nouveau_oclass *, void *data, u32 size, +		      struct nouveau_object **pobject); + +struct nv40_perfmon_cntr { +	struct nouveau_perfctr base; +}; + +extern const struct nouveau_funcdom nv40_perfctr_func; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c new file mode 100644 index 00000000000..94217691fe6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv50.c @@ -0,0 +1,70 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv40.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static const struct nouveau_specdom +nv50_perfmon[] = { +	{ 0x040, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x100, (const struct nouveau_specsig[]) { +			{ 0xc8, "gr_idle" }, +			{} +		}, &nv40_perfctr_func }, +	{ 0x100, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x020, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x040, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{} +}; + +struct nouveau_oclass * +nv50_perfmon_oclass = &(struct nv40_perfmon_oclass) { +	.base.handle = NV_ENGINE(PERFMON, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv40_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = _nouveau_perfmon_fini, +	}, +	.doms = nv50_perfmon, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c new file mode 100644 index 00000000000..9232c7fc625 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nv84.c @@ -0,0 +1,78 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv40.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static const struct nouveau_specdom +nv84_perfmon[] = { +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{} +}; + +struct nouveau_oclass * +nv84_perfmon_oclass = &(struct nv40_perfmon_oclass) { +	.base.handle = NV_ENGINE(PERFMON, 0x84), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv40_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = _nouveau_perfmon_fini, +	}, +	.doms = nv84_perfmon, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c new file mode 100644 index 00000000000..6197ebdeb64 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nva3.c @@ -0,0 +1,96 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv40.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static const struct nouveau_specdom +nva3_perfmon[] = { +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{ 0x20, (const struct nouveau_specsig[]) { +			{} +		}, &nv40_perfctr_func }, +	{} +}; + +static int +nva3_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **object) +{ +	int ret = nv40_perfmon_ctor(parent, engine, oclass, data, size, object); +	if (ret == 0) { +		struct nv40_perfmon_priv *priv = (void *)*object; +		ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, +					   nva3_perfmon_pwr); +		if (ret) +			return ret; + +		priv->base.last = 3; +	} +	return ret; +} + +struct nouveau_oclass * +nva3_perfmon_oclass = &(struct nv40_perfmon_oclass) { +	.base.handle = NV_ENGINE(PERFMON, 0xa3), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nva3_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = _nouveau_perfmon_fini, +	}, +	.doms = nva3_perfmon, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c new file mode 100644 index 00000000000..74b24104250 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.c @@ -0,0 +1,173 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nvc0.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static const struct nouveau_specdom +nvc0_perfmon_hub[] = { +	{} +}; + +static const struct nouveau_specdom +nvc0_perfmon_gpc[] = { +	{} +}; + +static const struct nouveau_specdom +nvc0_perfmon_part[] = { +	{} +}; + +static void +nvc0_perfctr_init(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, +		  struct nouveau_perfctr *ctr) +{ +	struct nvc0_perfmon_priv *priv = (void *)ppm; +	struct nvc0_perfmon_cntr *cntr = (void *)ctr; +	u32 log = ctr->logic_op; +	u32 src = 0x00000000; +	int i; + +	for (i = 0; i < 4 && ctr->signal[i]; i++) +		src |= (ctr->signal[i] - dom->signal) << (i * 8); + +	nv_wr32(priv, dom->addr + 0x09c, 0x00040002); +	nv_wr32(priv, dom->addr + 0x100, 0x00000000); +	nv_wr32(priv, dom->addr + 0x040 + (cntr->base.slot * 0x08), src); +	nv_wr32(priv, dom->addr + 0x044 + (cntr->base.slot * 0x08), log); +} + +static void +nvc0_perfctr_read(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom, +		  struct nouveau_perfctr *ctr) +{ +	struct nvc0_perfmon_priv *priv = (void *)ppm; +	struct nvc0_perfmon_cntr *cntr = (void *)ctr; + +	switch (cntr->base.slot) { +	case 0: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x08c); break; +	case 1: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x088); break; +	case 2: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x080); break; +	case 3: cntr->base.ctr = nv_rd32(priv, dom->addr + 0x090); break; +	} +	cntr->base.clk = nv_rd32(priv, dom->addr + 0x070); +} + +static void +nvc0_perfctr_next(struct nouveau_perfmon *ppm, struct nouveau_perfdom *dom) +{ +	struct nvc0_perfmon_priv *priv = (void *)ppm; +	nv_wr32(priv, dom->addr + 0x06c, dom->signal_nr - 0x40 + 0x27); +	nv_wr32(priv, dom->addr + 0x0ec, 0x00000011); +} + +const struct nouveau_funcdom +nvc0_perfctr_func = { +	.init = nvc0_perfctr_init, +	.read = nvc0_perfctr_read, +	.next = nvc0_perfctr_next, +}; + +int +nvc0_perfmon_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvc0_perfmon_priv *priv = (void *)object; +	nv_mask(priv, 0x000200, 0x10000000, 0x00000000); +	nv_mask(priv, 0x000200, 0x10000000, 0x10000000); +	return nouveau_perfmon_fini(&priv->base, suspend); +} + +static int +nvc0_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **pobject) +{ +	struct nvc0_perfmon_priv *priv; +	u32 mask; +	int ret; + +	ret = nouveau_perfmon_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, +				   nvc0_perfmon_pwr); +	if (ret) +		return ret; + +	/* HUB */ +	ret = nouveau_perfdom_new(&priv->base, "hub", 0, 0x1b0000, 0, 0x200, +				   nvc0_perfmon_hub); +	if (ret) +		return ret; + +	/* GPC */ +	mask  = (1 << nv_rd32(priv, 0x022430)) - 1; +	mask &= ~nv_rd32(priv, 0x022504); +	mask &= ~nv_rd32(priv, 0x022584); + +	ret = nouveau_perfdom_new(&priv->base, "gpc", mask, 0x180000, +				  0x1000, 0x200, nvc0_perfmon_gpc); +	if (ret) +		return ret; + +	/* PART */ +	mask  = (1 << nv_rd32(priv, 0x022438)) - 1; +	mask &= ~nv_rd32(priv, 0x022548); +	mask &= ~nv_rd32(priv, 0x0225c8); + +	ret = nouveau_perfdom_new(&priv->base, "part", mask, 0x1a0000, +				  0x1000, 0x200, nvc0_perfmon_part); +	if (ret) +		return ret; + +	nv_engine(priv)->cclass = &nouveau_perfmon_cclass; +	nv_engine(priv)->sclass =  nouveau_perfmon_sclass; +	priv->base.last = 7; +	return 0; +} + +struct nouveau_oclass +nvc0_perfmon_oclass = { +	.handle = NV_ENGINE(PERFMON, 0xc0), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = nvc0_perfmon_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h new file mode 100644 index 00000000000..f66bca48426 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvc0.h @@ -0,0 +1,17 @@ +#ifndef __NVKM_PM_NVC0_H__ +#define __NVKM_PM_NVC0_H__ + +#include "priv.h" + +struct nvc0_perfmon_priv { +	struct nouveau_perfmon base; +}; + +struct nvc0_perfmon_cntr { +	struct nouveau_perfctr base; +}; + +extern const struct nouveau_funcdom nvc0_perfctr_func; +int nvc0_perfmon_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c new file mode 100644 index 00000000000..71d718c1207 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nve0.c @@ -0,0 +1,162 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nvc0.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static const struct nouveau_specdom +nve0_perfmon_hub[] = { +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "hub00_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x40, (const struct nouveau_specsig[]) { +			{ 0x27, "hub01_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "hub02_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "hub03_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x40, (const struct nouveau_specsig[]) { +			{ 0x03, "host_mmio_rd" }, +			{ 0x27, "hub04_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "hub05_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0xc0, (const struct nouveau_specsig[]) { +			{ 0x74, "host_fb_rd3x" }, +			{ 0x75, "host_fb_rd3x_2" }, +			{ 0xa7, "hub06_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "hub07_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{} +}; + +static const struct nouveau_specdom +nve0_perfmon_gpc[] = { +	{ 0xe0, (const struct nouveau_specsig[]) { +			{ 0xc7, "gpc00_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{} +}; + +static const struct nouveau_specdom +nve0_perfmon_part[] = { +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "part00_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{ 0x60, (const struct nouveau_specsig[]) { +			{ 0x47, "part01_user_0" }, +			{} +		}, &nvc0_perfctr_func }, +	{} +}; + +static int +nve0_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **pobject) +{ +	struct nvc0_perfmon_priv *priv; +	u32 mask; +	int ret; + +	ret = nouveau_perfmon_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	/* PDAEMON */ +	ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, +				   nve0_perfmon_pwr); +	if (ret) +		return ret; + +	/* HUB */ +	ret = nouveau_perfdom_new(&priv->base, "hub", 0, 0x1b0000, 0, 0x200, +				   nve0_perfmon_hub); +	if (ret) +		return ret; + +	/* GPC */ +	mask  = (1 << nv_rd32(priv, 0x022430)) - 1; +	mask &= ~nv_rd32(priv, 0x022504); +	mask &= ~nv_rd32(priv, 0x022584); + +	ret = nouveau_perfdom_new(&priv->base, "gpc", mask, 0x180000, +				  0x1000, 0x200, nve0_perfmon_gpc); +	if (ret) +		return ret; + +	/* PART */ +	mask  = (1 << nv_rd32(priv, 0x022438)) - 1; +	mask &= ~nv_rd32(priv, 0x022548); +	mask &= ~nv_rd32(priv, 0x0225c8); + +	ret = nouveau_perfdom_new(&priv->base, "part", mask, 0x1a0000, +				  0x1000, 0x200, nve0_perfmon_part); +	if (ret) +		return ret; + +	nv_engine(priv)->cclass = &nouveau_perfmon_cclass; +	nv_engine(priv)->sclass =  nouveau_perfmon_sclass; +	priv->base.last = 7; +	return 0; +} + +struct nouveau_oclass +nve0_perfmon_oclass = { +	.handle = NV_ENGINE(PERFMON, 0xe0), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nve0_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = nvc0_perfmon_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c new file mode 100644 index 00000000000..47256f78a89 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/nvf0.c @@ -0,0 +1,71 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nvc0.h" + +/******************************************************************************* + * Perfmon object classes + ******************************************************************************/ + +/******************************************************************************* + * PPM context + ******************************************************************************/ + +/******************************************************************************* + * PPM engine/subdev functions + ******************************************************************************/ + +static int +nvf0_perfmon_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **pobject) +{ +	struct nvc0_perfmon_priv *priv; +	int ret; + +	ret = nouveau_perfmon_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	ret = nouveau_perfdom_new(&priv->base, "pwr", 0, 0, 0, 0, +				   nve0_perfmon_pwr); +	if (ret) +		return ret; + +	nv_engine(priv)->cclass = &nouveau_perfmon_cclass; +	nv_engine(priv)->sclass =  nouveau_perfmon_sclass; +	return 0; +} + +struct nouveau_oclass +nvf0_perfmon_oclass = { +	.handle = NV_ENGINE(PERFMON, 0xf0), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvf0_perfmon_ctor, +		.dtor = _nouveau_perfmon_dtor, +		.init = _nouveau_perfmon_init, +		.fini = nvc0_perfmon_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h b/drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h new file mode 100644 index 00000000000..0ac8714fe0b --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/perfmon/priv.h @@ -0,0 +1,91 @@ +#ifndef __NVKM_PERFMON_PRIV_H__ +#define __NVKM_PERFMON_PRIV_H__ + +#include <engine/perfmon.h> + +struct nouveau_perfctr { +	struct nouveau_object base; +	struct list_head head; +	struct nouveau_perfsig *signal[4]; +	int slot; +	u32 logic_op; +	u32 clk; +	u32 ctr; +}; + +extern struct nouveau_oclass nouveau_perfmon_sclass[]; + +struct nouveau_perfctx { +	struct nouveau_engctx base; +}; + +extern struct nouveau_oclass nouveau_perfmon_cclass; + +struct nouveau_specsig { +	u8 signal; +	const char *name; +}; + +struct nouveau_perfsig { +	const char *name; +}; + +struct nouveau_perfdom; +struct nouveau_perfctr * +nouveau_perfsig_wrap(struct nouveau_perfmon *, const char *, +		     struct nouveau_perfdom **); + +struct nouveau_specdom { +	u16 signal_nr; +	const struct nouveau_specsig *signal; +	const struct nouveau_funcdom *func; +}; + +extern const struct nouveau_specdom nva3_perfmon_pwr[]; +extern const struct nouveau_specdom nvc0_perfmon_pwr[]; +extern const struct nouveau_specdom nve0_perfmon_pwr[]; + +struct nouveau_perfdom { +	struct list_head head; +	struct list_head list; +	const struct nouveau_funcdom *func; +	char name[32]; +	u32 addr; +	u8  quad; +	u32 signal_nr; +	struct nouveau_perfsig signal[]; +}; + +struct nouveau_funcdom { +	void (*init)(struct nouveau_perfmon *, struct nouveau_perfdom *, +		     struct nouveau_perfctr *); +	void (*read)(struct nouveau_perfmon *, struct nouveau_perfdom *, +		     struct nouveau_perfctr *); +	void (*next)(struct nouveau_perfmon *, struct nouveau_perfdom *); +}; + +int nouveau_perfdom_new(struct nouveau_perfmon *, const char *, u32, +			u32, u32, u32, const struct nouveau_specdom *); + +#define nouveau_perfmon_create(p,e,o,d)                                        \ +	nouveau_perfmon_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_perfmon_dtor(p) ({                                             \ +	struct nouveau_perfmon *c = (p);                                       \ +	_nouveau_perfmon_dtor(nv_object(c));                                   \ +}) +#define nouveau_perfmon_init(p) ({                                             \ +	struct nouveau_perfmon *c = (p);                                       \ +	_nouveau_perfmon_init(nv_object(c));                                   \ +}) +#define nouveau_perfmon_fini(p,s) ({                                           \ +	struct nouveau_perfmon *c = (p);                                       \ +	_nouveau_perfmon_fini(nv_object(c), (s));                              \ +}) + +int nouveau_perfmon_create_(struct nouveau_object *, struct nouveau_object *, +			    struct nouveau_oclass *, int, void **); +void _nouveau_perfmon_dtor(struct nouveau_object *); +int  _nouveau_perfmon_init(struct nouveau_object *); +int  _nouveau_perfmon_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c index 2a859a31c30..c571758e4a2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv04.c @@ -135,8 +135,8 @@ nv04_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -struct nouveau_oclass -nv04_software_oclass = { +struct nouveau_oclass * +nv04_software_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(SW, 0x04),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_software_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c index a019364b1e1..a62f11a7843 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv10.c @@ -117,8 +117,8 @@ nv10_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -struct nouveau_oclass -nv10_software_oclass = { +struct nouveau_oclass * +nv10_software_oclass = &(struct nouveau_oclass) {  	.handle = NV_ENGINE(SW, 0x10),  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv10_software_ctor, diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c index c48e7495377..f3b4d9dbf23 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -32,16 +32,9 @@  #include <subdev/bar.h> -#include <engine/software.h>  #include <engine/disp.h> -struct nv50_software_priv { -	struct nouveau_software base; -}; - -struct nv50_software_chan { -	struct nouveau_software_chan base; -}; +#include "nv50.h"  /*******************************************************************************   * software object classes @@ -62,7 +55,7 @@ nv50_software_mthd_dma_vblsem(struct nouveau_object *object, u32 mthd,  	if (nv_iclass(handle->object, NV_GPUOBJ_CLASS)) {  		struct nouveau_gpuobj *gpuobj = nv_gpuobj(handle->object); -		chan->base.vblank.ctxdma = gpuobj->node->offset >> 4; +		chan->vblank.ctxdma = gpuobj->node->offset >> 4;  		ret = 0;  	}  	nouveau_namedb_put(handle); @@ -74,34 +67,33 @@ nv50_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd,  				 void *args, u32 size)  {  	struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); -	chan->base.vblank.offset = *(u32 *)args; +	chan->vblank.offset = *(u32 *)args;  	return 0;  } -static int +int  nv50_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd,  				void *args, u32 size)  {  	struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); -	chan->base.vblank.value = *(u32 *)args; +	chan->vblank.value = *(u32 *)args;  	return 0;  } -static int +int  nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd,  				  void *args, u32 size)  {  	struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); -	struct nouveau_disp *disp = nouveau_disp(object); -	u32 crtc = *(u32 *)args; -	if (crtc > 1) +	u32 head = *(u32 *)args; +	if (head >= chan->vblank.nr_event)  		return -EINVAL; -	nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); +	nouveau_event_get(chan->vblank.event[head]);  	return 0;  } -static int +int  nv50_software_mthd_flip(struct nouveau_object *object, u32 mthd,  			void *args, u32 size)  { @@ -132,10 +124,9 @@ nv50_software_sclass[] = {   ******************************************************************************/  static int -nv50_software_vblsem_release(struct nouveau_eventh *event, int head) +nv50_software_vblsem_release(void *data, u32 type, int head)  { -	struct nouveau_software_chan *chan = -		container_of(event, struct nouveau_software_chan, vblank.event); +	struct nv50_software_chan *chan = data;  	struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;  	struct nouveau_bar *bar = nouveau_bar(priv); @@ -154,45 +145,76 @@ nv50_software_vblsem_release(struct nouveau_eventh *event, int head)  	return NVKM_EVENT_DROP;  } -static int +void +nv50_software_context_dtor(struct nouveau_object *object) +{ +	struct nv50_software_chan *chan = (void *)object; +	int i; + +	if (chan->vblank.event) { +		for (i = 0; i < chan->vblank.nr_event; i++) +			nouveau_event_ref(NULL, &chan->vblank.event[i]); +		kfree(chan->vblank.event); +	} + +	nouveau_software_context_destroy(&chan->base); +} + +int  nv50_software_context_ctor(struct nouveau_object *parent,  			   struct nouveau_object *engine,  			   struct nouveau_oclass *oclass, void *data, u32 size,  			   struct nouveau_object **pobject)  { +	struct nouveau_disp *pdisp = nouveau_disp(parent); +	struct nv50_software_cclass *pclass = (void *)oclass;  	struct nv50_software_chan *chan; -	int ret; +	int ret, i;  	ret = nouveau_software_context_create(parent, engine, oclass, &chan);  	*pobject = nv_object(chan);  	if (ret)  		return ret; -	chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; -	chan->base.vblank.event.func = nv50_software_vblsem_release; +	chan->vblank.nr_event = pdisp ? pdisp->vblank->index_nr : 0; +	chan->vblank.event = kzalloc(chan->vblank.nr_event * +				     sizeof(*chan->vblank.event), GFP_KERNEL); +	if (!chan->vblank.event) +		return -ENOMEM; + +	for (i = 0; i < chan->vblank.nr_event; i++) { +		ret = nouveau_event_new(pdisp->vblank, 1, i, pclass->vblank, +					chan, &chan->vblank.event[i]); +		if (ret) +			return ret; +	} + +	chan->vblank.channel = nv_gpuobj(parent->parent)->addr >> 12;  	return 0;  } -static struct nouveau_oclass +static struct nv50_software_cclass  nv50_software_cclass = { -	.handle = NV_ENGCTX(SW, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +	.base.handle = NV_ENGCTX(SW, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_software_context_ctor,  		.dtor = _nouveau_software_context_dtor,  		.init = _nouveau_software_context_init,  		.fini = _nouveau_software_context_fini,  	}, +	.vblank = nv50_software_vblsem_release,  };  /*******************************************************************************   * software engine/subdev functions   ******************************************************************************/ -static int +int  nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		   struct nouveau_oclass *oclass, void *data, u32 size,  		   struct nouveau_object **pobject)  { +	struct nv50_software_oclass *pclass = (void *)oclass;  	struct nv50_software_priv *priv;  	int ret; @@ -201,19 +223,21 @@ nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; -	nv_engine(priv)->cclass = &nv50_software_cclass; -	nv_engine(priv)->sclass = nv50_software_sclass; +	nv_engine(priv)->cclass = pclass->cclass; +	nv_engine(priv)->sclass = pclass->sclass;  	nv_subdev(priv)->intr = nv04_software_intr;  	return 0;  } -struct nouveau_oclass -nv50_software_oclass = { -	.handle = NV_ENGINE(SW, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_software_oclass = &(struct nv50_software_oclass) { +	.base.handle = NV_ENGINE(SW, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_software_ctor,  		.dtor = _nouveau_software_dtor,  		.init = _nouveau_software_init,  		.fini = _nouveau_software_fini,  	}, -}; +	.cclass = &nv50_software_cclass.base, +	.sclass =  nv50_software_sclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nv50.h b/drivers/gpu/drm/nouveau/core/engine/software/nv50.h new file mode 100644 index 00000000000..bb49a7a2085 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/engine/software/nv50.h @@ -0,0 +1,47 @@ +#ifndef __NVKM_SW_NV50_H__ +#define __NVKM_SW_NV50_H__ + +#include <engine/software.h> + +struct nv50_software_oclass { +	struct nouveau_oclass base; +	struct nouveau_oclass *cclass; +	struct nouveau_oclass *sclass; +}; + +struct nv50_software_priv { +	struct nouveau_software base; +}; + +int  nv50_software_ctor(struct nouveau_object *, struct nouveau_object *, +			struct nouveau_oclass *, void *, u32, +			struct nouveau_object **); + +struct nv50_software_cclass { +	struct nouveau_oclass base; +	int (*vblank)(void *, u32, int); +}; + +struct nv50_software_chan { +	struct nouveau_software_chan base; +	struct { +		struct nouveau_eventh **event; +		int nr_event; +		u32 channel; +		u32 ctxdma; +		u64 offset; +		u32 value; +	} vblank; +}; + +int  nv50_software_context_ctor(struct nouveau_object *, +				struct nouveau_object *, +				struct nouveau_oclass *, void *, u32, +				struct nouveau_object **); +void nv50_software_context_dtor(struct nouveau_object *); + +int nv50_software_mthd_vblsem_value(struct nouveau_object *, u32, void *, u32); +int nv50_software_mthd_vblsem_release(struct nouveau_object *, u32, void *, u32); +int nv50_software_mthd_flip(struct nouveau_object *, u32, void *, u32); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c index d698e710ddd..135c20f3835 100644 --- a/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -32,13 +32,7 @@  #include <engine/software.h>  #include <engine/disp.h> -struct nvc0_software_priv { -	struct nouveau_software base; -}; - -struct nvc0_software_chan { -	struct nouveau_software_chan base; -}; +#include "nv50.h"  /*******************************************************************************   * software object classes @@ -48,58 +42,24 @@ static int  nvc0_software_mthd_vblsem_offset(struct nouveau_object *object, u32 mthd,  				 void *args, u32 size)  { -	struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); +	struct nv50_software_chan *chan = (void *)nv_engctx(object->parent);  	u64 data = *(u32 *)args;  	if (mthd == 0x0400) { -		chan->base.vblank.offset &= 0x00ffffffffULL; -		chan->base.vblank.offset |= data << 32; +		chan->vblank.offset &= 0x00ffffffffULL; +		chan->vblank.offset |= data << 32;  	} else { -		chan->base.vblank.offset &= 0xff00000000ULL; -		chan->base.vblank.offset |= data; +		chan->vblank.offset &= 0xff00000000ULL; +		chan->vblank.offset |= data;  	}  	return 0;  }  static int -nvc0_software_mthd_vblsem_value(struct nouveau_object *object, u32 mthd, -				void *args, u32 size) -{ -	struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); -	chan->base.vblank.value = *(u32 *)args; -	return 0; -} - -static int -nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, -				  void *args, u32 size) -{ -	struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); -	struct nouveau_disp *disp = nouveau_disp(object); -	u32 crtc = *(u32 *)args; - -	if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) -		return -EINVAL; - -	nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); -	return 0; -} - -static int -nvc0_software_mthd_flip(struct nouveau_object *object, u32 mthd, -			void *args, u32 size) -{ -	struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); -	if (chan->base.flip) -		return chan->base.flip(chan->base.flip_data); -	return -EINVAL; -} - -static int  nvc0_software_mthd_mp_control(struct nouveau_object *object, u32 mthd,                                void *args, u32 size)  { -	struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); -	struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine; +	struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); +	struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;  	u32 data = *(u32 *)args;  	switch (mthd) { @@ -124,9 +84,9 @@ static struct nouveau_omthds  nvc0_software_omthds[] = {  	{ 0x0400, 0x0400, nvc0_software_mthd_vblsem_offset },  	{ 0x0404, 0x0404, nvc0_software_mthd_vblsem_offset }, -	{ 0x0408, 0x0408, nvc0_software_mthd_vblsem_value }, -	{ 0x040c, 0x040c, nvc0_software_mthd_vblsem_release }, -	{ 0x0500, 0x0500, nvc0_software_mthd_flip }, +	{ 0x0408, 0x0408, nv50_software_mthd_vblsem_value }, +	{ 0x040c, 0x040c, nv50_software_mthd_vblsem_release }, +	{ 0x0500, 0x0500, nv50_software_mthd_flip },  	{ 0x0600, 0x0600, nvc0_software_mthd_mp_control },  	{ 0x0644, 0x0644, nvc0_software_mthd_mp_control },  	{ 0x06ac, 0x06ac, nvc0_software_mthd_mp_control }, @@ -144,11 +104,10 @@ nvc0_software_sclass[] = {   ******************************************************************************/  static int -nvc0_software_vblsem_release(struct nouveau_eventh *event, int head) +nvc0_software_vblsem_release(void *data, u32 type, int head)  { -	struct nouveau_software_chan *chan = -		container_of(event, struct nouveau_software_chan, vblank.event); -	struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine; +	struct nv50_software_chan *chan = data; +	struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;  	struct nouveau_bar *bar = nouveau_bar(priv);  	nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); @@ -160,66 +119,31 @@ nvc0_software_vblsem_release(struct nouveau_eventh *event, int head)  	return NVKM_EVENT_DROP;  } -static int -nvc0_software_context_ctor(struct nouveau_object *parent, -			   struct nouveau_object *engine, -			   struct nouveau_oclass *oclass, void *data, u32 size, -			   struct nouveau_object **pobject) -{ -	struct nvc0_software_chan *chan; -	int ret; - -	ret = nouveau_software_context_create(parent, engine, oclass, &chan); -	*pobject = nv_object(chan); -	if (ret) -		return ret; - -	chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; -	chan->base.vblank.event.func = nvc0_software_vblsem_release; -	return 0; -} - -static struct nouveau_oclass +static struct nv50_software_cclass  nvc0_software_cclass = { -	.handle = NV_ENGCTX(SW, 0xc0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvc0_software_context_ctor, +	.base.handle = NV_ENGCTX(SW, 0xc0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_software_context_ctor,  		.dtor = _nouveau_software_context_dtor,  		.init = _nouveau_software_context_init,  		.fini = _nouveau_software_context_fini,  	}, +	.vblank = nvc0_software_vblsem_release,  };  /*******************************************************************************   * software engine/subdev functions   ******************************************************************************/ -static int -nvc0_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		   struct nouveau_oclass *oclass, void *data, u32 size, -		   struct nouveau_object **pobject) -{ -	struct nvc0_software_priv *priv; -	int ret; - -	ret = nouveau_software_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	nv_engine(priv)->cclass = &nvc0_software_cclass; -	nv_engine(priv)->sclass = nvc0_software_sclass; -	nv_subdev(priv)->intr = nv04_software_intr; -	return 0; -} - -struct nouveau_oclass -nvc0_software_oclass = { -	.handle = NV_ENGINE(SW, 0xc0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvc0_software_ctor, +struct nouveau_oclass * +nvc0_software_oclass = &(struct nv50_software_oclass) { +	.base.handle = NV_ENGINE(SW, 0xc0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_software_ctor,  		.dtor = _nouveau_software_dtor,  		.init = _nouveau_software_init,  		.fini = _nouveau_software_fini,  	}, -}; +	.cclass = &nvc0_software_cclass.base, +	.sclass =  nvc0_software_sclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/engine/xtensa.c b/drivers/gpu/drm/nouveau/core/engine/xtensa.c index 5f6ede7c489..92384759d2f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/xtensa.c +++ b/drivers/gpu/drm/nouveau/core/engine/xtensa.c @@ -112,7 +112,7 @@ _nouveau_xtensa_init(struct nouveau_object *object)  		snprintf(name, sizeof(name), "nouveau/nv84_xuc%03x",  			 xtensa->addr >> 12); -		ret = request_firmware(&fw, name, &device->pdev->dev); +		ret = request_firmware(&fw, name, nv_device_base(device));  		if (ret) {  			nv_warn(xtensa, "unable to load firmware %s\n", name);  			return ret; diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h index 5a5961b6a6a..e0c812bc884 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -22,7 +22,7 @@  #define NV_DEVICE_DISABLE_PPP                             0x0000004000000000ULL  #define NV_DEVICE_DISABLE_COPY0                           0x0000008000000000ULL  #define NV_DEVICE_DISABLE_COPY1                           0x0000010000000000ULL -#define NV_DEVICE_DISABLE_UNK1C1                          0x0000020000000000ULL +#define NV_DEVICE_DISABLE_VIC                             0x0000020000000000ULL  #define NV_DEVICE_DISABLE_VENC                            0x0000040000000000ULL  struct nv_device_class { @@ -98,6 +98,77 @@ struct nv_dma_class {  	u32 conf0;  }; +/* Perfmon counter class + * + * XXXX: NV_PERFCTR + */ +#define NV_PERFCTR_CLASS                                             0x0000ffff +#define NV_PERFCTR_QUERY                                             0x00000000 +#define NV_PERFCTR_SAMPLE                                            0x00000001 +#define NV_PERFCTR_READ                                              0x00000002 + +struct nv_perfctr_class { +	u16 logic_op; +	struct { +		char __user *name; /*XXX: use cfu when exposed to userspace */ +		u32 size; +	} signal[4]; +}; + +struct nv_perfctr_query { +	u32 iter; +	u32 size; +	char __user *name; /*XXX: use ctu when exposed to userspace */ +}; + +struct nv_perfctr_sample { +}; + +struct nv_perfctr_read { +	u32 ctr; +	u32 clk; +}; + +/* Device control class + * + * XXXX: NV_CONTROL + */ +#define NV_CONTROL_CLASS                                             0x0000fffe + +#define NV_CONTROL_PSTATE_INFO                                       0x00000000 +#define NV_CONTROL_PSTATE_INFO_USTATE_DISABLE                              (-1) +#define NV_CONTROL_PSTATE_INFO_USTATE_PERFMON                              (-2) +#define NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN                              (-1) +#define NV_CONTROL_PSTATE_INFO_PSTATE_PERFMON                              (-2) +#define NV_CONTROL_PSTATE_ATTR                                       0x00000001 +#define NV_CONTROL_PSTATE_ATTR_STATE_CURRENT                               (-1) +#define NV_CONTROL_PSTATE_USER                                       0x00000002 +#define NV_CONTROL_PSTATE_USER_STATE_UNKNOWN                               (-1) +#define NV_CONTROL_PSTATE_USER_STATE_PERFMON                               (-2) + +struct nv_control_pstate_info { +	u32 count; /* out: number of power states */ +	s32 ustate; /* out: current target pstate index */ +	u32 pstate; /* out: current pstate index */ +}; + +struct nv_control_pstate_attr { +	s32 state; /*  in: index of pstate to query +		    * out: pstate identifier +		    */ +	u32 index; /*  in: index of attribute to query +		    * out: index of next attribute, or 0 if no more +		    */ +	char name[32]; +	char unit[16]; +	u32 min; +	u32 max; +}; + +struct nv_control_pstate_user { +	s32 state; /*  in: pstate identifier */ +}; +  /* DMA FIFO channel classes   *   * 006b: NV03_CHANNEL_DMA @@ -159,9 +230,26 @@ struct nve0_channel_ind_class {  #define NV04_DISP_CLASS                                              0x00000046 +#define NV04_DISP_MTHD                                               0x00000000 +#define NV04_DISP_MTHD_HEAD                                          0x00000001 + +#define NV04_DISP_SCANOUTPOS                                         0x00000000 +  struct nv04_display_class {  }; +struct nv04_display_scanoutpos { +	s64 time[2]; +	u32 vblanks; +	u32 vblanke; +	u32 vtotal; +	u32 vline; +	u32 hblanks; +	u32 hblanke; +	u32 htotal; +	u32 hline; +}; +  /* 5070: NV50_DISP   * 8270: NV84_DISP   * 8370: NVA0_DISP @@ -170,6 +258,7 @@ struct nv04_display_class {   * 9070: NVD0_DISP   * 9170: NVE0_DISP   * 9270: NVF0_DISP + * 9470: GM107_DISP   */  #define NV50_DISP_CLASS                                              0x00005070 @@ -180,6 +269,12 @@ struct nv04_display_class {  #define NVD0_DISP_CLASS                                              0x00009070  #define NVE0_DISP_CLASS                                              0x00009170  #define NVF0_DISP_CLASS                                              0x00009270 +#define GM107_DISP_CLASS                                             0x00009470 + +#define NV50_DISP_MTHD                                               0x00000000 +#define NV50_DISP_MTHD_HEAD                                          0x00000003 + +#define NV50_DISP_SCANOUTPOS                                         0x00000000  #define NV50_DISP_SOR_MTHD                                           0x00010000  #define NV50_DISP_SOR_MTHD_TYPE                                      0x0000f000 @@ -200,6 +295,10 @@ struct nv04_display_class {  #define NV84_DISP_SOR_HDMI_PWR_REKEY                                 0x0000007f  #define NV50_DISP_SOR_LVDS_SCRIPT                                    0x00013000  #define NV50_DISP_SOR_LVDS_SCRIPT_ID                                 0x0000ffff +#define NV94_DISP_SOR_DP_PWR                                         0x00016000 +#define NV94_DISP_SOR_DP_PWR_STATE                                   0x00000001 +#define NV94_DISP_SOR_DP_PWR_STATE_OFF                               0x00000000 +#define NV94_DISP_SOR_DP_PWR_STATE_ON                                0x00000001  #define NV50_DISP_DAC_MTHD                                           0x00020000  #define NV50_DISP_DAC_MTHD_TYPE                                      0x0000f000 @@ -249,6 +348,7 @@ struct nv50_display_class {   * 907a: NVD0_DISP_CURS   * 917a: NVE0_DISP_CURS   * 927a: NVF0_DISP_CURS + * 947a: GM107_DISP_CURS   */  #define NV50_DISP_CURS_CLASS                                         0x0000507a @@ -259,6 +359,7 @@ struct nv50_display_class {  #define NVD0_DISP_CURS_CLASS                                         0x0000907a  #define NVE0_DISP_CURS_CLASS                                         0x0000917a  #define NVF0_DISP_CURS_CLASS                                         0x0000927a +#define GM107_DISP_CURS_CLASS                                        0x0000947a  struct nv50_display_curs_class {  	u32 head; @@ -272,6 +373,7 @@ struct nv50_display_curs_class {   * 907b: NVD0_DISP_OIMM   * 917b: NVE0_DISP_OIMM   * 927b: NVE0_DISP_OIMM + * 947b: GM107_DISP_OIMM   */  #define NV50_DISP_OIMM_CLASS                                         0x0000507b @@ -282,6 +384,7 @@ struct nv50_display_curs_class {  #define NVD0_DISP_OIMM_CLASS                                         0x0000907b  #define NVE0_DISP_OIMM_CLASS                                         0x0000917b  #define NVF0_DISP_OIMM_CLASS                                         0x0000927b +#define GM107_DISP_OIMM_CLASS                                        0x0000947b  struct nv50_display_oimm_class {  	u32 head; @@ -295,6 +398,7 @@ struct nv50_display_oimm_class {   * 907c: NVD0_DISP_SYNC   * 917c: NVE0_DISP_SYNC   * 927c: NVF0_DISP_SYNC + * 947c: GM107_DISP_SYNC   */  #define NV50_DISP_SYNC_CLASS                                         0x0000507c @@ -305,6 +409,7 @@ struct nv50_display_oimm_class {  #define NVD0_DISP_SYNC_CLASS                                         0x0000907c  #define NVE0_DISP_SYNC_CLASS                                         0x0000917c  #define NVF0_DISP_SYNC_CLASS                                         0x0000927c +#define GM107_DISP_SYNC_CLASS                                        0x0000947c  struct nv50_display_sync_class {  	u32 pushbuf; @@ -319,6 +424,7 @@ struct nv50_display_sync_class {   * 907d: NVD0_DISP_MAST   * 917d: NVE0_DISP_MAST   * 927d: NVF0_DISP_MAST + * 947d: GM107_DISP_MAST   */  #define NV50_DISP_MAST_CLASS                                         0x0000507d @@ -329,6 +435,7 @@ struct nv50_display_sync_class {  #define NVD0_DISP_MAST_CLASS                                         0x0000907d  #define NVE0_DISP_MAST_CLASS                                         0x0000917d  #define NVF0_DISP_MAST_CLASS                                         0x0000927d +#define GM107_DISP_MAST_CLASS                                        0x0000947d  struct nv50_display_mast_class {  	u32 pushbuf; @@ -342,6 +449,7 @@ struct nv50_display_mast_class {   * 907e: NVD0_DISP_OVLY   * 917e: NVE0_DISP_OVLY   * 927e: NVF0_DISP_OVLY + * 947e: GM107_DISP_OVLY   */  #define NV50_DISP_OVLY_CLASS                                         0x0000507e @@ -352,6 +460,7 @@ struct nv50_display_mast_class {  #define NVD0_DISP_OVLY_CLASS                                         0x0000907e  #define NVE0_DISP_OVLY_CLASS                                         0x0000917e  #define NVF0_DISP_OVLY_CLASS                                         0x0000927e +#define GM107_DISP_OVLY_CLASS                                        0x0000947e  struct nv50_display_ovly_class {  	u32 pushbuf; diff --git a/drivers/gpu/drm/nouveau/core/include/core/debug.h b/drivers/gpu/drm/nouveau/core/include/core/debug.h index 9ea18dfcb4d..8092e2e9032 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/debug.h +++ b/drivers/gpu/drm/nouveau/core/include/core/debug.h @@ -1,13 +1,20 @@  #ifndef __NOUVEAU_DEBUG_H__  #define __NOUVEAU_DEBUG_H__ +extern int nv_info_debug_level; +  #define NV_DBG_FATAL    0  #define NV_DBG_ERROR    1  #define NV_DBG_WARN     2 -#define NV_DBG_INFO     3 +#define NV_DBG_INFO     nv_info_debug_level  #define NV_DBG_DEBUG    4  #define NV_DBG_TRACE    5  #define NV_DBG_PARANOIA 6  #define NV_DBG_SPAM     7 +#define NV_DBG_INFO_NORMAL 3 +#define NV_DBG_INFO_SILENT NV_DBG_DEBUG + +#define nv_debug_level(a) nv_info_debug_level = NV_DBG_INFO_##a +  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 99b6600fe80..a8a9a9cf16c 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -33,11 +33,14 @@ enum nv_subdev_type {  	NVDEV_SUBDEV_INSTMEM,  	NVDEV_SUBDEV_VM,  	NVDEV_SUBDEV_BAR, +	NVDEV_SUBDEV_PWR,  	NVDEV_SUBDEV_VOLT, -	NVDEV_SUBDEV_CLOCK,  	NVDEV_SUBDEV_THERM, +	NVDEV_SUBDEV_CLOCK, -	NVDEV_ENGINE_DMAOBJ, +	NVDEV_ENGINE_FIRST, +	NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST, +	NVDEV_ENGINE_IFB,  	NVDEV_ENGINE_FIFO,  	NVDEV_ENGINE_SW,  	NVDEV_ENGINE_GR, @@ -50,9 +53,10 @@ enum nv_subdev_type {  	NVDEV_ENGINE_COPY0,  	NVDEV_ENGINE_COPY1,  	NVDEV_ENGINE_COPY2, -	NVDEV_ENGINE_UNK1C1, +	NVDEV_ENGINE_VIC,  	NVDEV_ENGINE_VENC,  	NVDEV_ENGINE_DISP, +	NVDEV_ENGINE_PERFMON,  	NVDEV_SUBDEV_NR,  }; @@ -62,16 +66,19 @@ struct nouveau_device {  	struct list_head head;  	struct pci_dev *pdev; +	struct platform_device *platformdev;  	u64 handle;  	const char *cfgopt;  	const char *dbgopt;  	const char *name;  	const char *cname; +	u64 disable_mask;  	enum {  		NV_04    = 0x04,  		NV_10    = 0x10, +		NV_11    = 0x11,  		NV_20    = 0x20,  		NV_30    = 0x30,  		NV_40    = 0x40, @@ -79,6 +86,7 @@ struct nouveau_device {  		NV_C0    = 0xc0,  		NV_D0    = 0xd0,  		NV_E0    = 0xe0, +		GM100    = 0x110,  	} card_type;  	u32 chipset;  	u32 crystal; @@ -135,4 +143,32 @@ nv_device_match(struct nouveau_object *object, u16 dev, u16 ven, u16 sub)  	       device->pdev->subsystem_device == sub;  } +static inline bool +nv_device_is_pci(struct nouveau_device *device) +{ +	return device->pdev != NULL; +} + +static inline struct device * +nv_device_base(struct nouveau_device *device) +{ +	return nv_device_is_pci(device) ? &device->pdev->dev : +					  &device->platformdev->dev; +} + +resource_size_t +nv_device_resource_start(struct nouveau_device *device, unsigned int bar); + +resource_size_t +nv_device_resource_len(struct nouveau_device *device, unsigned int bar); + +dma_addr_t +nv_device_map_page(struct nouveau_device *device, struct page *page); + +void +nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr); + +int +nv_device_get_irq(struct nouveau_device *device, bool stall); +  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/event.h b/drivers/gpu/drm/nouveau/core/include/core/event.h index 9e094408f14..ba3f1a76a81 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/event.h +++ b/drivers/gpu/drm/nouveau/core/include/core/event.h @@ -5,32 +5,43 @@  #define NVKM_EVENT_DROP 0  #define NVKM_EVENT_KEEP 1 +/* nouveau_eventh.flags bit #s */ +#define NVKM_EVENT_ENABLE 0 +  struct nouveau_eventh { +	struct nouveau_event *event;  	struct list_head head; -	int (*func)(struct nouveau_eventh *, int index); +	unsigned long flags; +	u32 types; +	int index; +	int (*func)(void *, u32, int); +	void *priv;  };  struct nouveau_event { -	spinlock_t lock; -  	void *priv; -	void (*enable)(struct nouveau_event *, int index); -	void (*disable)(struct nouveau_event *, int index); +	int (*check)(struct nouveau_event *, u32 type, int index); +	void (*enable)(struct nouveau_event *, int type, int index); +	void (*disable)(struct nouveau_event *, int type, int index); +	int types_nr;  	int index_nr; -	struct { -		struct list_head list; -		int refs; -	} index[]; + +	spinlock_t list_lock; +	struct list_head *list; +	spinlock_t refs_lock; +	int refs[];  }; -int  nouveau_event_create(int index_nr, struct nouveau_event **); +int  nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **);  void nouveau_event_destroy(struct nouveau_event **); -void nouveau_event_trigger(struct nouveau_event *, int index); - -void nouveau_event_get(struct nouveau_event *, int index, -		       struct nouveau_eventh *); -void nouveau_event_put(struct nouveau_event *, int index, -		       struct nouveau_eventh *); +void nouveau_event_trigger(struct nouveau_event *, u32 types, int index); + +int  nouveau_event_new(struct nouveau_event *, u32 types, int index, +		       int (*func)(void *, u32, int), void *, +		       struct nouveau_eventh **); +void nouveau_event_ref(struct nouveau_eventh *, struct nouveau_eventh **); +void nouveau_event_get(struct nouveau_eventh *); +void nouveau_event_put(struct nouveau_eventh *);  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/namedb.h b/drivers/gpu/drm/nouveau/core/include/core/namedb.h index 8897e088608..f5b5fd8e1fc 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/namedb.h +++ b/drivers/gpu/drm/nouveau/core/include/core/namedb.h @@ -33,7 +33,7 @@ nv_namedb(void *obj)  int  nouveau_namedb_create_(struct nouveau_object *, struct nouveau_object *,  			    struct nouveau_oclass *, u32 pclass, -			    struct nouveau_oclass *, u32 engcls, +			    struct nouveau_oclass *, u64 engcls,  			    int size, void **);  int  _nouveau_namedb_ctor(struct nouveau_object *, struct nouveau_object *, diff --git a/drivers/gpu/drm/nouveau/core/include/core/option.h b/drivers/gpu/drm/nouveau/core/include/core/option.h index 27074957fd2..ed055847887 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/option.h +++ b/drivers/gpu/drm/nouveau/core/include/core/option.h @@ -8,4 +8,13 @@ bool nouveau_boolopt(const char *optstr, const char *opt, bool value);  int nouveau_dbgopt(const char *optstr, const char *sub); +/* compares unterminated string 'str' with zero-terminated string 'cmp' */ +static inline int +strncasecmpz(const char *str, const char *cmp, size_t len) +{ +	if (strlen(cmp) != len) +		return len; +	return strncasecmp(str, cmp, len); +} +  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/core/printk.h b/drivers/gpu/drm/nouveau/core/include/core/printk.h index d87836e3a70..0f9a37bd32b 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/printk.h +++ b/drivers/gpu/drm/nouveau/core/include/core/printk.h @@ -6,27 +6,12 @@  struct nouveau_object; -#define NV_PRINTK_FATAL    KERN_CRIT -#define NV_PRINTK_ERROR    KERN_ERR -#define NV_PRINTK_WARN     KERN_WARNING -#define NV_PRINTK_INFO     KERN_INFO -#define NV_PRINTK_DEBUG    KERN_DEBUG -#define NV_PRINTK_PARANOIA KERN_DEBUG -#define NV_PRINTK_TRACE    KERN_DEBUG -#define NV_PRINTK_SPAM     KERN_DEBUG - -extern int nv_printk_suspend_level; - -#define NV_DBG_SUSPEND (nv_printk_suspend_level) -#define NV_PRINTK_SUSPEND  (nv_printk_level_to_pfx(nv_printk_suspend_level)) - -const char *nv_printk_level_to_pfx(int level); -void __printf(4, 5) -nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); +void __printf(3, 4) +nv_printk_(struct nouveau_object *, int, const char *, ...);  #define nv_printk(o,l,f,a...) do {                                             \  	if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG)                                \ -		nv_printk_(nv_object(o), NV_PRINTK_##l, NV_DBG_##l, f, ##a);   \ +		nv_printk_(nv_object(o), NV_DBG_##l, f, ##a);                  \  } while(0)  #define nv_fatal(o,f,a...) nv_printk((o), FATAL, f, ##a) @@ -37,16 +22,9 @@ nv_printk_(struct nouveau_object *, const char *, int, const char *, ...);  #define nv_trace(o,f,a...) nv_printk((o), TRACE, f, ##a)  #define nv_spam(o,f,a...) nv_printk((o), SPAM, f, ##a) -#define nv_suspend(o,f,a...) nv_printk((o), SUSPEND, f, ##a) - -static inline void nv_suspend_set_printk_level(int level) -{ -	nv_printk_suspend_level = level; -} -  #define nv_assert(f,a...) do {                                                 \  	if (NV_DBG_FATAL <= CONFIG_NOUVEAU_DEBUG)                              \ -		nv_printk_(NULL, NV_PRINTK_FATAL, NV_DBG_FATAL, f "\n", ##a);  \ +		nv_printk_(NULL, NV_DBG_FATAL, f "\n", ##a);                   \  	BUG_ON(1);                                                             \  } while(0) diff --git a/drivers/gpu/drm/nouveau/core/include/engine/device.h b/drivers/gpu/drm/nouveau/core/include/engine/device.h index b3dd2c4c2f1..672d3c8f414 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/device.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/device.h @@ -3,11 +3,20 @@  #include <core/device.h> -#define nouveau_device_create(p,n,s,c,d,u)                                     \ -	nouveau_device_create_((p), (n), (s), (c), (d), sizeof(**u), (void **)u) +struct platform_device; -int  nouveau_device_create_(struct pci_dev *, u64 name, const char *sname, -			    const char *cfg, const char *dbg, int, void **); +enum nv_bus_type { +	NOUVEAU_BUS_PCI, +	NOUVEAU_BUS_PLATFORM, +}; + +#define nouveau_device_create(p,t,n,s,c,d,u)                                   \ +	nouveau_device_create_((void *)(p), (t), (n), (s), (c), (d),           \ +			       sizeof(**u), (void **)u) + +int  nouveau_device_create_(void *, enum nv_bus_type type, u64 name, +			    const char *sname, const char *cfg, const char *dbg, +			    int, void **);  int nv04_identify(struct nouveau_device *);  int nv10_identify(struct nouveau_device *); @@ -17,6 +26,7 @@ int nv40_identify(struct nouveau_device *);  int nv50_identify(struct nouveau_device *);  int nvc0_identify(struct nouveau_device *);  int nve0_identify(struct nouveau_device *); +int gm100_identify(struct nouveau_device *);  struct nouveau_device *nouveau_device_find(u64 name); diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h index 4b21fabfbdd..fde84289680 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/disp.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h @@ -6,8 +6,19 @@  #include <core/device.h>  #include <core/event.h> +enum nvkm_hpd_event { +	NVKM_HPD_PLUG = 1, +	NVKM_HPD_UNPLUG = 2, +	NVKM_HPD_IRQ = 4, +	NVKM_HPD = (NVKM_HPD_PLUG | NVKM_HPD_UNPLUG | NVKM_HPD_IRQ) +}; +  struct nouveau_disp {  	struct nouveau_engine base; + +	struct list_head outp; +	struct nouveau_event *hpd; +  	struct nouveau_event *vblank;  }; @@ -17,33 +28,15 @@ nouveau_disp(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP];  } -#define nouveau_disp_create(p,e,c,h,i,x,d)                                     \ -	nouveau_disp_create_((p), (e), (c), (h), (i), (x),                     \ -			     sizeof(**d), (void **)d) -#define nouveau_disp_destroy(d) ({                                             \ -	struct nouveau_disp *disp = (d);                                       \ -	_nouveau_disp_dtor(nv_object(disp));                                   \ -}) -#define nouveau_disp_init(d)                                                   \ -	nouveau_engine_init(&(d)->base) -#define nouveau_disp_fini(d,s)                                                 \ -	nouveau_engine_fini(&(d)->base, (s)) - -int  nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *, -			  struct nouveau_oclass *, int heads, -			  const char *, const char *, int, void **); -void _nouveau_disp_dtor(struct nouveau_object *); -#define _nouveau_disp_init _nouveau_engine_init -#define _nouveau_disp_fini _nouveau_engine_fini - -extern struct nouveau_oclass nv04_disp_oclass; -extern struct nouveau_oclass nv50_disp_oclass; -extern struct nouveau_oclass nv84_disp_oclass; -extern struct nouveau_oclass nva0_disp_oclass; -extern struct nouveau_oclass nv94_disp_oclass; -extern struct nouveau_oclass nva3_disp_oclass; -extern struct nouveau_oclass nvd0_disp_oclass; -extern struct nouveau_oclass nve0_disp_oclass; -extern struct nouveau_oclass nvf0_disp_oclass; +extern struct nouveau_oclass *nv04_disp_oclass; +extern struct nouveau_oclass *nv50_disp_oclass; +extern struct nouveau_oclass *nv84_disp_oclass; +extern struct nouveau_oclass *nva0_disp_oclass; +extern struct nouveau_oclass *nv94_disp_oclass; +extern struct nouveau_oclass *nva3_disp_oclass; +extern struct nouveau_oclass *nvd0_disp_oclass; +extern struct nouveau_oclass *nve0_disp_oclass; +extern struct nouveau_oclass *nvf0_disp_oclass; +extern struct nouveau_oclass *gm107_disp_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index 633c2f80648..b639eb2c74f 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -101,14 +101,16 @@ nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid);  #define _nouveau_fifo_init _nouveau_engine_init  #define _nouveau_fifo_fini _nouveau_engine_fini -extern struct nouveau_oclass nv04_fifo_oclass; -extern struct nouveau_oclass nv10_fifo_oclass; -extern struct nouveau_oclass nv17_fifo_oclass; -extern struct nouveau_oclass nv40_fifo_oclass; -extern struct nouveau_oclass nv50_fifo_oclass; -extern struct nouveau_oclass nv84_fifo_oclass; -extern struct nouveau_oclass nvc0_fifo_oclass; -extern struct nouveau_oclass nve0_fifo_oclass; +extern struct nouveau_oclass *nv04_fifo_oclass; +extern struct nouveau_oclass *nv10_fifo_oclass; +extern struct nouveau_oclass *nv17_fifo_oclass; +extern struct nouveau_oclass *nv40_fifo_oclass; +extern struct nouveau_oclass *nv50_fifo_oclass; +extern struct nouveau_oclass *nv84_fifo_oclass; +extern struct nouveau_oclass *nvc0_fifo_oclass; +extern struct nouveau_oclass *nve0_fifo_oclass; +extern struct nouveau_oclass *gk20a_fifo_oclass; +extern struct nouveau_oclass *nv108_fifo_oclass;  void nv04_fifo_intr(struct nouveau_subdev *);  int  nv04_fifo_context_attach(struct nouveau_object *, struct nouveau_object *); diff --git a/drivers/gpu/drm/nouveau/core/include/engine/graph.h b/drivers/gpu/drm/nouveau/core/include/engine/graph.h index 8e1b52312dd..8c1d4772da0 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/graph.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/graph.h @@ -63,12 +63,15 @@ extern struct nouveau_oclass nv40_graph_oclass;  extern struct nouveau_oclass nv50_graph_oclass;  extern struct nouveau_oclass *nvc0_graph_oclass;  extern struct nouveau_oclass *nvc1_graph_oclass; -extern struct nouveau_oclass *nvc3_graph_oclass; +extern struct nouveau_oclass *nvc4_graph_oclass;  extern struct nouveau_oclass *nvc8_graph_oclass;  extern struct nouveau_oclass *nvd7_graph_oclass;  extern struct nouveau_oclass *nvd9_graph_oclass;  extern struct nouveau_oclass *nve4_graph_oclass; +extern struct nouveau_oclass *gk20a_graph_oclass;  extern struct nouveau_oclass *nvf0_graph_oclass; +extern struct nouveau_oclass *nv108_graph_oclass; +extern struct nouveau_oclass *gm107_graph_oclass;  extern const struct nouveau_bitfield nv04_graph_nsource[];  extern struct nouveau_ofuncs nv04_graph_ofuncs; diff --git a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h index 1d1a89a06ee..9b0d938199f 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/mpeg.h @@ -42,10 +42,13 @@ struct nouveau_mpeg {  extern struct nouveau_oclass nv31_mpeg_oclass;  extern struct nouveau_oclass nv40_mpeg_oclass; +extern struct nouveau_oclass nv44_mpeg_oclass;  extern struct nouveau_oclass nv50_mpeg_oclass;  extern struct nouveau_oclass nv84_mpeg_oclass; - +extern struct nouveau_ofuncs nv31_mpeg_ofuncs; +extern struct nouveau_oclass nv31_mpeg_cclass;  extern struct nouveau_oclass nv31_mpeg_sclass[]; +extern struct nouveau_oclass nv40_mpeg_sclass[];  void nv31_mpeg_intr(struct nouveau_subdev *);  void nv31_mpeg_tile_prog(struct nouveau_engine *, int);  int  nv31_mpeg_init(struct nouveau_object *); diff --git a/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h b/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h new file mode 100644 index 00000000000..49b0024910f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/engine/perfmon.h @@ -0,0 +1,39 @@ +#ifndef __NVKM_PERFMON_H__ +#define __NVKM_PERFMON_H__ + +#include <core/device.h> +#include <core/engine.h> +#include <core/engctx.h> +#include <core/class.h> + +struct nouveau_perfdom; +struct nouveau_perfctr; +struct nouveau_perfmon { +	struct nouveau_engine base; + +	struct nouveau_perfctx *context; +	void *profile_data; + +	struct list_head domains; +	u32 sequence; + +	/*XXX: temp for daemon backend */ +	u32 pwr[8]; +	u32 last; +}; + +static inline struct nouveau_perfmon * +nouveau_perfmon(void *obj) +{ +	return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_PERFMON]; +} + +extern struct nouveau_oclass *nv40_perfmon_oclass; +extern struct nouveau_oclass *nv50_perfmon_oclass; +extern struct nouveau_oclass *nv84_perfmon_oclass; +extern struct nouveau_oclass *nva3_perfmon_oclass; +extern struct nouveau_oclass nvc0_perfmon_oclass; +extern struct nouveau_oclass nve0_perfmon_oclass; +extern struct nouveau_oclass nvf0_perfmon_oclass; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/engine/software.h b/drivers/gpu/drm/nouveau/core/include/engine/software.h index 45799487e57..23a462b50d0 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/software.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/software.h @@ -3,19 +3,10 @@  #include <core/engine.h>  #include <core/engctx.h> -#include <core/event.h>  struct nouveau_software_chan {  	struct nouveau_engctx base; -	struct { -		struct nouveau_eventh event; -		u32 channel; -		u32 ctxdma; -		u64 offset; -		u32 value; -	} vblank; -  	int (*flip)(void *);  	void *flip_data;  }; @@ -50,10 +41,10 @@ struct nouveau_software {  #define _nouveau_software_init _nouveau_engine_init  #define _nouveau_software_fini _nouveau_engine_fini -extern struct nouveau_oclass nv04_software_oclass; -extern struct nouveau_oclass nv10_software_oclass; -extern struct nouveau_oclass nv50_software_oclass; -extern struct nouveau_oclass nvc0_software_oclass; +extern struct nouveau_oclass *nv04_software_oclass; +extern struct nouveau_oclass *nv10_software_oclass; +extern struct nouveau_oclass *nv50_software_oclass; +extern struct nouveau_oclass *nvc0_software_oclass;  void nv04_software_intr(struct nouveau_subdev *); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h index 4f4ff4502c3..9faa98e67ad 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bar.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bar.h @@ -4,8 +4,7 @@  #include <core/subdev.h>  #include <core/device.h> -#include <subdev/fb.h> - +struct nouveau_mem;  struct nouveau_vma;  struct nouveau_bar { @@ -29,27 +28,7 @@ nouveau_bar(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BAR];  } -#define nouveau_bar_create(p,e,o,d)                                            \ -	nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nouveau_bar_init(p)                                                    \ -	nouveau_subdev_init(&(p)->base) -#define nouveau_bar_fini(p,s)                                                  \ -	nouveau_subdev_fini(&(p)->base, (s)) - -int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *, -			struct nouveau_oclass *, int, void **); -void nouveau_bar_destroy(struct nouveau_bar *); - -void _nouveau_bar_dtor(struct nouveau_object *); -#define _nouveau_bar_init _nouveau_subdev_init -#define _nouveau_bar_fini _nouveau_subdev_fini -  extern struct nouveau_oclass nv50_bar_oclass;  extern struct nouveau_oclass nvc0_bar_oclass; -int nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *, -		      struct nouveau_mem *, struct nouveau_object **); - -void nv84_bar_flush(struct nouveau_bar *); -  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h new file mode 100644 index 00000000000..bba01ab1e04 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/P0260.h @@ -0,0 +1,23 @@ +#ifndef __NVBIOS_P0260_H__ +#define __NVBIOS_P0260_H__ + +u32 nvbios_P0260Te(struct nouveau_bios *, +		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz); + +struct nvbios_P0260E { +	u32 data; +}; + +u32 nvbios_P0260Ee(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr); +u32 nvbios_P0260Ep(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr, +		   struct nvbios_P0260E *); + +struct nvbios_P0260X { +	u32 data; +}; + +u32 nvbios_P0260Xe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr); +u32 nvbios_P0260Xp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr, +		   struct nvbios_P0260X *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h new file mode 100644 index 00000000000..662b2072685 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/boost.h @@ -0,0 +1,29 @@ +#ifndef __NVBIOS_BOOST_H__ +#define __NVBIOS_BOOST_H__ + +u16 nvbios_boostTe(struct nouveau_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *); + +struct nvbios_boostE { +	u8  pstate; +	u32 min; +	u32 max; +}; + +u16 nvbios_boostEe(struct nouveau_bios *, int idx, u8 *, u8 *, u8 *, u8 *); +u16 nvbios_boostEp(struct nouveau_bios *, int idx, u8 *, u8 *, u8 *, u8 *, +		   struct nvbios_boostE *); +u16 nvbios_boostEm(struct nouveau_bios *, u8, u8 *, u8 *, u8 *, u8 *, +		   struct nvbios_boostE *); + +struct nvbios_boostS { +	u8  domain; +	u8  percent; +	u32 min; +	u32 max; +}; + +u16 nvbios_boostSe(struct nouveau_bios *, int, u16, u8 *, u8 *, u8, u8); +u16 nvbios_boostSp(struct nouveau_bios *, int, u16, u8 *, u8 *, u8, u8, +		   struct nvbios_boostS *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h index c1270548fd0..f3930c27cb7 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h @@ -16,12 +16,31 @@ enum dcb_connector_type {  	DCB_CONNECTOR_eDP = 0x47,  	DCB_CONNECTOR_HDMI_0 = 0x60,  	DCB_CONNECTOR_HDMI_1 = 0x61, +	DCB_CONNECTOR_HDMI_C = 0x63,  	DCB_CONNECTOR_DMS59_DP0 = 0x64,  	DCB_CONNECTOR_DMS59_DP1 = 0x65,  	DCB_CONNECTOR_NONE = 0xff  }; -u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); -u16 dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len); +struct nvbios_connT { +}; + +u32 nvbios_connTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u32 nvbios_connTp(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		  struct nvbios_connT *info); + +struct nvbios_connE { +	u8 type; +	u8 location; +	u8 hpd; +	u8 dp; +	u8 di; +	u8 sr; +	u8 lcdid; +}; + +u32 nvbios_connEe(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *hdr); +u32 nvbios_connEp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *hdr, +		  struct nvbios_connE *info);  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h new file mode 100644 index 00000000000..a80a4380988 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/cstep.h @@ -0,0 +1,28 @@ +#ifndef __NVBIOS_CSTEP_H__ +#define __NVBIOS_CSTEP_H__ + +u16 nvbios_cstepTe(struct nouveau_bios *, +		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz); + +struct nvbios_cstepE { +	u8  pstate; +	u8  index; +}; + +u16 nvbios_cstepEe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr); +u16 nvbios_cstepEp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr, +		   struct nvbios_cstepE *); +u16 nvbios_cstepEm(struct nouveau_bios *, u8 pstate, u8 *ver, u8 *hdr, +		   struct nvbios_cstepE *); + +struct nvbios_cstepX { +	u32 freq; +	u8  unkn[2]; +	u8  voltage; +}; + +u16 nvbios_cstepXe(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr); +u16 nvbios_cstepXp(struct nouveau_bios *, int idx, u8 *ver, u8 *hdr, +		   struct nvbios_cstepX *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h index 6e54218b55f..728206e2177 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h @@ -17,9 +17,10 @@ u16 nvbios_dpout_match(struct nouveau_bios *, u16 type, u16 mask,  		       struct nvbios_dpout *);  struct nvbios_dpcfg { -	u8 drv; -	u8 pre; -	u8 unk; +	u8 pc; +	u8 dc; +	u8 pe; +	u8 tx_pu;  };  u16 @@ -27,7 +28,7 @@ nvbios_dpcfg_parse(struct nouveau_bios *, u16 outp, u8 idx,  		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,  		   struct nvbios_dpcfg *);  u16 -nvbios_dpcfg_match(struct nouveau_bios *, u16 outp, u8 un, u8 vs, u8 pe, +nvbios_dpcfg_match(struct nouveau_bios *, u16 outp, u8 pc, u8 vs, u8 pe,  		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,  		   struct nvbios_dpcfg *); diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index 96d3364f6db..c7b2e586be0 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h @@ -7,7 +7,15 @@ enum dcb_gpio_func_name {  	DCB_GPIO_TVDAC1 = 0x2d,  	DCB_GPIO_FAN = 0x09,  	DCB_GPIO_FAN_SENSE = 0x3d, -	DCB_GPIO_UNUSED = 0xff +	DCB_GPIO_UNUSED = 0xff, +	DCB_GPIO_VID0 = 0x04, +	DCB_GPIO_VID1 = 0x05, +	DCB_GPIO_VID2 = 0x06, +	DCB_GPIO_VID3 = 0x1a, +	DCB_GPIO_VID4 = 0x73, +	DCB_GPIO_VID5 = 0x74, +	DCB_GPIO_VID6 = 0x75, +	DCB_GPIO_VID7 = 0x76,  };  #define DCB_GPIO_LOG_DIR     0x02 diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h index 0b285e99be5..16ff06ec2a8 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/perf.h @@ -3,6 +3,39 @@  struct nouveau_bios; +u16 nvbios_perf_table(struct nouveau_bios *, u8 *ver, u8 *hdr, +		      u8 *cnt, u8 *len, u8 *snr, u8 *ssz); + +struct nvbios_perfE { +	u8  pstate; +	u8  fanspeed; +	u8  voltage; +	u32 core; +	u32 shader; +	u32 memory; +	u32 vdec; +	u32 disp; +	u32 script; +}; + +u16 nvbios_perf_entry(struct nouveau_bios *, int idx, +		      u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 nvbios_perfEp(struct nouveau_bios *, int idx, +		  u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *); + +struct nvbios_perfS { +	union { +		struct { +			u32 freq; +		} v40; +	}; +}; + +u32 nvbios_perfSe(struct nouveau_bios *, u32 data, int idx, +		  u8 *ver, u8 *hdr, u8 cnt, u8 len); +u32 nvbios_perfSp(struct nouveau_bios *, u32 data, int idx, +		  u8 *ver, u8 *hdr, u8 cnt, u8 len, struct nvbios_perfS *); +  struct nvbios_perf_fan {  	u32 pwm_divisor;  }; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h new file mode 100644 index 00000000000..c086ac6d677 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/ramcfg.h @@ -0,0 +1,66 @@ +#ifndef __NVBIOS_RAMCFG_H__ +#define __NVBIOS_RAMCFG_H__ + +struct nouveau_bios; + +struct nvbios_ramcfg { +	unsigned rammap_11_08_01:1; +	unsigned rammap_11_08_0c:2; +	unsigned rammap_11_08_10:1; +	unsigned rammap_11_11_0c:2; + +	unsigned ramcfg_11_01_01:1; +	unsigned ramcfg_11_01_02:1; +	unsigned ramcfg_11_01_04:1; +	unsigned ramcfg_11_01_08:1; +	unsigned ramcfg_11_01_10:1; +	unsigned ramcfg_11_01_20:1; +	unsigned ramcfg_11_01_40:1; +	unsigned ramcfg_11_01_80:1; +	unsigned ramcfg_11_02_03:2; +	unsigned ramcfg_11_02_04:1; +	unsigned ramcfg_11_02_08:1; +	unsigned ramcfg_11_02_10:1; +	unsigned ramcfg_11_02_40:1; +	unsigned ramcfg_11_02_80:1; +	unsigned ramcfg_11_03_0f:4; +	unsigned ramcfg_11_03_30:2; +	unsigned ramcfg_11_03_c0:2; +	unsigned ramcfg_11_03_f0:4; +	unsigned ramcfg_11_04:8; +	unsigned ramcfg_11_06:8; +	unsigned ramcfg_11_07_02:1; +	unsigned ramcfg_11_07_04:1; +	unsigned ramcfg_11_07_08:1; +	unsigned ramcfg_11_07_10:1; +	unsigned ramcfg_11_07_40:1; +	unsigned ramcfg_11_07_80:1; +	unsigned ramcfg_11_08_01:1; +	unsigned ramcfg_11_08_02:1; +	unsigned ramcfg_11_08_04:1; +	unsigned ramcfg_11_08_08:1; +	unsigned ramcfg_11_08_10:1; +	unsigned ramcfg_11_08_20:1; +	unsigned ramcfg_11_09:8; + +	unsigned timing[11]; +	unsigned timing_20_2e_03:2; +	unsigned timing_20_2e_30:2; +	unsigned timing_20_2e_c0:2; +	unsigned timing_20_2f_03:2; +	unsigned timing_20_2c_003f:6; +	unsigned timing_20_2c_1fc0:7; +	unsigned timing_20_30_f8:5; +	unsigned timing_20_30_07:3; +	unsigned timing_20_31_0007:3; +	unsigned timing_20_31_0078:4; +	unsigned timing_20_31_0780:4; +	unsigned timing_20_31_0800:1; +	unsigned timing_20_31_7000:3; +	unsigned timing_20_31_8000:1; +}; + +u8 nvbios_ramcfg_count(struct nouveau_bios *); +u8 nvbios_ramcfg_index(struct nouveau_subdev *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h new file mode 100644 index 00000000000..5bdf8e4db40 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/rammap.h @@ -0,0 +1,25 @@ +#ifndef __NVBIOS_RAMMAP_H__ +#define __NVBIOS_RAMMAP_H__ + +struct nvbios_ramcfg; + +u32 nvbios_rammapTe(struct nouveau_bios *, u8 *ver, u8 *hdr, +		    u8 *cnt, u8 *len, u8 *snr, u8 *ssz); + +u32 nvbios_rammapEe(struct nouveau_bios *, int idx, +		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u32 nvbios_rammapEm(struct nouveau_bios *, u16 mhz, +		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u32 nvbios_rammapEp(struct nouveau_bios *, u16 mhz, +		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		    struct nvbios_ramcfg *); + +u32 nvbios_rammapSe(struct nouveau_bios *, u32 data, +		    u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, +		    u8 *ver, u8 *hdr); +u32 nvbios_rammapSp(struct nouveau_bios *, u32 data, +		    u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, +		    u8 *ver, u8 *hdr, +		    struct nvbios_ramcfg *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h index 083541dbe9c..8dc5051df55 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h @@ -31,6 +31,12 @@ struct nouveau_therm_trip_point {  	int hysteresis;  }; +enum nvbios_therm_fan_mode { +	NVBIOS_THERM_FAN_TRIP = 0, +	NVBIOS_THERM_FAN_LINEAR = 1, +	NVBIOS_THERM_FAN_OTHER = 2, +}; +  struct nvbios_therm_fan {  	u16 pwm_freq; @@ -40,6 +46,7 @@ struct nvbios_therm_fan {  	u16 bump_period;  	u16 slow_down_period; +	enum nvbios_therm_fan_mode fan_mode;  	struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX];  	u8 nr_fan_trip;  	u8 linear_min_temp; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h new file mode 100644 index 00000000000..76d914b67ab --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/timing.h @@ -0,0 +1,14 @@ +#ifndef __NVBIOS_TIMING_H__ +#define __NVBIOS_TIMING_H__ + +struct nvbios_ramcfg; + +u16 nvbios_timingTe(struct nouveau_bios *, +		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz); +u16 nvbios_timingEe(struct nouveau_bios *, int idx, +		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 nvbios_timingEp(struct nouveau_bios *, int idx, +		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		    struct nvbios_ramcfg *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h new file mode 100644 index 00000000000..ad5a8f20e11 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/vmap.h @@ -0,0 +1,25 @@ +#ifndef __NVBIOS_VMAP_H__ +#define __NVBIOS_VMAP_H__ + +struct nouveau_bios; + +struct nvbios_vmap { +}; + +u16 nvbios_vmap_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 nvbios_vmap_parse(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		      struct nvbios_vmap *); + +struct nvbios_vmap_entry { +	u8  unk0; +	u8  link; +	u32 min; +	u32 max; +	s32 arg[6]; +}; + +u16 nvbios_vmap_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *len); +u16 nvbios_vmap_entry_parse(struct nouveau_bios *, int idx, u8 *ver, u8 *len, +			    struct nvbios_vmap_entry *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h new file mode 100644 index 00000000000..6a11dcd5977 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/volt.h @@ -0,0 +1,27 @@ +#ifndef __NVBIOS_VOLT_H__ +#define __NVBIOS_VOLT_H__ + +struct nouveau_bios; + +struct nvbios_volt { +	u8  vidmask; +	u32 min; +	u32 max; +	u32 base; +	s16 step; +}; + +u16 nvbios_volt_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); +u16 nvbios_volt_parse(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		      struct nvbios_volt *); + +struct nvbios_volt_entry { +	u32 voltage; +	u8  vid; +}; + +u16 nvbios_volt_entry(struct nouveau_bios *, int idx, u8 *ver, u8 *len); +u16 nvbios_volt_entry_parse(struct nouveau_bios *, int idx, u8 *ver, u8 *len, +			    struct nvbios_volt_entry *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bus.h b/drivers/gpu/drm/nouveau/core/include/subdev/bus.h index 7d88ec4a6d0..697f7ce70aa 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bus.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bus.h @@ -11,6 +11,8 @@ struct nouveau_bus_intr {  struct nouveau_bus {  	struct nouveau_subdev base; +	int (*hwsq_exec)(struct nouveau_bus *, u32 *, u32); +	u32 hwsq_size;  };  static inline struct nouveau_bus * @@ -33,9 +35,19 @@ nouveau_bus(void *obj)  #define _nouveau_bus_init _nouveau_subdev_init  #define _nouveau_bus_fini _nouveau_subdev_fini -extern struct nouveau_oclass nv04_bus_oclass; -extern struct nouveau_oclass nv31_bus_oclass; -extern struct nouveau_oclass nv50_bus_oclass; -extern struct nouveau_oclass nvc0_bus_oclass; +extern struct nouveau_oclass *nv04_bus_oclass; +extern struct nouveau_oclass *nv31_bus_oclass; +extern struct nouveau_oclass *nv50_bus_oclass; +extern struct nouveau_oclass *nv94_bus_oclass; +extern struct nouveau_oclass *nvc0_bus_oclass; + +/* interface to sequencer */ +struct nouveau_hwsq; +int  nouveau_hwsq_init(struct nouveau_bus *, struct nouveau_hwsq **); +int  nouveau_hwsq_fini(struct nouveau_hwsq **, bool exec); +void nouveau_hwsq_wr32(struct nouveau_hwsq *, u32 addr, u32 data); +void nouveau_hwsq_setf(struct nouveau_hwsq *, u8 flag, int data); +void nouveau_hwsq_wait(struct nouveau_hwsq *, u8 flag, u8 data); +void nouveau_hwsq_nsec(struct nouveau_hwsq *, u32 nsec);  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 89ee289097a..c01e29c9f89 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -7,9 +7,83 @@  struct nouveau_pll_vals;  struct nvbios_pll; +enum nv_clk_src { +	nv_clk_src_crystal, +	nv_clk_src_href, + +	nv_clk_src_hclk, +	nv_clk_src_hclkm3, +	nv_clk_src_hclkm3d2, +	nv_clk_src_hclkm2d3, /* NVAA */ +	nv_clk_src_hclkm4, /* NVAA */ +	nv_clk_src_cclk, /* NVAA */ + +	nv_clk_src_host, + +	nv_clk_src_sppll0, +	nv_clk_src_sppll1, + +	nv_clk_src_mpllsrcref, +	nv_clk_src_mpllsrc, +	nv_clk_src_mpll, +	nv_clk_src_mdiv, + +	nv_clk_src_core, +	nv_clk_src_shader, + +	nv_clk_src_mem, + +	nv_clk_src_gpc, +	nv_clk_src_rop, +	nv_clk_src_hubk01, +	nv_clk_src_hubk06, +	nv_clk_src_hubk07, +	nv_clk_src_copy, +	nv_clk_src_daemon, +	nv_clk_src_disp, +	nv_clk_src_vdec, + +	nv_clk_src_dom6, + +	nv_clk_src_max, +}; + +struct nouveau_cstate { +	struct list_head head; +	u8  voltage; +	u32 domain[nv_clk_src_max]; +}; + +struct nouveau_pstate { +	struct list_head head; +	struct list_head list; /* c-states */ +	struct nouveau_cstate base; +	u8 pstate; +	u8 fanspeed; +}; +  struct nouveau_clock {  	struct nouveau_subdev base; +	struct nouveau_clocks *domains; +	struct nouveau_pstate bstate; + +	struct list_head states; +	int state_nr; + +	int pstate; /* current */ +	int ustate; /* user-requested (-1 disabled, -2 perfmon) */ +	int astate; /* perfmon adjustment (base) */ +	int tstate; /* thermal adjustment (max-) */ +	int dstate; /* display adjustment (min+) */ + +	bool allow_reclock; + +	int  (*read)(struct nouveau_clock *, enum nv_clk_src); +	int  (*calc)(struct nouveau_clock *, struct nouveau_cstate *); +	int  (*prog)(struct nouveau_clock *); +	void (*tidy)(struct nouveau_clock *); +  	/*XXX: die, these are here *only* to support the completely  	 *     bat-shit insane what-was-nouveau_hw.c code  	 */ @@ -25,27 +99,43 @@ nouveau_clock(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_CLOCK];  } -#define nouveau_clock_create(p,e,o,d)                                          \ -	nouveau_subdev_create((p), (e), (o), 0, "CLOCK", "clock", d) -#define nouveau_clock_destroy(p)                                               \ -	nouveau_subdev_destroy(&(p)->base) -#define nouveau_clock_init(p)                                                  \ -	nouveau_subdev_init(&(p)->base) +struct nouveau_clocks { +	enum nv_clk_src name; +	u8 bios; /* 0xff for none */ +#define NVKM_CLK_DOM_FLAG_CORE 0x01 +	u8 flags; +	const char *mname; +	int mdiv; +}; + +#define nouveau_clock_create(p,e,o,i,r,d)                                      \ +	nouveau_clock_create_((p), (e), (o), (i), (r), sizeof(**d), (void **)d) +#define nouveau_clock_destroy(p) ({                                            \ +	struct nouveau_clock *clk = (p);                                       \ +	_nouveau_clock_dtor(nv_object(clk));                                   \ +}) +#define nouveau_clock_init(p) ({                                               \ +	struct nouveau_clock *clk = (p);                                       \ +	_nouveau_clock_init(nv_object(clk));                                   \ +})  #define nouveau_clock_fini(p,s)                                                \  	nouveau_subdev_fini(&(p)->base, (s))  int  nouveau_clock_create_(struct nouveau_object *, struct nouveau_object *, -			   struct nouveau_oclass *, void *, u32, int, void **); - -#define _nouveau_clock_dtor _nouveau_subdev_dtor -#define _nouveau_clock_init _nouveau_subdev_init +			   struct nouveau_oclass *, +			   struct nouveau_clocks *, bool, int, void **); +void _nouveau_clock_dtor(struct nouveau_object *); +int _nouveau_clock_init(struct nouveau_object *);  #define _nouveau_clock_fini _nouveau_subdev_fini  extern struct nouveau_oclass nv04_clock_oclass;  extern struct nouveau_oclass nv40_clock_oclass; -extern struct nouveau_oclass nv50_clock_oclass; +extern struct nouveau_oclass *nv50_clock_oclass; +extern struct nouveau_oclass *nv84_clock_oclass; +extern struct nouveau_oclass *nvaa_clock_oclass;  extern struct nouveau_oclass nva3_clock_oclass;  extern struct nouveau_oclass nvc0_clock_oclass; +extern struct nouveau_oclass nve0_clock_oclass;  int nv04_clock_pll_set(struct nouveau_clock *, u32 type, u32 freq);  int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, @@ -55,4 +145,9 @@ int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,  int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,  			int clk, struct nouveau_pll_vals *); +int nouveau_clock_ustate(struct nouveau_clock *, int req); +int nouveau_clock_astate(struct nouveau_clock *, int req, int rel); +int nouveau_clock_dstate(struct nouveau_clock *, int req, int rel); +int nouveau_clock_tstate(struct nouveau_clock *, int req, int rel); +  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h index 685c9b12ee4..e292271a84e 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/devinit.h @@ -9,7 +9,7 @@ struct nouveau_devinit {  	bool post;  	void (*meminit)(struct nouveau_devinit *);  	int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq); - +	u32  (*mmio)(struct nouveau_devinit *, u32 addr);  };  static inline struct nouveau_devinit * @@ -18,32 +18,17 @@ nouveau_devinit(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DEVINIT];  } -#define nouveau_devinit_create(p,e,o,d)                                        \ -	nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nouveau_devinit_destroy(p)                                             \ -	nouveau_subdev_destroy(&(p)->base) -#define nouveau_devinit_init(p) ({                                             \ -	struct nouveau_devinit *d = (p);                                       \ -	_nouveau_devinit_init(nv_object(d));                                   \ -}) -#define nouveau_devinit_fini(p,s) ({                                           \ -	struct nouveau_devinit *d = (p);                                       \ -	_nouveau_devinit_fini(nv_object(d), (s));                              \ -}) - -int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *, -			    struct nouveau_oclass *, int, void **); -#define _nouveau_devinit_dtor _nouveau_subdev_dtor -int _nouveau_devinit_init(struct nouveau_object *); -int _nouveau_devinit_fini(struct nouveau_object *, bool suspend); - -extern struct nouveau_oclass nv04_devinit_oclass; -extern struct nouveau_oclass nv05_devinit_oclass; -extern struct nouveau_oclass nv10_devinit_oclass; -extern struct nouveau_oclass nv1a_devinit_oclass; -extern struct nouveau_oclass nv20_devinit_oclass; -extern struct nouveau_oclass nv50_devinit_oclass; -extern struct nouveau_oclass nva3_devinit_oclass; -extern struct nouveau_oclass nvc0_devinit_oclass; +extern struct nouveau_oclass *nv04_devinit_oclass; +extern struct nouveau_oclass *nv05_devinit_oclass; +extern struct nouveau_oclass *nv10_devinit_oclass; +extern struct nouveau_oclass *nv1a_devinit_oclass; +extern struct nouveau_oclass *nv20_devinit_oclass; +extern struct nouveau_oclass *nv50_devinit_oclass; +extern struct nouveau_oclass *nv84_devinit_oclass; +extern struct nouveau_oclass *nv98_devinit_oclass; +extern struct nouveau_oclass *nva3_devinit_oclass; +extern struct nouveau_oclass *nvaf_devinit_oclass; +extern struct nouveau_oclass *nvc0_devinit_oclass; +extern struct nouveau_oclass *gm107_devinit_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index 2e740508426..871e73914b2 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -75,26 +75,45 @@ struct nouveau_fb {  static inline struct nouveau_fb *  nouveau_fb(void *obj)  { +	/* fbram uses this before device subdev pointer is valid */ +	if (nv_iclass(obj, NV_SUBDEV_CLASS) && +	    nv_subidx(obj) == NVDEV_SUBDEV_FB) +		return obj; +  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_FB];  } -extern struct nouveau_oclass nv04_fb_oclass; -extern struct nouveau_oclass nv10_fb_oclass; -extern struct nouveau_oclass nv1a_fb_oclass; -extern struct nouveau_oclass nv20_fb_oclass; -extern struct nouveau_oclass nv25_fb_oclass; -extern struct nouveau_oclass nv30_fb_oclass; -extern struct nouveau_oclass nv35_fb_oclass; -extern struct nouveau_oclass nv36_fb_oclass; -extern struct nouveau_oclass nv40_fb_oclass; -extern struct nouveau_oclass nv41_fb_oclass; -extern struct nouveau_oclass nv44_fb_oclass; -extern struct nouveau_oclass nv46_fb_oclass; -extern struct nouveau_oclass nv47_fb_oclass; -extern struct nouveau_oclass nv49_fb_oclass; -extern struct nouveau_oclass nv4e_fb_oclass; -extern struct nouveau_oclass nv50_fb_oclass; -extern struct nouveau_oclass nvc0_fb_oclass; +extern struct nouveau_oclass *nv04_fb_oclass; +extern struct nouveau_oclass *nv10_fb_oclass; +extern struct nouveau_oclass *nv1a_fb_oclass; +extern struct nouveau_oclass *nv20_fb_oclass; +extern struct nouveau_oclass *nv25_fb_oclass; +extern struct nouveau_oclass *nv30_fb_oclass; +extern struct nouveau_oclass *nv35_fb_oclass; +extern struct nouveau_oclass *nv36_fb_oclass; +extern struct nouveau_oclass *nv40_fb_oclass; +extern struct nouveau_oclass *nv41_fb_oclass; +extern struct nouveau_oclass *nv44_fb_oclass; +extern struct nouveau_oclass *nv46_fb_oclass; +extern struct nouveau_oclass *nv47_fb_oclass; +extern struct nouveau_oclass *nv49_fb_oclass; +extern struct nouveau_oclass *nv4e_fb_oclass; +extern struct nouveau_oclass *nv50_fb_oclass; +extern struct nouveau_oclass *nv84_fb_oclass; +extern struct nouveau_oclass *nva3_fb_oclass; +extern struct nouveau_oclass *nvaa_fb_oclass; +extern struct nouveau_oclass *nvaf_fb_oclass; +extern struct nouveau_oclass *nvc0_fb_oclass; +extern struct nouveau_oclass *nve0_fb_oclass; +extern struct nouveau_oclass *gk20a_fb_oclass; +extern struct nouveau_oclass *gm107_fb_oclass; + +#include <subdev/bios/ramcfg.h> + +struct nouveau_ram_data { +	struct nvbios_ramcfg bios; +	u32 freq; +};  struct nouveau_ram {  	struct nouveau_object base; @@ -121,6 +140,23 @@ struct nouveau_ram {  	int  (*get)(struct nouveau_fb *, u64 size, u32 align,  		    u32 size_nc, u32 type, struct nouveau_mem **);  	void (*put)(struct nouveau_fb *, struct nouveau_mem **); + +	int  (*calc)(struct nouveau_fb *, u32 freq); +	int  (*prog)(struct nouveau_fb *); +	void (*tidy)(struct nouveau_fb *); +	struct { +		u8  version; +		u32 data; +		u8  size; +	} rammap, ramcfg, timing; +	u32 freq; +	u32 mr[16]; +	u32 mr1_nuts; + +	struct nouveau_ram_data *next; +	struct nouveau_ram_data former; +	struct nouveau_ram_data xition; +	struct nouveau_ram_data target;  };  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index c85b9f1579a..612d82ab683 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h @@ -8,17 +8,18 @@  #include <subdev/bios.h>  #include <subdev/bios/gpio.h> +enum nvkm_gpio_event { +	NVKM_GPIO_HI = 1, +	NVKM_GPIO_LO = 2, +	NVKM_GPIO_TOGGLED = (NVKM_GPIO_HI | NVKM_GPIO_LO), +}; +  struct nouveau_gpio {  	struct nouveau_subdev base;  	struct nouveau_event *events; -	/* hardware interfaces */  	void (*reset)(struct nouveau_gpio *, u8 func); -	int  (*drive)(struct nouveau_gpio *, int line, int dir, int out); -	int  (*sense)(struct nouveau_gpio *, int line); - -	/* software interfaces */  	int  (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line,  		     struct dcb_gpio_func *);  	int  (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); @@ -31,23 +32,10 @@ nouveau_gpio(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO];  } -#define nouveau_gpio_create(p,e,o,l,d)                                         \ -	nouveau_gpio_create_((p), (e), (o), (l), sizeof(**d), (void **)d) -#define nouveau_gpio_destroy(p) ({                                             \ -	struct nouveau_gpio *gpio = (p);                                       \ -	_nouveau_gpio_dtor(nv_object(gpio));                                   \ -}) -#define nouveau_gpio_fini(p,s)                                                 \ -	nouveau_subdev_fini(&(p)->base, (s)) - -int  nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, -			  struct nouveau_oclass *, int, int, void **); -void _nouveau_gpio_dtor(struct nouveau_object *); -int  nouveau_gpio_init(struct nouveau_gpio *); - -extern struct nouveau_oclass nv10_gpio_oclass; -extern struct nouveau_oclass nv50_gpio_oclass; -extern struct nouveau_oclass nvd0_gpio_oclass; -extern struct nouveau_oclass nve0_gpio_oclass; +extern struct nouveau_oclass *nv10_gpio_oclass; +extern struct nouveau_oclass *nv50_gpio_oclass; +extern struct nouveau_oclass *nv92_gpio_oclass; +extern struct nouveau_oclass *nvd0_gpio_oclass; +extern struct nouveau_oclass *nve0_gpio_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 7e4e2775f24..825f7bb46b6 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -14,61 +14,62 @@  #define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8)  #define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8) +enum nvkm_i2c_event { +	NVKM_I2C_PLUG = 1, +	NVKM_I2C_UNPLUG = 2, +	NVKM_I2C_IRQ = 4, +	NVKM_I2C_DONE = 8, +	NVKM_I2C_ANY = (NVKM_I2C_PLUG | +			NVKM_I2C_UNPLUG | +			NVKM_I2C_IRQ | +			NVKM_I2C_DONE), +}; +  struct nouveau_i2c_port {  	struct nouveau_object base;  	struct i2c_adapter adapter; +	struct mutex mutex;  	struct list_head head;  	u8  index; +	int aux;  	const struct nouveau_i2c_func *func;  };  struct nouveau_i2c_func { -	void (*acquire)(struct nouveau_i2c_port *); -	void (*release)(struct nouveau_i2c_port *); -  	void (*drive_scl)(struct nouveau_i2c_port *, int);  	void (*drive_sda)(struct nouveau_i2c_port *, int);  	int  (*sense_scl)(struct nouveau_i2c_port *);  	int  (*sense_sda)(struct nouveau_i2c_port *); -	int  (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8); +	int  (*aux)(struct nouveau_i2c_port *, bool, u8, u32, u8 *, u8);  	int  (*pattern)(struct nouveau_i2c_port *, int pattern);  	int  (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh);  	int  (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe);  }; -#define nouveau_i2c_port_create(p,e,o,i,a,f,d)                                 \ -	nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f),                 \ -				 sizeof(**d), (void **)d) -#define nouveau_i2c_port_destroy(p) ({                                         \ -	struct nouveau_i2c_port *port = (p);                                   \ -	_nouveau_i2c_port_dtor(nv_object(i2c));                                \ -}) -#define nouveau_i2c_port_init(p)                                               \ -	nouveau_object_init(&(p)->base) -#define nouveau_i2c_port_fini(p,s)                                             \ -	nouveau_object_fini(&(p)->base, (s)) - -int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, -			     struct nouveau_oclass *, u8, -			     const struct i2c_algorithm *, -			     const struct nouveau_i2c_func *, -			     int, void **); -void _nouveau_i2c_port_dtor(struct nouveau_object *); -#define _nouveau_i2c_port_init nouveau_object_init -#define _nouveau_i2c_port_fini nouveau_object_fini +struct nouveau_i2c_board_info { +	struct i2c_board_info dev; +	u8 udelay; /* set to 0 to use the standard delay */ +};  struct nouveau_i2c {  	struct nouveau_subdev base; +	struct nouveau_event *ntfy;  	struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index);  	struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type); +	int  (*acquire_pad)(struct nouveau_i2c_port *, unsigned long timeout); +	void (*release_pad)(struct nouveau_i2c_port *); +	int  (*acquire)(struct nouveau_i2c_port *, unsigned long timeout); +	void (*release)(struct nouveau_i2c_port *);  	int (*identify)(struct nouveau_i2c *, int index, -			const char *what, struct i2c_board_info *, +			const char *what, struct nouveau_i2c_board_info *,  			bool (*match)(struct nouveau_i2c_port *, -				      struct i2c_board_info *)); +				      struct i2c_board_info *, void *), void *); + +	wait_queue_head_t wait;  	struct list_head ports;  }; @@ -78,37 +79,13 @@ nouveau_i2c(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C];  } -#define nouveau_i2c_create(p,e,o,s,d)                                          \ -	nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d) -#define nouveau_i2c_destroy(p) ({                                              \ -	struct nouveau_i2c *i2c = (p);                                         \ -	_nouveau_i2c_dtor(nv_object(i2c));                                     \ -}) -#define nouveau_i2c_init(p) ({                                                 \ -	struct nouveau_i2c *i2c = (p);                                         \ -	_nouveau_i2c_init(nv_object(i2c));                                     \ -}) -#define nouveau_i2c_fini(p,s) ({                                               \ -	struct nouveau_i2c *i2c = (p);                                         \ -	_nouveau_i2c_fini(nv_object(i2c), (s));                                \ -}) - -int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, -			struct nouveau_oclass *, struct nouveau_oclass *, -			int, void **); -void _nouveau_i2c_dtor(struct nouveau_object *); -int  _nouveau_i2c_init(struct nouveau_object *); -int  _nouveau_i2c_fini(struct nouveau_object *, bool); - -extern struct nouveau_oclass nv04_i2c_oclass; -extern struct nouveau_oclass nv4e_i2c_oclass; -extern struct nouveau_oclass nv50_i2c_oclass; -extern struct nouveau_oclass nv94_i2c_oclass; -extern struct nouveau_oclass nvd0_i2c_oclass; -extern struct nouveau_oclass nouveau_anx9805_sclass[]; - -extern const struct i2c_algorithm nouveau_i2c_bit_algo; -extern const struct i2c_algorithm nouveau_i2c_aux_algo; +extern struct nouveau_oclass *nv04_i2c_oclass; +extern struct nouveau_oclass *nv4e_i2c_oclass; +extern struct nouveau_oclass *nv50_i2c_oclass; +extern struct nouveau_oclass *nv94_i2c_oclass; +extern struct nouveau_oclass *nvd0_i2c_oclass; +extern struct nouveau_oclass *gf117_i2c_oclass; +extern struct nouveau_oclass *nve0_i2c_oclass;  static inline int  nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h index 88814f159d8..31df634c0fd 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ibus.h @@ -30,5 +30,6 @@ nouveau_ibus(void *obj)  extern struct nouveau_oclass nvc0_ibus_oclass;  extern struct nouveau_oclass nve0_ibus_oclass; +extern struct nouveau_oclass gk20a_ibus_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h index ec7a54e91a0..c1df26f3230 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/instmem.h @@ -23,21 +23,6 @@ nv_memobj(void *obj)  	return obj;  } -#define nouveau_instobj_create(p,e,o,d)                                        \ -	nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nouveau_instobj_init(p)                                                \ -	nouveau_object_init(&(p)->base) -#define nouveau_instobj_fini(p,s)                                              \ -	nouveau_object_fini(&(p)->base, (s)) - -int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *, -			     struct nouveau_oclass *, int, void **); -void nouveau_instobj_destroy(struct nouveau_instobj *); - -void _nouveau_instobj_dtor(struct nouveau_object *); -#define _nouveau_instobj_init nouveau_object_init -#define _nouveau_instobj_fini nouveau_object_fini -  struct nouveau_instmem {  	struct nouveau_subdev base;  	struct list_head list; @@ -50,24 +35,18 @@ struct nouveau_instmem {  static inline struct nouveau_instmem *  nouveau_instmem(void *obj)  { +	/* nv04/nv40 impls need to create objects in their constructor, +	 * which is before the subdev pointer is valid +	 */ +	if (nv_iclass(obj, NV_SUBDEV_CLASS) && +	    nv_subidx(obj) == NVDEV_SUBDEV_INSTMEM) +		return obj; +  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_INSTMEM];  } -#define nouveau_instmem_create(p,e,o,d)                                        \ -	nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nouveau_instmem_destroy(p)                                             \ -	nouveau_subdev_destroy(&(p)->base) -int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *, -			    struct nouveau_oclass *, int, void **); -int nouveau_instmem_init(struct nouveau_instmem *); -int nouveau_instmem_fini(struct nouveau_instmem *, bool); - -#define _nouveau_instmem_dtor _nouveau_subdev_dtor -int _nouveau_instmem_init(struct nouveau_object *); -int _nouveau_instmem_fini(struct nouveau_object *, bool); - -extern struct nouveau_oclass nv04_instmem_oclass; -extern struct nouveau_oclass nv40_instmem_oclass; -extern struct nouveau_oclass nv50_instmem_oclass; +extern struct nouveau_oclass *nv04_instmem_oclass; +extern struct nouveau_oclass *nv40_instmem_oclass; +extern struct nouveau_oclass *nv50_instmem_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h index a1985ed3d58..c9c1950b774 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h @@ -35,6 +35,7 @@ nouveau_ltcg(void *obj)  #define _nouveau_ltcg_init _nouveau_subdev_init  #define _nouveau_ltcg_fini _nouveau_subdev_fini -extern struct nouveau_oclass nvc0_ltcg_oclass; +extern struct nouveau_oclass *gf100_ltcg_oclass; +extern struct nouveau_oclass *gm107_ltcg_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index ce6569f365a..72b176831be 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h @@ -11,8 +11,8 @@ struct nouveau_mc_intr {  struct nouveau_mc {  	struct nouveau_subdev base; -	const struct nouveau_mc_intr *intr_map;  	bool use_msi; +	unsigned int irq;  };  static inline struct nouveau_mc * @@ -21,8 +21,8 @@ nouveau_mc(void *obj)  	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];  } -#define nouveau_mc_create(p,e,o,m,d)                                           \ -	nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d) +#define nouveau_mc_create(p,e,o,d)                                             \ +	nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)  #define nouveau_mc_destroy(p) ({                                               \  	struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc));        \  }) @@ -34,20 +34,25 @@ nouveau_mc(void *obj)  })  int  nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *, -			struct nouveau_oclass *, const struct nouveau_mc_intr *, -			int, void **); +			struct nouveau_oclass *, int, void **);  void _nouveau_mc_dtor(struct nouveau_object *);  int  _nouveau_mc_init(struct nouveau_object *);  int  _nouveau_mc_fini(struct nouveau_object *, bool); -extern struct nouveau_oclass nv04_mc_oclass; -extern struct nouveau_oclass nv44_mc_oclass; -extern struct nouveau_oclass nv50_mc_oclass; -extern struct nouveau_oclass nv98_mc_oclass; -extern struct nouveau_oclass nvc0_mc_oclass; +struct nouveau_mc_oclass { +	struct nouveau_oclass base; +	const struct nouveau_mc_intr *intr; +	void (*msi_rearm)(struct nouveau_mc *); +}; -extern const struct nouveau_mc_intr nv04_mc_intr[]; -int nv04_mc_init(struct nouveau_object *); -int nv50_mc_init(struct nouveau_object *); +extern struct nouveau_oclass *nv04_mc_oclass; +extern struct nouveau_oclass *nv40_mc_oclass; +extern struct nouveau_oclass *nv44_mc_oclass; +extern struct nouveau_oclass *nv4c_mc_oclass; +extern struct nouveau_oclass *nv50_mc_oclass; +extern struct nouveau_oclass *nv94_mc_oclass; +extern struct nouveau_oclass *nv98_mc_oclass; +extern struct nouveau_oclass *nvc0_mc_oclass; +extern struct nouveau_oclass *nvc3_mc_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h b/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h new file mode 100644 index 00000000000..c5c92cbed33 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/pwr.h @@ -0,0 +1,80 @@ +#ifndef __NOUVEAU_PWR_H__ +#define __NOUVEAU_PWR_H__ + +#include <core/subdev.h> +#include <core/device.h> + +struct nouveau_pwr { +	struct nouveau_subdev base; + +	struct { +		u32 limit; +		u32 *data; +		u32  size; +	} code; + +	struct { +		u32 limit; +		u32 *data; +		u32  size; +	} data; + +	struct { +		u32 base; +		u32 size; +	} send; + +	struct { +		u32 base; +		u32 size; + +		struct work_struct work; +		wait_queue_head_t wait; +		u32 process; +		u32 message; +		u32 data[2]; +	} recv; + +	int (*message)(struct nouveau_pwr *, u32[2], u32, u32, u32, u32); +}; + +static inline struct nouveau_pwr * +nouveau_pwr(void *obj) +{ +	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_PWR]; +} + +#define nouveau_pwr_create(p, e, o, d)                                         \ +	nouveau_pwr_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_pwr_destroy(p)                                                 \ +	nouveau_subdev_destroy(&(p)->base) +#define nouveau_pwr_init(p) ({                                                 \ +	struct nouveau_pwr *ppwr = (p);                                        \ +	_nouveau_pwr_init(nv_object(ppwr));                                    \ +}) +#define nouveau_pwr_fini(p,s) ({                                               \ +	struct nouveau_pwr *ppwr = (p);                                        \ +	_nouveau_pwr_fini(nv_object(ppwr), (s));                               \ +}) + +int nouveau_pwr_create_(struct nouveau_object *, struct nouveau_object *, +			   struct nouveau_oclass *, int, void **); +#define _nouveau_pwr_dtor _nouveau_subdev_dtor +int _nouveau_pwr_init(struct nouveau_object *); +int _nouveau_pwr_fini(struct nouveau_object *, bool); + +extern struct nouveau_oclass nva3_pwr_oclass; +extern struct nouveau_oclass nvc0_pwr_oclass; +extern struct nouveau_oclass nvd0_pwr_oclass; +extern struct nouveau_oclass nv108_pwr_oclass; + +/* interface to MEMX process running on PPWR */ +struct nouveau_memx; +int  nouveau_memx_init(struct nouveau_pwr *, struct nouveau_memx **); +int  nouveau_memx_fini(struct nouveau_memx **, bool exec); +void nouveau_memx_wr32(struct nouveau_memx *, u32 addr, u32 data); +void nouveau_memx_wait(struct nouveau_memx *, +		       u32 addr, u32 mask, u32 data, u32 nsec); +void nouveau_memx_nsec(struct nouveau_memx *, u32 nsec); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h index c075998d82e..d4a68179e58 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h @@ -31,7 +31,7 @@ struct nouveau_therm {  	int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);  	int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *);  	int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); -	int (*pwm_clock)(struct nouveau_therm *); +	int (*pwm_clock)(struct nouveau_therm *, int line);  	int (*fan_get)(struct nouveau_therm *);  	int (*fan_set)(struct nouveau_therm *, int); @@ -71,6 +71,8 @@ void _nouveau_therm_dtor(struct nouveau_object *);  int  _nouveau_therm_init(struct nouveau_object *);  int  _nouveau_therm_fini(struct nouveau_object *, bool); +int  nouveau_therm_cstate(struct nouveau_therm *, int, int); +  extern struct nouveau_oclass nv40_therm_oclass;  extern struct nouveau_oclass nv50_therm_oclass;  extern struct nouveau_oclass nv84_therm_oclass; diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index 9ab70dfe5b0..db9be803a87 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h @@ -59,5 +59,6 @@ int nouveau_timer_create_(struct nouveau_object *, struct nouveau_engine *,  			  struct nouveau_oclass *, int size, void **);  extern struct nouveau_oclass nv04_timer_oclass; +extern struct nouveau_oclass gk20a_timer_oclass;  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h index fcf57fa309b..c9509039f94 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h @@ -131,9 +131,5 @@ void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);  void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);  void nouveau_vm_unmap(struct nouveau_vma *);  void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); -void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, -		       struct nouveau_mem *); -void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, -		     struct nouveau_mem *mem);  #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/volt.h b/drivers/gpu/drm/nouveau/core/include/subdev/volt.h new file mode 100644 index 00000000000..820b62ffd75 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/include/subdev/volt.h @@ -0,0 +1,60 @@ +#ifndef __NOUVEAU_VOLT_H__ +#define __NOUVEAU_VOLT_H__ + +#include <core/subdev.h> +#include <core/device.h> + +struct nouveau_voltage { +	u32 uv; +	u8  id; +}; + +struct nouveau_volt { +	struct nouveau_subdev base; + +	int (*vid_get)(struct nouveau_volt *); +	int (*get)(struct nouveau_volt *); +	int (*vid_set)(struct nouveau_volt *, u8 vid); +	int (*set)(struct nouveau_volt *, u32 uv); +	int (*set_id)(struct nouveau_volt *, u8 id, int condition); + +	u8 vid_mask; +	u8 vid_nr; +	struct { +		u32 uv; +		u8 vid; +	} vid[256]; +}; + +static inline struct nouveau_volt * +nouveau_volt(void *obj) +{ +	return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_VOLT]; +} + +#define nouveau_volt_create(p, e, o, d)                                        \ +	nouveau_volt_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_volt_destroy(p) ({                                             \ +	struct nouveau_volt *v = (p);                                          \ +	_nouveau_volt_dtor(nv_object(v));                                      \ +}) +#define nouveau_volt_init(p) ({                                                \ +	struct nouveau_volt *v = (p);                                          \ +	_nouveau_volt_init(nv_object(v));                                      \ +}) +#define nouveau_volt_fini(p,s)                                                 \ +	nouveau_subdev_fini((p), (s)) + +int  nouveau_volt_create_(struct nouveau_object *, struct nouveau_object *, +			  struct nouveau_oclass *, int, void **); +void _nouveau_volt_dtor(struct nouveau_object *); +int  _nouveau_volt_init(struct nouveau_object *); +#define _nouveau_volt_fini _nouveau_subdev_fini + +extern struct nouveau_oclass nv40_volt_oclass; + +int nouveau_voltgpio_init(struct nouveau_volt *); +int nouveau_voltgpio_get(struct nouveau_volt *); +int nouveau_voltgpio_set(struct nouveau_volt *, u8); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 191e739f30d..d0ced94ca54 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h @@ -5,6 +5,7 @@  #include <linux/slab.h>  #include <linux/mutex.h>  #include <linux/pci.h> +#include <linux/platform_device.h>  #include <linux/printk.h>  #include <linux/bitops.h>  #include <linux/firmware.h> @@ -23,17 +24,6 @@  #include <asm/unaligned.h> -static inline int -ffsll(u64 mask) -{ -	int i; -	for (i = 0; i < 64; i++) { -		if (mask & (1ULL << i)) -			return i + 1; -	} -	return 0; -} -  #ifndef ioread32_native  #ifdef __BIG_ENDIAN  #define ioread16_native ioread16be diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c index d70ba342aa2..73b1ed20c8d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/base.c @@ -23,7 +23,11 @@   */  #include <core/object.h> -#include <subdev/bar.h> + +#include <subdev/fb.h> +#include <subdev/vm.h> + +#include "priv.h"  struct nouveau_barobj {  	struct nouveau_object base; @@ -114,8 +118,10 @@ nouveau_bar_create_(struct nouveau_object *parent,  	if (ret)  		return ret; -	bar->iomem = ioremap(pci_resource_start(device->pdev, 3), -			     pci_resource_len(device->pdev, 3)); +	if (nv_device_resource_len(device, 3) != 0) +		bar->iomem = ioremap(nv_device_resource_start(device, 3), +				     nv_device_resource_len(device, 3)); +  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c index 160d27f3c7b..f748ba49dfc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nv50.c @@ -25,10 +25,11 @@  #include <core/gpuobj.h>  #include <subdev/timer.h> -#include <subdev/bar.h>  #include <subdev/fb.h>  #include <subdev/vm.h> +#include "priv.h" +  struct nv50_bar_priv {  	struct nouveau_bar base;  	spinlock_t lock; @@ -138,7 +139,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	/* BAR3 */  	start = 0x0100000000ULL; -	limit = start + pci_resource_len(device->pdev, 3); +	limit = start + nv_device_resource_len(device, 3);  	ret = nouveau_vm_new(device, start, limit, start, &vm);  	if (ret) @@ -172,7 +173,7 @@ nv50_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	/* BAR1 */  	start = 0x0000000000ULL; -	limit = start + pci_resource_len(device->pdev, 1); +	limit = start + nv_device_resource_len(device, 1);  	ret = nouveau_vm_new(device, start, limit--, start, &vm);  	if (ret) @@ -230,7 +231,7 @@ static int  nv50_bar_init(struct nouveau_object *object)  {  	struct nv50_bar_priv *priv = (void *)object; -	int ret; +	int ret, i;  	ret = nouveau_bar_init(&priv->base);  	if (ret) @@ -248,6 +249,8 @@ nv50_bar_init(struct nouveau_object *object)  	nv_wr32(priv, 0x001704, 0x40000000 | priv->mem->addr >> 12);  	nv_wr32(priv, 0x001708, 0x80000000 | priv->bar1->node->offset >> 4);  	nv_wr32(priv, 0x00170c, 0x80000000 | priv->bar3->node->offset >> 4); +	for (i = 0; i < 8; i++) +		nv_wr32(priv, 0x001900 + (i * 4), 0x00000000);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c index b2ec7411eb2..ca8139b9ab2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c @@ -25,18 +25,21 @@  #include <core/gpuobj.h>  #include <subdev/timer.h> -#include <subdev/bar.h>  #include <subdev/fb.h>  #include <subdev/vm.h> +#include "priv.h" + +struct nvc0_bar_priv_vm { +	struct nouveau_gpuobj *mem; +	struct nouveau_gpuobj *pgd; +	struct nouveau_vm *vm; +}; +  struct nvc0_bar_priv {  	struct nouveau_bar base;  	spinlock_t lock; -	struct { -		struct nouveau_gpuobj *mem; -		struct nouveau_gpuobj *pgd; -		struct nouveau_vm *vm; -	} bar[2]; +	struct nvc0_bar_priv_vm bar[2];  };  static int @@ -78,88 +81,87 @@ nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma)  }  static int -nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) +nvc0_bar_init_vm(struct nvc0_bar_priv *priv, struct nvc0_bar_priv_vm *bar_vm, +		 int bar_nr)  { -	struct nouveau_device *device = nv_device(parent); -	struct pci_dev *pdev = device->pdev; -	struct nvc0_bar_priv *priv; -	struct nouveau_gpuobj *mem; +	struct nouveau_device *device = nv_device(&priv->base);  	struct nouveau_vm *vm; +	resource_size_t bar_len;  	int ret; -	ret = nouveau_bar_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	/* BAR3 */  	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, -				&priv->bar[0].mem); -	mem = priv->bar[0].mem; +				&bar_vm->mem);  	if (ret)  		return ret;  	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, -				&priv->bar[0].pgd); +				&bar_vm->pgd);  	if (ret)  		return ret; -	ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 3), 0, &vm); +	bar_len = nv_device_resource_len(device, bar_nr); + +	ret = nouveau_vm_new(device, 0, bar_len, 0, &vm);  	if (ret)  		return ret;  	atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); -	ret = nouveau_gpuobj_new(nv_object(priv), NULL, -				 (pci_resource_len(pdev, 3) >> 12) * 8, -				 0x1000, NVOBJ_FLAG_ZERO_ALLOC, -				 &vm->pgt[0].obj[0]); -	vm->pgt[0].refcount[0] = 1; -	if (ret) -		return ret; +	/* +	 * Bootstrap page table lookup. +	 */ +	if (bar_nr == 3) { +		ret = nouveau_gpuobj_new(nv_object(priv), NULL, +					 (bar_len >> 12) * 8, 0x1000, +					 NVOBJ_FLAG_ZERO_ALLOC, +					&vm->pgt[0].obj[0]); +		vm->pgt[0].refcount[0] = 1; +		if (ret) +			return ret; +	} -	ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd); +	ret = nouveau_vm_ref(vm, &bar_vm->vm, bar_vm->pgd);  	nouveau_vm_ref(NULL, &vm, NULL);  	if (ret)  		return ret; -	nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); -	nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); -	nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 3) - 1)); -	nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 3) - 1)); +	nv_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr)); +	nv_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr)); +	nv_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1)); +	nv_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1)); -	/* BAR1 */ -	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, -				&priv->bar[1].mem); -	mem = priv->bar[1].mem; -	if (ret) -		return ret; +	return 0; +} -	ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, -				&priv->bar[1].pgd); -	if (ret) -		return ret; +static int +nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 size, +	      struct nouveau_object **pobject) +{ +	struct nouveau_device *device = nv_device(parent); +	struct nvc0_bar_priv *priv; +	bool has_bar3 = nv_device_resource_len(device, 3) != 0; +	int ret; -	ret = nouveau_vm_new(device, 0, pci_resource_len(pdev, 1), 0, &vm); +	ret = nouveau_bar_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv);  	if (ret)  		return ret; -	atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); +	/* BAR3 */ +	if (has_bar3) { +		ret = nvc0_bar_init_vm(priv, &priv->bar[0], 3); +		if (ret) +			return ret; +		priv->base.alloc = nouveau_bar_alloc; +		priv->base.kmap = nvc0_bar_kmap; +	} -	ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd); -	nouveau_vm_ref(NULL, &vm, NULL); +	/* BAR1 */ +	ret = nvc0_bar_init_vm(priv, &priv->bar[1], 1);  	if (ret)  		return ret; -	nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); -	nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); -	nv_wo32(mem, 0x0208, lower_32_bits(pci_resource_len(pdev, 1) - 1)); -	nv_wo32(mem, 0x020c, upper_32_bits(pci_resource_len(pdev, 1) - 1)); - -	priv->base.alloc = nouveau_bar_alloc; -	priv->base.kmap = nvc0_bar_kmap;  	priv->base.umap = nvc0_bar_umap;  	priv->base.unmap = nvc0_bar_unmap;  	priv->base.flush = nv84_bar_flush; @@ -201,7 +203,9 @@ nvc0_bar_init(struct nouveau_object *object)  	nv_mask(priv, 0x100c80, 0x00000001, 0x00000000);  	nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); -	nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12); +	if (priv->bar[0].mem) +		nv_wr32(priv, 0x001714, +			0xc0000000 | priv->bar[0].mem->addr >> 12);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h new file mode 100644 index 00000000000..ffad8f337ea --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/priv.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_BAR_PRIV_H__ +#define __NVKM_BAR_PRIV_H__ + +#include <subdev/bar.h> + +#define nouveau_bar_create(p,e,o,d)                                            \ +	nouveau_bar_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_bar_init(p)                                                    \ +	nouveau_subdev_init(&(p)->base) +#define nouveau_bar_fini(p,s)                                                  \ +	nouveau_subdev_fini(&(p)->base, (s)) + +int nouveau_bar_create_(struct nouveau_object *, struct nouveau_object *, +			struct nouveau_oclass *, int, void **); +void nouveau_bar_destroy(struct nouveau_bar *); + +void _nouveau_bar_dtor(struct nouveau_object *); +#define _nouveau_bar_init _nouveau_subdev_init +#define _nouveau_bar_fini _nouveau_subdev_fini + +int  nouveau_bar_alloc(struct nouveau_bar *, struct nouveau_object *, +		       struct nouveau_mem *, struct nouveau_object **); + +void nv84_bar_flush(struct nouveau_bar *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c b/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c new file mode 100644 index 00000000000..199f4e5f748 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/P0260.c @@ -0,0 +1,109 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> +#include <subdev/bios/P0260.h> + +u32 +nvbios_P0260Te(struct nouveau_bios *bios, +	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz) +{ +	struct bit_entry bit_P; +	u32 data = 0x00000000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 2 && bit_P.length > 0x63) +			data = nv_ro32(bios, bit_P.offset + 0x60); +		if (data) { +			*ver = nv_ro08(bios, data + 0); +			switch (*ver) { +			case 0x10: +				*hdr = nv_ro08(bios, data + 1); +				*cnt = nv_ro08(bios, data + 2); +				*len = 4; +				*xnr = nv_ro08(bios, data + 3); +				*xsz = 4; +				return data; +			default: +				break; +			} +		} +	} + +	return 0x00000000; +} + +u32 +nvbios_P0260Ee(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) +{ +	u8  hdr, cnt, xnr, xsz; +	u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, len, &xnr, &xsz); +	if (data && idx < cnt) +		return data + hdr + (idx * *len); +	return 0x00000000; +} + +u32 +nvbios_P0260Ep(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len, +	       struct nvbios_P0260E *info) +{ +	u32 data = nvbios_P0260Ee(bios, idx, ver, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!data * *ver) { +	case 0x10: +		info->data = nv_ro32(bios, data); +		return data; +	default: +		break; +	} +	return 0x00000000; +} + +u32 +nvbios_P0260Xe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *xsz) +{ +	u8  hdr, cnt, len, xnr; +	u32 data = nvbios_P0260Te(bios, ver, &hdr, &cnt, &len, &xnr, xsz); +	if (data && idx < xnr) +		return data + hdr + (cnt * len) + (idx * *xsz); +	return 0x00000000; +} + +u32 +nvbios_P0260Xp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr, +	       struct nvbios_P0260X *info) +{ +	u32 data = nvbios_P0260Xe(bios, idx, ver, hdr); +	memset(info, 0x00, sizeof(*info)); +	switch (!!data * *ver) { +	case 0x10: +		info->data = nv_ro32(bios, data); +		return data; +	default: +		break; +	} +	return 0x00000000; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index aa0fbbec7f0..d45704a2c2d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -90,10 +90,26 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)  	int i;  	if (device->card_type >= NV_50) { -		if (  device->card_type < NV_C0 || -		    !(nv_rd32(bios, 0x022500) & 0x00000001)) -			addr = (u64)(nv_rd32(bios, 0x619f04) & 0xffffff00) << 8; +		if (device->card_type >= NV_C0 && device->card_type < GM100) { +			if (nv_rd32(bios, 0x022500) & 0x00000001) +				return; +		} else +		if (device->card_type >= GM100) { +			if (nv_rd32(bios, 0x021c04) & 0x00000001) +				return; +		} + +		addr = nv_rd32(bios, 0x619f04); +		if (!(addr & 0x00000008)) { +			nv_debug(bios, "... not enabled\n"); +			return; +		} +		if ( (addr & 0x00000003) != 1) { +			nv_debug(bios, "... not in vram\n"); +			return; +		} +		addr = (addr & 0xffffff00) << 8;  		if (!addr) {  			addr  = (u64)nv_rd32(bios, 0x001700) << 16;  			addr += 0xf0000; @@ -130,6 +146,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)  	u16 pcir;  	int i; +	/* there is no prom on nv4x IGP's */ +	if (device->card_type == NV_40 && device->chipset >= 0x4c) +		return; +  	/* enable access to rom */  	if (device->card_type >= NV_50)  		pcireg = 0x088050; @@ -137,6 +157,10 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)  		pcireg = 0x001850;  	access = nv_mask(bios, pcireg, 0x00000001, 0x00000000); +	/* WARNING: PROM accesses should always be 32-bits aligned. Other +	 * accesses work on most chipset but do not on Kepler chipsets +	 */ +  	/* bail if no rom signature, with a workaround for a PROM reading  	 * issue on some chipsets.  the first read after a period of  	 * inactivity returns the wrong result, so retry the first header @@ -144,31 +168,35 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)  	 */  	i = 16;  	do { -		if (nv_rd08(bios, 0x300000) == 0x55) +		u32 data = le32_to_cpu(nv_rd32(bios, 0x300000)) & 0xffff; +		if (data == 0xaa55)  			break;  	} while (i--); -	if (!i || nv_rd08(bios, 0x300001) != 0xaa) -		goto out; - -	/* additional check (see note below) - read PCI record header */ -	pcir = nv_rd08(bios, 0x300018) | -	       nv_rd08(bios, 0x300019) << 8; -	if (nv_rd08(bios, 0x300000 + pcir) != 'P' || -	    nv_rd08(bios, 0x300001 + pcir) != 'C' || -	    nv_rd08(bios, 0x300002 + pcir) != 'I' || -	    nv_rd08(bios, 0x300003 + pcir) != 'R') +	if (!i)  		goto out;  	/* read entire bios image to system memory */ -	bios->size = nv_rd08(bios, 0x300002) * 512; +	bios->size = (le32_to_cpu(nv_rd32(bios, 0x300000)) >> 16) & 0xff; +	bios->size = bios->size * 512;  	if (!bios->size)  		goto out;  	bios->data = kmalloc(bios->size, GFP_KERNEL); -	if (bios->data) { -		for (i = 0; i < bios->size; i++) -			nv_wo08(bios, i, nv_rd08(bios, 0x300000 + i)); +	if (!bios->data) +		goto out; + +	for (i = 0; i < bios->size; i += 4) +		((u32 *)bios->data)[i/4] = nv_rd32(bios, 0x300000 + i); + +	/* check the PCI record header */ +	pcir = nv_ro16(bios, 0x0018); +	if (bios->data[pcir + 0] != 'P' || +	    bios->data[pcir + 1] != 'C' || +	    bios->data[pcir + 2] != 'I' || +	    bios->data[pcir + 3] != 'R') { +		bios->size = 0; +		kfree(bios->data);  	}  out: diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/boost.c b/drivers/gpu/drm/nouveau/core/subdev/bios/boost.c new file mode 100644 index 00000000000..c1835e591c4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/boost.c @@ -0,0 +1,127 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/boost.h> + +u16 +nvbios_boostTe(struct nouveau_bios *bios, +	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz) +{ +	struct bit_entry bit_P; +	u16 boost = 0x0000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 2) +			boost = nv_ro16(bios, bit_P.offset + 0x30); + +		if (boost) { +			*ver = nv_ro08(bios, boost + 0); +			switch (*ver) { +			case 0x11: +				*hdr = nv_ro08(bios, boost + 1); +				*cnt = nv_ro08(bios, boost + 5); +				*len = nv_ro08(bios, boost + 2); +				*snr = nv_ro08(bios, boost + 4); +				*ssz = nv_ro08(bios, boost + 3); +				return boost; +			default: +				break; +			} +		} +	} + +	return 0x0000; +} + +u16 +nvbios_boostEe(struct nouveau_bios *bios, int idx, +	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	u8  snr, ssz; +	u16 data = nvbios_boostTe(bios, ver, hdr, cnt, len, &snr, &ssz); +	if (data && idx < *cnt) { +		data = data + *hdr + (idx * (*len + (snr * ssz))); +		*hdr = *len; +		*cnt = snr; +		*len = ssz; +		return data; +	} +	return 0x0000; +} + +u16 +nvbios_boostEp(struct nouveau_bios *bios, int idx, +	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info) +{ +	u16 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	if (data) { +		info->pstate = (nv_ro16(bios, data + 0x00) & 0x01e0) >> 5; +		info->min    =  nv_ro16(bios, data + 0x02) * 1000; +		info->max    =  nv_ro16(bios, data + 0x04) * 1000; +	} +	return data; +} + +u16 +nvbios_boostEm(struct nouveau_bios *bios, u8 pstate, +	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info) +{ +	u32 data, idx = 0; +	while ((data = nvbios_boostEp(bios, idx++, ver, hdr, cnt, len, info))) { +		if (info->pstate == pstate) +			break; +	} +	return data; +} + +u16 +nvbios_boostSe(struct nouveau_bios *bios, int idx, +	       u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len) +{ +	if (data && idx < cnt) { +		data = data + *hdr + (idx * len); +		*hdr = len; +		return data; +	} +	return 0x0000; +} + +u16 +nvbios_boostSp(struct nouveau_bios *bios, int idx, +	       u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len, +	       struct nvbios_boostS *info) +{ +	data = nvbios_boostSe(bios, idx, data, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	if (data) { +		info->domain  = nv_ro08(bios, data + 0x00); +		info->percent = nv_ro08(bios, data + 0x01); +		info->min     = nv_ro16(bios, data + 0x02) * 1000; +		info->max     = nv_ro16(bios, data + 0x04) * 1000; +	} +	return data; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c index 5ac010efd95..2ede3bcd96a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/conn.c @@ -28,12 +28,12 @@  #include <subdev/bios/dcb.h>  #include <subdev/bios/conn.h> -u16 -dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +u32 +nvbios_connTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)  { -	u16 dcb = dcb_table(bios, ver, hdr, cnt, len); +	u32 dcb = dcb_table(bios, ver, hdr, cnt, len);  	if (dcb && *ver >= 0x30 && *hdr >= 0x16) { -		u16 data = nv_ro16(bios, dcb + 0x14); +		u32 data = nv_ro16(bios, dcb + 0x14);  		if (data) {  			*ver = nv_ro08(bios, data + 0);  			*hdr = nv_ro08(bios, data + 1); @@ -42,15 +42,59 @@ dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)  			return data;  		}  	} -	return 0x0000; +	return 0x00000000;  } -u16 -dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) +u32 +nvbios_connTp(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +	      struct nvbios_connT *info) +{ +	u32 data = nvbios_connTe(bios, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!data * *ver) { +	case 0x30: +	case 0x40: +		return data; +	default: +		break; +	} +	return 0x00000000; +} + +u32 +nvbios_connEe(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len)  {  	u8  hdr, cnt; -	u16 data = dcb_conntab(bios, ver, &hdr, &cnt, len); +	u32 data = nvbios_connTe(bios, ver, &hdr, &cnt, len);  	if (data && idx < cnt)  		return data + hdr + (idx * *len); -	return 0x0000; +	return 0x00000000; +} + +u32 +nvbios_connEp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, +	      struct nvbios_connE *info) +{ +	u32 data = nvbios_connEe(bios, idx, ver, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!data * *ver) { +	case 0x30: +	case 0x40: +		info->type     =  nv_ro08(bios, data + 0x00); +		info->location =  nv_ro08(bios, data + 0x01) & 0x0f; +		info->hpd      = (nv_ro08(bios, data + 0x01) & 0x30) >> 4; +		info->dp       = (nv_ro08(bios, data + 0x01) & 0xc0) >> 6; +		if (*len < 4) +			return data; +		info->hpd     |= (nv_ro08(bios, data + 0x02) & 0x03) << 2; +		info->dp      |=  nv_ro08(bios, data + 0x02) & 0x0c; +		info->di       = (nv_ro08(bios, data + 0x02) & 0xf0) >> 4; +		info->hpd     |= (nv_ro08(bios, data + 0x03) & 0x07) << 4; +		info->sr       = (nv_ro08(bios, data + 0x03) & 0x08) >> 3; +		info->lcdid    = (nv_ro08(bios, data + 0x03) & 0x70) >> 4; +		return data; +	default: +		break; +	} +	return 0x00000000;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c b/drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c new file mode 100644 index 00000000000..d3b15327fbf --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/cstep.c @@ -0,0 +1,123 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/cstep.h> + +u16 +nvbios_cstepTe(struct nouveau_bios *bios, +	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz) +{ +	struct bit_entry bit_P; +	u16 cstep = 0x0000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 2) +			cstep = nv_ro16(bios, bit_P.offset + 0x34); + +		if (cstep) { +			*ver = nv_ro08(bios, cstep + 0); +			switch (*ver) { +			case 0x10: +				*hdr = nv_ro08(bios, cstep + 1); +				*cnt = nv_ro08(bios, cstep + 3); +				*len = nv_ro08(bios, cstep + 2); +				*xnr = nv_ro08(bios, cstep + 5); +				*xsz = nv_ro08(bios, cstep + 4); +				return cstep; +			default: +				break; +			} +		} +	} + +	return 0x0000; +} + +u16 +nvbios_cstepEe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr) +{ +	u8  cnt, len, xnr, xsz; +	u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz); +	if (data && idx < cnt) { +		data = data + *hdr + (idx * len); +		*hdr = len; +		return data; +	} +	return 0x0000; +} + +u16 +nvbios_cstepEp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr, +	       struct nvbios_cstepE *info) +{ +	u16 data = nvbios_cstepEe(bios, idx, ver, hdr); +	memset(info, 0x00, sizeof(*info)); +	if (data) { +		info->pstate = (nv_ro16(bios, data + 0x00) & 0x01e0) >> 5; +		info->index   = nv_ro08(bios, data + 0x03); +	} +	return data; +} + +u16 +nvbios_cstepEm(struct nouveau_bios *bios, u8 pstate, u8 *ver, u8 *hdr, +	       struct nvbios_cstepE *info) +{ +	u32 data, idx = 0; +	while ((data = nvbios_cstepEp(bios, idx++, ver, hdr, info))) { +		if (info->pstate == pstate) +			break; +	} +	return data; +} + +u16 +nvbios_cstepXe(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr) +{ +	u8  cnt, len, xnr, xsz; +	u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz); +	if (data && idx < xnr) { +		data = data + *hdr + (cnt * len) + (idx * xsz); +		*hdr = xsz; +		return data; +	} +	return 0x0000; +} + +u16 +nvbios_cstepXp(struct nouveau_bios *bios, int idx, u8 *ver, u8 *hdr, +	       struct nvbios_cstepX *info) +{ +	u16 data = nvbios_cstepXe(bios, idx, ver, hdr); +	memset(info, 0x00, sizeof(*info)); +	if (data) { +		info->freq    = nv_ro16(bios, data + 0x00) * 1000; +		info->unkn[0] = nv_ro08(bios, data + 0x02); +		info->unkn[1] = nv_ro08(bios, data + 0x03); +		info->voltage = nv_ro08(bios, data + 0x04); +	} +	return data; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 2d9b9d7a799..88606bfaf84 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -142,9 +142,36 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len,  		if (*ver >= 0x40) {  			u32 conf = nv_ro32(bios, dcb + 0x04);  			switch (outp->type) { +			case DCB_OUTPUT_DP: +				switch (conf & 0x00e00000) { +				case 0x00000000: +					outp->dpconf.link_bw = 0x06; +					break; +				case 0x00200000: +					outp->dpconf.link_bw = 0x0a; +					break; +				case 0x00400000: +				default: +					outp->dpconf.link_bw = 0x14; +					break; +				} + +				switch (conf & 0x0f000000) { +				case 0x0f000000: +					outp->dpconf.link_nr = 4; +					break; +				case 0x03000000: +					outp->dpconf.link_nr = 2; +					break; +				case 0x01000000: +				default: +					outp->dpconf.link_nr = 1; +					break; +				} + +				/* fall-through... */  			case DCB_OUTPUT_TMDS:  			case DCB_OUTPUT_LVDS: -			case DCB_OUTPUT_DP:  				outp->link = (conf & 0x00000030) >> 4;  				outp->sorconf.link = outp->link; /*XXX*/  				outp->extdev = 0x00; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c index 663853bcca8..f309dd65725 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dp.c @@ -89,6 +89,7 @@ nvbios_dpout_parse(struct nouveau_bios *bios, u8 idx,  		   struct nvbios_dpout *info)  {  	u16 data = nvbios_dpout_entry(bios, idx, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info));  	if (data && *ver) {  		info->type = nv_ro16(bios, data + 0x00);  		info->mask = nv_ro16(bios, data + 0x02); @@ -99,9 +100,12 @@ nvbios_dpout_parse(struct nouveau_bios *bios, u8 idx,  			info->script[0] = nv_ro16(bios, data + 0x06);  			info->script[1] = nv_ro16(bios, data + 0x08);  			info->lnkcmp    = nv_ro16(bios, data + 0x0a); -			info->script[2] = nv_ro16(bios, data + 0x0c); -			info->script[3] = nv_ro16(bios, data + 0x0e); -			info->script[4] = nv_ro16(bios, data + 0x10); +			if (*len >= 0x0f) { +				info->script[2] = nv_ro16(bios, data + 0x0c); +				info->script[3] = nv_ro16(bios, data + 0x0e); +			} +			if (*len >= 0x11) +				info->script[4] = nv_ro16(bios, data + 0x10);  			break;  		case 0x40:  			info->flags     = nv_ro08(bios, data + 0x04); @@ -158,18 +162,20 @@ nvbios_dpcfg_parse(struct nouveau_bios *bios, u16 outp, u8 idx,  		   struct nvbios_dpcfg *info)  {  	u16 data = nvbios_dpcfg_entry(bios, outp, idx, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info));  	if (data) {  		switch (*ver) {  		case 0x21: -			info->drv = nv_ro08(bios, data + 0x02); -			info->pre = nv_ro08(bios, data + 0x03); -			info->unk = nv_ro08(bios, data + 0x04); +			info->dc    = nv_ro08(bios, data + 0x02); +			info->pe    = nv_ro08(bios, data + 0x03); +			info->tx_pu = nv_ro08(bios, data + 0x04);  			break;  		case 0x30:  		case 0x40: -			info->drv = nv_ro08(bios, data + 0x01); -			info->pre = nv_ro08(bios, data + 0x02); -			info->unk = nv_ro08(bios, data + 0x03); +			info->pc    = nv_ro08(bios, data + 0x00); +			info->dc    = nv_ro08(bios, data + 0x01); +			info->pe    = nv_ro08(bios, data + 0x02); +			info->tx_pu = nv_ro08(bios, data + 0x03);  			break;  		default:  			data = 0x0000; @@ -180,7 +186,7 @@ nvbios_dpcfg_parse(struct nouveau_bios *bios, u16 outp, u8 idx,  }  u16 -nvbios_dpcfg_match(struct nouveau_bios *bios, u16 outp, u8 un, u8 vs, u8 pe, +nvbios_dpcfg_match(struct nouveau_bios *bios, u16 outp, u8 pc, u8 vs, u8 pe,  		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len,  		   struct nvbios_dpcfg *info)  { @@ -189,16 +195,15 @@ nvbios_dpcfg_match(struct nouveau_bios *bios, u16 outp, u8 un, u8 vs, u8 pe,  	if (*ver >= 0x30) {  		const u8 vsoff[] = { 0, 4, 7, 9 }; -		idx = (un * 10) + vsoff[vs] + pe; +		idx = (pc * 10) + vsoff[vs] + pe;  	} else { -		while ((data = nvbios_dpcfg_entry(bios, outp, idx, +		while ((data = nvbios_dpcfg_entry(bios, outp, ++idx,  						  ver, hdr, cnt, len))) {  			if (nv_ro08(bios, data + 0x00) == vs &&  			    nv_ro08(bios, data + 0x01) == pe)  				break; -			idx++;  		}  	} -	return nvbios_dpcfg_parse(bios, outp, pe, ver, hdr, cnt, len, info); +	return nvbios_dpcfg_parse(bios, outp, idx, ver, hdr, cnt, len, info);  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2e11ea02cf8..626380f9e4c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -9,6 +9,7 @@  #include <subdev/bios/dp.h>  #include <subdev/bios/gpio.h>  #include <subdev/bios/init.h> +#include <subdev/bios/ramcfg.h>  #include <subdev/devinit.h>  #include <subdev/i2c.h>  #include <subdev/vga.h> @@ -97,15 +98,16 @@ static u8  init_conn(struct nvbios_init *init)  {  	struct nouveau_bios *bios = init->bios; -	u8  ver, len; -	u16 conn; +	struct nvbios_connE connE; +	u8  ver, hdr; +	u32 conn;  	if (init_exec(init)) {  		if (init->outp) {  			conn = init->outp->connector; -			conn = dcb_conn(bios, conn, &ver, &len); +			conn = nvbios_connEp(bios, conn, &ver, &hdr, &connE);  			if (conn) -				return nv_ro08(bios, conn); +				return connE.type;  		}  		error("script needs connector type\n"); @@ -117,6 +119,8 @@ init_conn(struct nvbios_init *init)  static inline u32  init_nvreg(struct nvbios_init *init, u32 reg)  { +	struct nouveau_devinit *devinit = nouveau_devinit(init->bios); +  	/* C51 (at least) sometimes has the lower bits set which the VBIOS  	 * interprets to mean that access needs to go through certain IO  	 * ports instead.  The NVIDIA binary driver has been seen to access @@ -146,6 +150,9 @@ init_nvreg(struct nvbios_init *init, u32 reg)  	if (reg & ~0x00fffffc)  		warn("unknown bits in register 0x%08x\n", reg); + +	if (devinit->mmio) +		reg = devinit->mmio(devinit, reg);  	return reg;  } @@ -153,7 +160,7 @@ static u32  init_rd32(struct nvbios_init *init, u32 reg)  {  	reg = init_nvreg(init, reg); -	if (init_exec(init)) +	if (reg != ~0 && init_exec(init))  		return nv_rd32(init->subdev, reg);  	return 0x00000000;  } @@ -162,7 +169,7 @@ static void  init_wr32(struct nvbios_init *init, u32 reg, u32 val)  {  	reg = init_nvreg(init, reg); -	if (init_exec(init)) +	if (reg != ~0 && init_exec(init))  		nv_wr32(init->subdev, reg, val);  } @@ -170,7 +177,7 @@ static u32  init_mask(struct nvbios_init *init, u32 reg, u32 mask, u32 val)  {  	reg = init_nvreg(init, reg); -	if (init_exec(init)) { +	if (reg != ~0 && init_exec(init)) {  		u32 tmp = nv_rd32(init->subdev, reg);  		nv_wr32(init->subdev, reg, (tmp & ~mask) | val);  		return tmp; @@ -365,13 +372,13 @@ static u16  init_script(struct nouveau_bios *bios, int index)  {  	struct nvbios_init init = { .bios = bios }; -	u16 data; +	u16 bmp_ver = bmp_version(bios), data; -	if (bmp_version(bios) && bmp_version(bios) < 0x0510) { -		if (index > 1) +	if (bmp_ver && bmp_ver < 0x0510) { +		if (index > 1 || bmp_ver < 0x0100)  			return 0x0000; -		data = bios->bmp_offset + (bios->version.major < 2 ? 14 : 18); +		data = bios->bmp_offset + (bmp_ver < 0x0200 ? 14 : 18);  		return nv_ro16(bios, data + (index * 2));  	} @@ -391,43 +398,14 @@ init_unknown_script(struct nouveau_bios *bios)  	return 0x0000;  } -static u16 -init_ram_restrict_table(struct nvbios_init *init) -{ -	struct nouveau_bios *bios = init->bios; -	struct bit_entry bit_M; -	u16 data = 0x0000; - -	if (!bit_entry(bios, 'M', &bit_M)) { -		if (bit_M.version == 1 && bit_M.length >= 5) -			data = nv_ro16(bios, bit_M.offset + 3); -		if (bit_M.version == 2 && bit_M.length >= 3) -			data = nv_ro16(bios, bit_M.offset + 1); -	} - -	if (data == 0x0000) -		warn("ram restrict table not found\n"); -	return data; -} -  static u8  init_ram_restrict_group_count(struct nvbios_init *init)  { -	struct nouveau_bios *bios = init->bios; -	struct bit_entry bit_M; - -	if (!bit_entry(bios, 'M', &bit_M)) { -		if (bit_M.version == 1 && bit_M.length >= 5) -			return nv_ro08(bios, bit_M.offset + 2); -		if (bit_M.version == 2 && bit_M.length >= 3) -			return nv_ro08(bios, bit_M.offset + 0); -	} - -	return 0x00; +	return nvbios_ramcfg_count(init->bios);  }  static u8 -init_ram_restrict_strap(struct nvbios_init *init) +init_ram_restrict(struct nvbios_init *init)  {  	/* This appears to be the behaviour of the VBIOS parser, and *is*  	 * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to @@ -438,18 +416,8 @@ init_ram_restrict_strap(struct nvbios_init *init)  	 * in case *not* re-reading the strap causes similar breakage.  	 */  	if (!init->ramcfg || init->bios->version.major < 0x70) -		init->ramcfg = init_rd32(init, 0x101000); -	return (init->ramcfg & 0x00000003c) >> 2; -} - -static u8 -init_ram_restrict(struct nvbios_init *init) -{ -	u8  strap = init_ram_restrict_strap(init); -	u16 table = init_ram_restrict_table(init); -	if (table) -		return nv_ro08(init->bios, table + strap); -	return 0x00; +		init->ramcfg = 0x80000000 | nvbios_ramcfg_index(init->subdev); +	return (init->ramcfg & 0x7fffffff);  }  static u8 @@ -579,8 +547,22 @@ static void  init_reserved(struct nvbios_init *init)  {  	u8 opcode = nv_ro08(init->bios, init->offset); -	trace("RESERVED\t0x%02x\n", opcode); -	init->offset += 1; +	u8 length, i; + +	switch (opcode) { +	case 0xaa: +		length = 4; +		break; +	default: +		length = 1; +		break; +	} + +	trace("RESERVED 0x%02x\t", opcode); +	for (i = 1; i < length; i++) +		cont(" 0x%02x", nv_ro08(init->bios, init->offset + i)); +	cont("\n"); +	init->offset += length;  }  /** @@ -869,9 +851,8 @@ init_idx_addr_latched(struct nvbios_init *init)  	u32 data = nv_ro32(bios, init->offset + 13);  	u8 count = nv_ro08(bios, init->offset + 17); -	trace("INDEX_ADDRESS_LATCHED\t" -	      "R[0x%06x] : R[0x%06x]\n\tCTRL &= 0x%08x |= 0x%08x\n", -	      creg, dreg, mask, data); +	trace("INDEX_ADDRESS_LATCHED\tR[0x%06x] : R[0x%06x]\n", creg, dreg); +	trace("\tCTRL &= 0x%08x |= 0x%08x\n", mask, data);  	init->offset += 18;  	while (count--) { @@ -1280,7 +1261,11 @@ init_jump(struct nvbios_init *init)  	u16 offset = nv_ro16(bios, init->offset + 1);  	trace("JUMP\t0x%04x\n", offset); -	init->offset = offset; + +	if (init_exec(init)) +		init->offset = offset; +	else +		init->offset += 3;  }  /** @@ -1437,7 +1422,7 @@ init_configure_mem(struct nvbios_init *init)  	data = init_rdvgai(init, 0x03c4, 0x01);  	init_wrvgai(init, 0x03c4, 0x01, data | 0x20); -	while ((addr = nv_ro32(bios, sdata)) != 0xffffffff) { +	for (; (addr = nv_ro32(bios, sdata)) != 0xffffffff; sdata += 4) {  		switch (addr) {  		case 0x10021c: /* CKE_NORMAL */  		case 0x1002d0: /* CMD_REFRESH */ @@ -2135,6 +2120,7 @@ static struct nvbios_init_opcode {  	[0x99] = { init_zm_auxch },  	[0x9a] = { init_i2c_long_if },  	[0xa9] = { init_gpio_ne }, +	[0xaa] = { init_reserved },  };  #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) @@ -2165,7 +2151,7 @@ nvbios_init(struct nouveau_subdev *subdev, bool execute)  	u16 data;  	if (execute) -		nv_suspend(bios, "running init tables\n"); +		nv_info(bios, "running init tables\n");  	while (!ret && (data = (init_script(bios, ++i)))) {  		struct nvbios_init init = {  			.subdev = subdev, @@ -2195,5 +2181,5 @@ nvbios_init(struct nouveau_subdev *subdev, bool execute)  		ret = nvbios_exec(&init);  	} -	return 0; +	return ret;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c b/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c index bcbb056c288..675e221680a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/perf.c @@ -26,8 +26,9 @@  #include <subdev/bios/bit.h>  #include <subdev/bios/perf.h> -static u16 -perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +u16 +nvbios_perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, +		  u8 *cnt, u8 *len, u8 *snr, u8 *ssz)  {  	struct bit_entry bit_P;  	u16 perf = 0x0000; @@ -38,10 +39,22 @@ perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)  			if (perf) {  				*ver = nv_ro08(bios, perf + 0);  				*hdr = nv_ro08(bios, perf + 1); +				if (*ver >= 0x40 && *ver < 0x41) { +					*cnt = nv_ro08(bios, perf + 5); +					*len = nv_ro08(bios, perf + 2); +					*snr = nv_ro08(bios, perf + 4); +					*ssz = nv_ro08(bios, perf + 3); +					return perf; +				} else +				if (*ver >= 0x20 && *ver < 0x40) { +					*cnt = nv_ro08(bios, perf + 2); +					*len = nv_ro08(bios, perf + 3); +					*snr = nv_ro08(bios, perf + 4); +					*ssz = nv_ro08(bios, perf + 5); +					return perf; +				}  			} -		} else -			nv_error(bios, "unknown offset for perf in BIT P %d\n", -				bit_P.version); +		}  	}  	if (bios->bmp_offset) { @@ -50,19 +63,132 @@ perf_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)  			if (perf) {  				*hdr = nv_ro08(bios, perf + 0);  				*ver = nv_ro08(bios, perf + 1); +				*cnt = nv_ro08(bios, perf + 2); +				*len = nv_ro08(bios, perf + 3); +				*snr = 0; +				*ssz = 0; +				return perf;  			}  		}  	} +	return 0x0000; +} + +u16 +nvbios_perf_entry(struct nouveau_bios *bios, int idx, +		  u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	u8  snr, ssz; +	u16 perf = nvbios_perf_table(bios, ver, hdr, cnt, len, &snr, &ssz); +	if (perf && idx < *cnt) { +		perf = perf + *hdr + (idx * (*len + (snr * ssz))); +		*hdr = *len; +		*cnt = snr; +		*len = ssz; +		return perf; +	} +	return 0x0000; +} + +u16 +nvbios_perfEp(struct nouveau_bios *bios, int idx, +	      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +	      struct nvbios_perfE *info) +{ +	u16 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	info->pstate = nv_ro08(bios, perf + 0x00); +	switch (!!perf * *ver) { +	case 0x12: +	case 0x13: +	case 0x14: +		info->core     = nv_ro32(bios, perf + 0x01) * 10; +		info->memory   = nv_ro32(bios, perf + 0x05) * 20; +		info->fanspeed = nv_ro08(bios, perf + 0x37); +		if (*hdr > 0x38) +			info->voltage = nv_ro08(bios, perf + 0x38); +		break; +	case 0x21: +	case 0x23: +	case 0x24: +		info->fanspeed = nv_ro08(bios, perf + 0x04); +		info->voltage  = nv_ro08(bios, perf + 0x05); +		info->shader   = nv_ro16(bios, perf + 0x06) * 1000; +		info->core     = info->shader + (signed char) +				 nv_ro08(bios, perf + 0x08) * 1000; +		switch (nv_device(bios)->chipset) { +		case 0x49: +		case 0x4b: +			info->memory = nv_ro16(bios, perf + 0x0b) * 1000; +			break; +		default: +			info->memory = nv_ro16(bios, perf + 0x0b) * 2000; +			break; +		} +		break; +	case 0x25: +		info->fanspeed = nv_ro08(bios, perf + 0x04); +		info->voltage  = nv_ro08(bios, perf + 0x05); +		info->core     = nv_ro16(bios, perf + 0x06) * 1000; +		info->shader   = nv_ro16(bios, perf + 0x0a) * 1000; +		info->memory   = nv_ro16(bios, perf + 0x0c) * 1000; +		break; +	case 0x30: +		info->script   = nv_ro16(bios, perf + 0x02); +	case 0x35: +		info->fanspeed = nv_ro08(bios, perf + 0x06); +		info->voltage  = nv_ro08(bios, perf + 0x07); +		info->core     = nv_ro16(bios, perf + 0x08) * 1000; +		info->shader   = nv_ro16(bios, perf + 0x0a) * 1000; +		info->memory   = nv_ro16(bios, perf + 0x0c) * 1000; +		info->vdec     = nv_ro16(bios, perf + 0x10) * 1000; +		info->disp     = nv_ro16(bios, perf + 0x14) * 1000; +		break; +	case 0x40: +		info->voltage  = nv_ro08(bios, perf + 0x02); +		break; +	default: +		return 0x0000; +	}  	return perf;  } +u32 +nvbios_perfSe(struct nouveau_bios *bios, u32 perfE, int idx, +	      u8 *ver, u8 *hdr, u8 cnt, u8 len) +{ +	u32 data = 0x00000000; +	if (idx < cnt) { +		data = perfE + *hdr + (idx * len); +		*hdr = len; +	} +	return data; +} + +u32 +nvbios_perfSp(struct nouveau_bios *bios, u32 perfE, int idx, +	      u8 *ver, u8 *hdr, u8 cnt, u8 len, +	      struct nvbios_perfS *info) +{ +	u32 data = nvbios_perfSe(bios, perfE, idx, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!data * *ver) { +	case 0x40: +		info->v40.freq = (nv_ro16(bios, data + 0x00) & 0x3fff) * 1000; +		break; +	default: +		break; +	} +	return data; +} +  int  nvbios_perf_fan_parse(struct nouveau_bios *bios,  		      struct nvbios_perf_fan *fan)  { -	u8 ver = 0, hdr = 0, cnt = 0, len = 0; -	u16 perf = perf_table(bios, &ver, &hdr, &cnt, &len); +	u8  ver, hdr, cnt, len, snr, ssz; +	u16 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);  	if (!perf)  		return -ENODEV; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c index f835501203e..1f76de597d4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c @@ -114,6 +114,7 @@ pll_map(struct nouveau_bios *bios)  	switch (nv_device(bios)->card_type) {  	case NV_04:  	case NV_10: +	case NV_11:  	case NV_20:  	case NV_30:  		return nv04_pll_mapping; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c new file mode 100644 index 00000000000..6c401f70ab9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c @@ -0,0 +1,68 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> + +static u8 +nvbios_ramcfg_strap(struct nouveau_subdev *subdev) +{ +	return (nv_rd32(subdev, 0x101000) & 0x0000003c) >> 2; +} + +u8 +nvbios_ramcfg_count(struct nouveau_bios *bios) +{ +	struct bit_entry bit_M; + +	if (!bit_entry(bios, 'M', &bit_M)) { +		if (bit_M.version == 1 && bit_M.length >= 5) +			return nv_ro08(bios, bit_M.offset + 2); +		if (bit_M.version == 2 && bit_M.length >= 3) +			return nv_ro08(bios, bit_M.offset + 0); +	} + +	return 0x00; +} + +u8 +nvbios_ramcfg_index(struct nouveau_subdev *subdev) +{ +	struct nouveau_bios *bios = nouveau_bios(subdev); +	u8 strap = nvbios_ramcfg_strap(subdev); +	u32 xlat = 0x00000000; +	struct bit_entry bit_M; + +	if (!bit_entry(bios, 'M', &bit_M)) { +		if (bit_M.version == 1 && bit_M.length >= 5) +			xlat = nv_ro16(bios, bit_M.offset + 3); +		if (bit_M.version == 2 && bit_M.length >= 3) +			xlat = nv_ro16(bios, bit_M.offset + 1); +	} + +	if (xlat) +		strap = nv_ro08(bios, xlat + strap); +	return strap; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c new file mode 100644 index 00000000000..1811b2cb047 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/rammap.c @@ -0,0 +1,173 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> +#include <subdev/bios/rammap.h> + +u32 +nvbios_rammapTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, +		u8 *cnt, u8 *len, u8 *snr, u8 *ssz) +{ +	struct bit_entry bit_P; +	u16 rammap = 0x0000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 2) +			rammap = nv_ro16(bios, bit_P.offset + 4); + +		if (rammap) { +			*ver = nv_ro08(bios, rammap + 0); +			switch (*ver) { +			case 0x10: +			case 0x11: +				*hdr = nv_ro08(bios, rammap + 1); +				*cnt = nv_ro08(bios, rammap + 5); +				*len = nv_ro08(bios, rammap + 2); +				*snr = nv_ro08(bios, rammap + 4); +				*ssz = nv_ro08(bios, rammap + 3); +				return rammap; +			default: +				break; +			} +		} +	} + +	return 0x0000; +} + +u32 +nvbios_rammapEe(struct nouveau_bios *bios, int idx, +		u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	u8  snr, ssz; +	u16 rammap = nvbios_rammapTe(bios, ver, hdr, cnt, len, &snr, &ssz); +	if (rammap && idx < *cnt) { +		rammap = rammap + *hdr + (idx * (*len + (snr * ssz))); +		*hdr = *len; +		*cnt = snr; +		*len = ssz; +		return rammap; +	} +	return 0x0000; +} + +u32 +nvbios_rammapEm(struct nouveau_bios *bios, u16 khz, +		u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	int idx = 0; +	u32 data; +	while ((data = nvbios_rammapEe(bios, idx++, ver, hdr, cnt, len))) { +		if (khz >= nv_ro16(bios, data + 0x00) && +		    khz <= nv_ro16(bios, data + 0x02)) +			break; +	} +	return data; +} + +u32 +nvbios_rammapEp(struct nouveau_bios *bios, u16 khz, +		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		struct nvbios_ramcfg *p) +{ +	u32 data = nvbios_rammapEm(bios, khz, ver, hdr, cnt, len); +	memset(p, 0x00, sizeof(*p)); +	switch (!!data * *ver) { +	case 0x11: +		p->rammap_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0; +		p->rammap_11_08_0c = (nv_ro08(bios, data + 0x08) & 0x0c) >> 2; +		p->rammap_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4; +		p->rammap_11_11_0c = (nv_ro08(bios, data + 0x11) & 0x0c) >> 2; +		break; +	default: +		data = 0; +		break; +	} +	return data; +} + +u32 +nvbios_rammapSe(struct nouveau_bios *bios, u32 data, +		u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, +		u8 *ver, u8 *hdr) +{ +	if (idx < ecnt) { +		data = data + ehdr + (idx * elen); +		*ver = ever; +		*hdr = elen; +		return data; +	} +	return 0; +} + +u32 +nvbios_rammapSp(struct nouveau_bios *bios, u32 data, +		u8 ever, u8 ehdr, u8 ecnt, u8 elen, int idx, +		u8 *ver, u8 *hdr, struct nvbios_ramcfg *p) +{ +	data = nvbios_rammapSe(bios, data, ever, ehdr, ecnt, elen, idx, ver, hdr); +	switch (!!data * *ver) { +	case 0x11: +		p->ramcfg_11_01_01 = (nv_ro08(bios, data + 0x01) & 0x01) >> 0; +		p->ramcfg_11_01_02 = (nv_ro08(bios, data + 0x01) & 0x02) >> 1; +		p->ramcfg_11_01_04 = (nv_ro08(bios, data + 0x01) & 0x04) >> 2; +		p->ramcfg_11_01_08 = (nv_ro08(bios, data + 0x01) & 0x08) >> 3; +		p->ramcfg_11_01_10 = (nv_ro08(bios, data + 0x01) & 0x10) >> 4; +		p->ramcfg_11_01_20 = (nv_ro08(bios, data + 0x01) & 0x20) >> 5; +		p->ramcfg_11_01_40 = (nv_ro08(bios, data + 0x01) & 0x40) >> 6; +		p->ramcfg_11_01_80 = (nv_ro08(bios, data + 0x01) & 0x80) >> 7; +		p->ramcfg_11_02_03 = (nv_ro08(bios, data + 0x02) & 0x03) >> 0; +		p->ramcfg_11_02_04 = (nv_ro08(bios, data + 0x02) & 0x04) >> 2; +		p->ramcfg_11_02_08 = (nv_ro08(bios, data + 0x02) & 0x08) >> 3; +		p->ramcfg_11_02_10 = (nv_ro08(bios, data + 0x02) & 0x10) >> 4; +		p->ramcfg_11_02_40 = (nv_ro08(bios, data + 0x02) & 0x40) >> 6; +		p->ramcfg_11_02_80 = (nv_ro08(bios, data + 0x02) & 0x80) >> 7; +		p->ramcfg_11_03_0f = (nv_ro08(bios, data + 0x03) & 0x0f) >> 0; +		p->ramcfg_11_03_30 = (nv_ro08(bios, data + 0x03) & 0x30) >> 4; +		p->ramcfg_11_03_c0 = (nv_ro08(bios, data + 0x03) & 0xc0) >> 6; +		p->ramcfg_11_03_f0 = (nv_ro08(bios, data + 0x03) & 0xf0) >> 4; +		p->ramcfg_11_04    = (nv_ro08(bios, data + 0x04) & 0xff) >> 0; +		p->ramcfg_11_06    = (nv_ro08(bios, data + 0x06) & 0xff) >> 0; +		p->ramcfg_11_07_02 = (nv_ro08(bios, data + 0x07) & 0x02) >> 1; +		p->ramcfg_11_07_04 = (nv_ro08(bios, data + 0x07) & 0x04) >> 2; +		p->ramcfg_11_07_08 = (nv_ro08(bios, data + 0x07) & 0x08) >> 3; +		p->ramcfg_11_07_10 = (nv_ro08(bios, data + 0x07) & 0x10) >> 4; +		p->ramcfg_11_07_40 = (nv_ro08(bios, data + 0x07) & 0x40) >> 6; +		p->ramcfg_11_07_80 = (nv_ro08(bios, data + 0x07) & 0x80) >> 7; +		p->ramcfg_11_08_01 = (nv_ro08(bios, data + 0x08) & 0x01) >> 0; +		p->ramcfg_11_08_02 = (nv_ro08(bios, data + 0x08) & 0x02) >> 1; +		p->ramcfg_11_08_04 = (nv_ro08(bios, data + 0x08) & 0x04) >> 2; +		p->ramcfg_11_08_08 = (nv_ro08(bios, data + 0x08) & 0x08) >> 3; +		p->ramcfg_11_08_10 = (nv_ro08(bios, data + 0x08) & 0x10) >> 4; +		p->ramcfg_11_08_20 = (nv_ro08(bios, data + 0x08) & 0x20) >> 5; +		p->ramcfg_11_09    = (nv_ro08(bios, data + 0x09) & 0xff) >> 0; +		break; +	default: +		data = 0; +		break; +	} +	return data; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c index 22ac6dbd6c8..d1585409407 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c @@ -164,6 +164,7 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,  	i = 0;  	fan->nr_fan_trip = 0; +	fan->fan_mode = NVBIOS_THERM_FAN_OTHER;  	while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) {  		s16 value = nv_ro16(bios, entry + 1); @@ -174,6 +175,8 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,  			break;  		case 0x24:  			fan->nr_fan_trip++; +			if (fan->fan_mode > NVBIOS_THERM_FAN_TRIP) +				fan->fan_mode = NVBIOS_THERM_FAN_TRIP;  			cur_trip = &fan->trip[fan->nr_fan_trip - 1];  			cur_trip->hysteresis = value & 0xf;  			cur_trip->temp = (value & 0xff0) >> 4; @@ -194,11 +197,19 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios,  			fan->slow_down_period = value;  			break;  		case 0x46: +			if (fan->fan_mode > NVBIOS_THERM_FAN_LINEAR) +				fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;  			fan->linear_min_temp = nv_ro08(bios, entry + 1);  			fan->linear_max_temp = nv_ro08(bios, entry + 2);  			break;  		}  	} +	/* starting from fermi, fan management is always linear */ +	if (nv_device(bios)->card_type >= NV_C0 && +		fan->fan_mode == NVBIOS_THERM_FAN_OTHER) { +		fan->fan_mode = NVBIOS_THERM_FAN_LINEAR; +	} +  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c new file mode 100644 index 00000000000..350d44ab2ba --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/timing.c @@ -0,0 +1,127 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/ramcfg.h> +#include <subdev/bios/timing.h> + +u16 +nvbios_timingTe(struct nouveau_bios *bios, +		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz) +{ +	struct bit_entry bit_P; +	u16 timing = 0x0000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 1) +			timing = nv_ro16(bios, bit_P.offset + 4); +		else +		if (bit_P.version == 2) +			timing = nv_ro16(bios, bit_P.offset + 8); + +		if (timing) { +			*ver = nv_ro08(bios, timing + 0); +			switch (*ver) { +			case 0x10: +				*hdr = nv_ro08(bios, timing + 1); +				*cnt = nv_ro08(bios, timing + 2); +				*len = nv_ro08(bios, timing + 3); +				*snr = 0; +				*ssz = 0; +				return timing; +			case 0x20: +				*hdr = nv_ro08(bios, timing + 1); +				*cnt = nv_ro08(bios, timing + 5); +				*len = nv_ro08(bios, timing + 2); +				*snr = nv_ro08(bios, timing + 4); +				*ssz = nv_ro08(bios, timing + 3); +				return timing; +			default: +				break; +			} +		} +	} + +	return 0x0000; +} + +u16 +nvbios_timingEe(struct nouveau_bios *bios, int idx, +		u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	u8  snr, ssz; +	u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz); +	if (timing && idx < *cnt) { +		timing += *hdr + idx * (*len + (snr * ssz)); +		*hdr = *len; +		*cnt = snr; +		*len = ssz; +		return timing; +	} +	return 0x0000; +} + +u16 +nvbios_timingEp(struct nouveau_bios *bios, int idx, +		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		struct nvbios_ramcfg *p) +{ +	u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp; +	switch (!!data * *ver) { +	case 0x20: +		p->timing[0] = nv_ro32(bios, data + 0x00); +		p->timing[1] = nv_ro32(bios, data + 0x04); +		p->timing[2] = nv_ro32(bios, data + 0x08); +		p->timing[3] = nv_ro32(bios, data + 0x0c); +		p->timing[4] = nv_ro32(bios, data + 0x10); +		p->timing[5] = nv_ro32(bios, data + 0x14); +		p->timing[6] = nv_ro32(bios, data + 0x18); +		p->timing[7] = nv_ro32(bios, data + 0x1c); +		p->timing[8] = nv_ro32(bios, data + 0x20); +		p->timing[9] = nv_ro32(bios, data + 0x24); +		p->timing[10] = nv_ro32(bios, data + 0x28); +		p->timing_20_2e_03 = (nv_ro08(bios, data + 0x2e) & 0x03) >> 0; +		p->timing_20_2e_30 = (nv_ro08(bios, data + 0x2e) & 0x30) >> 4; +		p->timing_20_2e_c0 = (nv_ro08(bios, data + 0x2e) & 0xc0) >> 6; +		p->timing_20_2f_03 = (nv_ro08(bios, data + 0x2f) & 0x03) >> 0; +		temp = nv_ro16(bios, data + 0x2c); +		p->timing_20_2c_003f = (temp & 0x003f) >> 0; +		p->timing_20_2c_1fc0 = (temp & 0x1fc0) >> 6; +		p->timing_20_30_07 = (nv_ro08(bios, data + 0x30) & 0x07) >> 0; +		p->timing_20_30_f8 = (nv_ro08(bios, data + 0x30) & 0xf8) >> 3; +		temp = nv_ro16(bios, data + 0x31); +		p->timing_20_31_0007 = (temp & 0x0007) >> 0; +		p->timing_20_31_0078 = (temp & 0x0078) >> 3; +		p->timing_20_31_0780 = (temp & 0x0780) >> 7; +		p->timing_20_31_0800 = (temp & 0x0800) >> 11; +		p->timing_20_31_7000 = (temp & 0x7000) >> 12; +		p->timing_20_31_8000 = (temp & 0x8000) >> 15; +		break; +	default: +		data = 0; +		break; +	} +	return data; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c b/drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c new file mode 100644 index 00000000000..f343a1b060e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/vmap.c @@ -0,0 +1,112 @@ +/* + * Copyright 2012 Nouveau Community + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Martin Peres + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/vmap.h> + +u16 +nvbios_vmap_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	struct bit_entry bit_P; +	u16 vmap = 0x0000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 2) { +			vmap = nv_ro16(bios, bit_P.offset + 0x20); +			if (vmap) { +				*ver = nv_ro08(bios, vmap + 0); +				switch (*ver) { +				case 0x10: +				case 0x20: +					*hdr = nv_ro08(bios, vmap + 1); +					*cnt = nv_ro08(bios, vmap + 3); +					*len = nv_ro08(bios, vmap + 2); +					return vmap; +				default: +					break; +				} +			} +		} +	} + +	return 0x0000; +} + +u16 +nvbios_vmap_parse(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		  struct nvbios_vmap *info) +{ +	u16 vmap = nvbios_vmap_table(bios, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!vmap * *ver) { +	case 0x10: +	case 0x20: +		break; +	} +	return vmap; +} + +u16 +nvbios_vmap_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) +{ +	u8  hdr, cnt; +	u16 vmap = nvbios_vmap_table(bios, ver, &hdr, &cnt, len); +	if (vmap && idx < cnt) { +		vmap = vmap + hdr + (idx * *len); +		return vmap; +	} +	return 0x0000; +} + +u16 +nvbios_vmap_entry_parse(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len, +			struct nvbios_vmap_entry *info) +{ +	u16 vmap = nvbios_vmap_entry(bios, idx, ver, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!vmap * *ver) { +	case 0x10: +		info->link   = 0xff; +		info->min    = nv_ro32(bios, vmap + 0x00); +		info->max    = nv_ro32(bios, vmap + 0x04); +		info->arg[0] = nv_ro32(bios, vmap + 0x08); +		info->arg[1] = nv_ro32(bios, vmap + 0x0c); +		info->arg[2] = nv_ro32(bios, vmap + 0x10); +		break; +	case 0x20: +		info->unk0   = nv_ro08(bios, vmap + 0x00); +		info->link   = nv_ro08(bios, vmap + 0x01); +		info->min    = nv_ro32(bios, vmap + 0x02); +		info->max    = nv_ro32(bios, vmap + 0x06); +		info->arg[0] = nv_ro32(bios, vmap + 0x0a); +		info->arg[1] = nv_ro32(bios, vmap + 0x0e); +		info->arg[2] = nv_ro32(bios, vmap + 0x12); +		info->arg[3] = nv_ro32(bios, vmap + 0x16); +		info->arg[4] = nv_ro32(bios, vmap + 0x1a); +		info->arg[5] = nv_ro32(bios, vmap + 0x1e); +		break; +	} +	return vmap; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/core/subdev/bios/volt.c new file mode 100644 index 00000000000..bb590de4ecb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/volt.c @@ -0,0 +1,137 @@ +/* + * Copyright 2012 Nouveau Community + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Martin Peres + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/volt.h> + +u16 +nvbios_volt_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) +{ +	struct bit_entry bit_P; +	u16 volt = 0x0000; + +	if (!bit_entry(bios, 'P', &bit_P)) { +		if (bit_P.version == 2) +			volt = nv_ro16(bios, bit_P.offset + 0x0c); +		else +		if (bit_P.version == 1) +			volt = nv_ro16(bios, bit_P.offset + 0x10); + +		if (volt) { +			*ver = nv_ro08(bios, volt + 0); +			switch (*ver) { +			case 0x12: +				*hdr = 5; +				*cnt = nv_ro08(bios, volt + 2); +				*len = nv_ro08(bios, volt + 1); +				return volt; +			case 0x20: +				*hdr = nv_ro08(bios, volt + 1); +				*cnt = nv_ro08(bios, volt + 2); +				*len = nv_ro08(bios, volt + 3); +				return volt; +			case 0x30: +			case 0x40: +			case 0x50: +				*hdr = nv_ro08(bios, volt + 1); +				*cnt = nv_ro08(bios, volt + 3); +				*len = nv_ro08(bios, volt + 2); +				return volt; +			} +		} +	} + +	return 0x0000; +} + +u16 +nvbios_volt_parse(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, +		  struct nvbios_volt *info) +{ +	u16 volt = nvbios_volt_table(bios, ver, hdr, cnt, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!volt * *ver) { +	case 0x12: +		info->vidmask = nv_ro08(bios, volt + 0x04); +		break; +	case 0x20: +		info->vidmask = nv_ro08(bios, volt + 0x05); +		break; +	case 0x30: +		info->vidmask = nv_ro08(bios, volt + 0x04); +		break; +	case 0x40: +		info->base    = nv_ro32(bios, volt + 0x04); +		info->step    = nv_ro16(bios, volt + 0x08); +		info->vidmask = nv_ro08(bios, volt + 0x0b); +		/*XXX*/ +		info->min     = 0; +		info->max     = info->base; +		break; +	case 0x50: +		info->vidmask = nv_ro08(bios, volt + 0x06); +		info->min     = nv_ro32(bios, volt + 0x0a); +		info->max     = nv_ro32(bios, volt + 0x0e); +		info->base    = nv_ro32(bios, volt + 0x12) & 0x00ffffff; +		info->step    = nv_ro16(bios, volt + 0x16); +		break; +	} +	return volt; +} + +u16 +nvbios_volt_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) +{ +	u8  hdr, cnt; +	u16 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len); +	if (volt && idx < cnt) { +		volt = volt + hdr + (idx * *len); +		return volt; +	} +	return 0x0000; +} + +u16 +nvbios_volt_entry_parse(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len, +			struct nvbios_volt_entry *info) +{ +	u16 volt = nvbios_volt_entry(bios, idx, ver, len); +	memset(info, 0x00, sizeof(*info)); +	switch (!!volt * *ver) { +	case 0x12: +	case 0x20: +		info->voltage = nv_ro08(bios, volt + 0x00) * 10000; +		info->vid     = nv_ro08(bios, volt + 0x01); +		break; +	case 0x30: +		info->voltage = nv_ro08(bios, volt + 0x00) * 10000; +		info->vid     = nv_ro08(bios, volt + 0x01) >> 2; +		break; +	case 0x40: +	case 0x50: +		break; +	} +	return volt; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c new file mode 100644 index 00000000000..f757470e228 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.c @@ -0,0 +1,145 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include <subdev/timer.h> +#include <subdev/bus.h> + +struct nouveau_hwsq { +	struct nouveau_bus *pbus; +	u32 addr; +	u32 data; +	struct { +		u8 data[512]; +		u8 size; +	} c; +}; + +static void +hwsq_cmd(struct nouveau_hwsq *hwsq, int size, u8 data[]) +{ +	memcpy(&hwsq->c.data[hwsq->c.size], data, size * sizeof(data[0])); +	hwsq->c.size += size; +} + +int +nouveau_hwsq_init(struct nouveau_bus *pbus, struct nouveau_hwsq **phwsq) +{ +	struct nouveau_hwsq *hwsq; + +	hwsq = *phwsq = kmalloc(sizeof(*hwsq), GFP_KERNEL); +	if (hwsq) { +		hwsq->pbus = pbus; +		hwsq->addr = ~0; +		hwsq->data = ~0; +		memset(hwsq->c.data, 0x7f, sizeof(hwsq->c.data)); +		hwsq->c.size = 0; +	} + +	return hwsq ? 0 : -ENOMEM; +} + +int +nouveau_hwsq_fini(struct nouveau_hwsq **phwsq, bool exec) +{ +	struct nouveau_hwsq *hwsq = *phwsq; +	int ret = 0, i; +	if (hwsq) { +		struct nouveau_bus *pbus = hwsq->pbus; +		hwsq->c.size = (hwsq->c.size + 4) / 4; +		if (hwsq->c.size <= pbus->hwsq_size) { +			if (exec) +				ret = pbus->hwsq_exec(pbus, (u32 *)hwsq->c.data, +						      hwsq->c.size); +			if (ret) +				nv_error(pbus, "hwsq exec failed: %d\n", ret); +		} else { +			nv_error(pbus, "hwsq ucode too large\n"); +			ret = -ENOSPC; +		} + +		for (i = 0; ret && i < hwsq->c.size; i++) +			nv_error(pbus, "\t0x%08x\n", ((u32 *)hwsq->c.data)[i]); + +		*phwsq = NULL; +		kfree(hwsq); +	} +	return ret; +} + +void +nouveau_hwsq_wr32(struct nouveau_hwsq *hwsq, u32 addr, u32 data) +{ +	nv_debug(hwsq->pbus, "R[%06x] = 0x%08x\n", addr, data); + +	if (hwsq->data != data) { +		if ((data & 0xffff0000) != (hwsq->data & 0xffff0000)) { +			hwsq_cmd(hwsq, 5, (u8[]){ 0xe2, data, data >> 8, +						  data >> 16, data >> 24 }); +		} else { +			hwsq_cmd(hwsq, 3, (u8[]){ 0x42, data, data >> 8 }); +		} +	} + +	if ((addr & 0xffff0000) != (hwsq->addr & 0xffff0000)) { +		hwsq_cmd(hwsq, 5, (u8[]){ 0xe0, addr, addr >> 8, +					  addr >> 16, addr >> 24 }); +	} else { +		hwsq_cmd(hwsq, 3, (u8[]){ 0x40, addr, addr >> 8 }); +	} + +	hwsq->addr = addr; +	hwsq->data = data; +} + +void +nouveau_hwsq_setf(struct nouveau_hwsq *hwsq, u8 flag, int data) +{ +	nv_debug(hwsq->pbus, " FLAG[%02x] = %d\n", flag, data); +	flag += 0x80; +	if (data >= 0) +		flag += 0x20; +	if (data >= 1) +		flag += 0x20; +	hwsq_cmd(hwsq, 1, (u8[]){ flag }); +} + +void +nouveau_hwsq_wait(struct nouveau_hwsq *hwsq, u8 flag, u8 data) +{ +	nv_debug(hwsq->pbus, " WAIT[%02x] = %d\n", flag, data); +	hwsq_cmd(hwsq, 3, (u8[]){ 0x5f, flag, data }); +} + +void +nouveau_hwsq_nsec(struct nouveau_hwsq *hwsq, u32 nsec) +{ +	u8 shift = 0, usec = nsec / 1000; +	while (usec & ~3) { +		usec >>= 2; +		shift++; +	} + +	nv_debug(hwsq->pbus, "    DELAY = %d ns\n", nsec); +	hwsq_cmd(hwsq, 1, (u8[]){ 0x00 | (shift << 2) | usec }); +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h new file mode 100644 index 00000000000..12176f9c1bc --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/hwsq.h @@ -0,0 +1,113 @@ +#ifndef __NVKM_BUS_HWSQ_H__ +#define __NVKM_BUS_HWSQ_H__ + +#include <subdev/bus.h> + +struct hwsq { +	struct nouveau_subdev *subdev; +	struct nouveau_hwsq *hwsq; +	int sequence; +}; + +struct hwsq_reg { +	int sequence; +	bool force; +	u32 addr[2]; +	u32 data; +}; + +static inline struct hwsq_reg +hwsq_reg2(u32 addr1, u32 addr2) +{ +	return (struct hwsq_reg) { +		.sequence = 0, +		.force = 0, +		.addr = { addr1, addr2 }, +		.data = 0xdeadbeef, +	}; +} + +static inline struct hwsq_reg +hwsq_reg(u32 addr) +{ +	return hwsq_reg2(addr, addr); +} + +static inline int +hwsq_init(struct hwsq *ram, struct nouveau_subdev *subdev) +{ +	struct nouveau_bus *pbus = nouveau_bus(subdev); +	int ret; + +	ret = nouveau_hwsq_init(pbus, &ram->hwsq); +	if (ret) +		return ret; + +	ram->sequence++; +	ram->subdev = subdev; +	return 0; +} + +static inline int +hwsq_exec(struct hwsq *ram, bool exec) +{ +	int ret = 0; +	if (ram->subdev) { +		ret = nouveau_hwsq_fini(&ram->hwsq, exec); +		ram->subdev = NULL; +	} +	return ret; +} + +static inline u32 +hwsq_rd32(struct hwsq *ram, struct hwsq_reg *reg) +{ +	if (reg->sequence != ram->sequence) +		reg->data = nv_rd32(ram->subdev, reg->addr[0]); +	return reg->data; +} + +static inline void +hwsq_wr32(struct hwsq *ram, struct hwsq_reg *reg, u32 data) +{ +	reg->sequence = ram->sequence; +	reg->data = data; +	if (reg->addr[0] != reg->addr[1]) +		nouveau_hwsq_wr32(ram->hwsq, reg->addr[1], reg->data); +	nouveau_hwsq_wr32(ram->hwsq, reg->addr[0], reg->data); +} + +static inline void +hwsq_nuke(struct hwsq *ram, struct hwsq_reg *reg) +{ +	reg->force = true; +} + +static inline u32 +hwsq_mask(struct hwsq *ram, struct hwsq_reg *reg, u32 mask, u32 data) +{ +	u32 temp = hwsq_rd32(ram, reg); +	if (temp != ((temp & ~mask) | data) || reg->force) +		hwsq_wr32(ram, reg, (temp & ~mask) | data); +	return temp; +} + +static inline void +hwsq_setf(struct hwsq *ram, u8 flag, int data) +{ +	nouveau_hwsq_setf(ram->hwsq, flag, data); +} + +static inline void +hwsq_wait(struct hwsq *ram, u8 flag, u8 data) +{ +	nouveau_hwsq_wait(ram->hwsq, flag, data); +} + +static inline void +hwsq_nsec(struct hwsq *ram, u32 nsec) +{ +	nouveau_hwsq_nsec(ram->hwsq, nsec); +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c index 8c7f8057a18..23921b5351d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c @@ -23,11 +23,7 @@   *          Ben Skeggs   */ -#include <subdev/bus.h> - -struct nv04_bus_priv { -	struct nouveau_bus base; -}; +#include "nv04.h"  static void  nv04_bus_intr(struct nouveau_subdev *subdev) @@ -56,10 +52,22 @@ nv04_bus_intr(struct nouveau_subdev *subdev)  }  static int +nv04_bus_init(struct nouveau_object *object) +{ +	struct nv04_bus_priv *priv = (void *)object; + +	nv_wr32(priv, 0x001100, 0xffffffff); +	nv_wr32(priv, 0x001140, 0x00000111); + +	return nouveau_bus_init(&priv->base); +} + +int  nv04_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	      struct nouveau_oclass *oclass, void *data, u32 size,  	      struct nouveau_object **pobject)  { +	struct nv04_bus_impl *impl = (void *)oclass;  	struct nv04_bus_priv *priv;  	int ret; @@ -68,28 +76,20 @@ nv04_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; -	nv_subdev(priv)->intr = nv04_bus_intr; +	nv_subdev(priv)->intr = impl->intr; +	priv->base.hwsq_exec = impl->hwsq_exec; +	priv->base.hwsq_size = impl->hwsq_size;  	return 0;  } -static int -nv04_bus_init(struct nouveau_object *object) -{ -	struct nv04_bus_priv *priv = (void *)object; - -	nv_wr32(priv, 0x001100, 0xffffffff); -	nv_wr32(priv, 0x001140, 0x00000111); - -	return nouveau_bus_init(&priv->base); -} - -struct nouveau_oclass -nv04_bus_oclass = { -	.handle = NV_SUBDEV(BUS, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_bus_oclass = &(struct nv04_bus_impl) { +	.base.handle = NV_SUBDEV(BUS, 0x04), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_bus_ctor,  		.dtor = _nouveau_bus_dtor,  		.init = nv04_bus_init,  		.fini = _nouveau_bus_fini,  	}, -}; +	.intr = nv04_bus_intr, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h new file mode 100644 index 00000000000..4d7602450a2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.h @@ -0,0 +1,23 @@ +#ifndef __NVKM_BUS_NV04_H__ +#define __NVKM_BUS_NV04_H__ + +#include <subdev/bus.h> + +struct nv04_bus_priv { +	struct nouveau_bus base; +}; + +int  nv04_bus_ctor(struct nouveau_object *, struct nouveau_object *, +		   struct nouveau_oclass *, void *, u32, +		   struct nouveau_object **); +int  nv50_bus_init(struct nouveau_object *); +void nv50_bus_intr(struct nouveau_subdev *); + +struct nv04_bus_impl { +	struct nouveau_oclass base; +	void (*intr)(struct nouveau_subdev *); +	int  (*hwsq_exec)(struct nouveau_bus *, u32 *, u32); +	u32  hwsq_size; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c index 34132aef34e..94da46f6162 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c @@ -23,11 +23,7 @@   *          Ben Skeggs   */ -#include <subdev/bus.h> - -struct nv31_bus_priv { -	struct nouveau_bus base; -}; +#include "nv04.h"  static void  nv31_bus_intr(struct nouveau_subdev *subdev) @@ -71,7 +67,7 @@ nv31_bus_intr(struct nouveau_subdev *subdev)  static int  nv31_bus_init(struct nouveau_object *object)  { -	struct nv31_bus_priv *priv = (void *)object; +	struct nv04_bus_priv *priv = (void *)object;  	int ret;  	ret = nouveau_bus_init(&priv->base); @@ -83,30 +79,14 @@ nv31_bus_init(struct nouveau_object *object)  	return 0;  } -static int -nv31_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv31_bus_priv *priv; -	int ret; - -	ret = nouveau_bus_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	nv_subdev(priv)->intr = nv31_bus_intr; -	return 0; -} - -struct nouveau_oclass -nv31_bus_oclass = { -	.handle = NV_SUBDEV(BUS, 0x31), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv31_bus_ctor, +struct nouveau_oclass * +nv31_bus_oclass = &(struct nv04_bus_impl) { +	.base.handle = NV_SUBDEV(BUS, 0x31), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_bus_ctor,  		.dtor = _nouveau_bus_dtor,  		.init = nv31_bus_init,  		.fini = _nouveau_bus_fini,  	}, -}; +	.intr = nv31_bus_intr, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c index f5b2117fa8c..11918f7e2ac 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c @@ -23,13 +23,27 @@   *          Ben Skeggs   */ -#include <subdev/bus.h> +#include <subdev/timer.h> -struct nv50_bus_priv { -	struct nouveau_bus base; -}; +#include "nv04.h" -static void +static int +nv50_bus_hwsq_exec(struct nouveau_bus *pbus, u32 *data, u32 size) +{ +	struct nv50_bus_priv *priv = (void *)pbus; +	int i; + +	nv_mask(pbus, 0x001098, 0x00000008, 0x00000000); +	nv_wr32(pbus, 0x001304, 0x00000000); +	for (i = 0; i < size; i++) +		nv_wr32(priv, 0x001400 + (i * 4), data[i]); +	nv_mask(pbus, 0x001098, 0x00000018, 0x00000018); +	nv_wr32(pbus, 0x00130c, 0x00000003); + +	return nv_wait(pbus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; +} + +void  nv50_bus_intr(struct nouveau_subdev *subdev)  {  	struct nouveau_bus *pbus = nouveau_bus(subdev); @@ -61,10 +75,10 @@ nv50_bus_intr(struct nouveau_subdev *subdev)  	}  } -static int +int  nv50_bus_init(struct nouveau_object *object)  { -	struct nv50_bus_priv *priv = (void *)object; +	struct nv04_bus_priv *priv = (void *)object;  	int ret;  	ret = nouveau_bus_init(&priv->base); @@ -76,30 +90,16 @@ nv50_bus_init(struct nouveau_object *object)  	return 0;  } -static int -nv50_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv50_bus_priv *priv; -	int ret; - -	ret = nouveau_bus_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	nv_subdev(priv)->intr = nv50_bus_intr; -	return 0; -} - -struct nouveau_oclass -nv50_bus_oclass = { -	.handle = NV_SUBDEV(BUS, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv50_bus_ctor, +struct nouveau_oclass * +nv50_bus_oclass = &(struct nv04_bus_impl) { +	.base.handle = NV_SUBDEV(BUS, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_bus_ctor,  		.dtor = _nouveau_bus_dtor,  		.init = nv50_bus_init,  		.fini = _nouveau_bus_fini,  	}, -}; +	.intr = nv50_bus_intr, +	.hwsq_exec = nv50_bus_hwsq_exec, +	.hwsq_size = 64, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c new file mode 100644 index 00000000000..d3659055fa4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nv94.c @@ -0,0 +1,59 @@ +/* + * Copyright 2012 Nouveau Community + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Martin Peres <martin.peres@labri.fr> + *          Ben Skeggs + */ + +#include <subdev/timer.h> + +#include "nv04.h" + +static int +nv94_bus_hwsq_exec(struct nouveau_bus *pbus, u32 *data, u32 size) +{ +	struct nv50_bus_priv *priv = (void *)pbus; +	int i; + +	nv_mask(pbus, 0x001098, 0x00000008, 0x00000000); +	nv_wr32(pbus, 0x001304, 0x00000000); +	nv_wr32(pbus, 0x001318, 0x00000000); +	for (i = 0; i < size; i++) +		nv_wr32(priv, 0x080000 + (i * 4), data[i]); +	nv_mask(pbus, 0x001098, 0x00000018, 0x00000018); +	nv_wr32(pbus, 0x00130c, 0x00000001); + +	return nv_wait(pbus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; +} + +struct nouveau_oclass * +nv94_bus_oclass = &(struct nv04_bus_impl) { +	.base.handle = NV_SUBDEV(BUS, 0x94), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_bus_ctor, +		.dtor = _nouveau_bus_dtor, +		.init = nv50_bus_init, +		.fini = _nouveau_bus_fini, +	}, +	.intr = nv50_bus_intr, +	.hwsq_exec = nv94_bus_hwsq_exec, +	.hwsq_size = 128, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c index b192d624636..73839d7151a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c @@ -23,11 +23,7 @@   *          Ben Skeggs   */ -#include <subdev/bus.h> - -struct nvc0_bus_priv { -	struct nouveau_bus base; -}; +#include "nv04.h"  static void  nvc0_bus_intr(struct nouveau_subdev *subdev) @@ -60,7 +56,7 @@ nvc0_bus_intr(struct nouveau_subdev *subdev)  static int  nvc0_bus_init(struct nouveau_object *object)  { -	struct nvc0_bus_priv *priv = (void *)object; +	struct nv04_bus_priv *priv = (void *)object;  	int ret;  	ret = nouveau_bus_init(&priv->base); @@ -72,30 +68,14 @@ nvc0_bus_init(struct nouveau_object *object)  	return 0;  } -static int -nvc0_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nvc0_bus_priv *priv; -	int ret; - -	ret = nouveau_bus_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	nv_subdev(priv)->intr = nvc0_bus_intr; -	return 0; -} - -struct nouveau_oclass -nvc0_bus_oclass = { -	.handle = NV_SUBDEV(BUS, 0xc0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvc0_bus_ctor, +struct nouveau_oclass * +nvc0_bus_oclass = &(struct nv04_bus_impl) { +	.base.handle = NV_SUBDEV(BUS, 0xc0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_bus_ctor,  		.dtor = _nouveau_bus_dtor,  		.init = nvc0_bus_init,  		.fini = _nouveau_bus_fini,  	}, -}; +	.intr = nvc0_bus_intr, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/base.c b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c new file mode 100644 index 00000000000..22351f594d2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/base.c @@ -0,0 +1,500 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <core/option.h> + +#include <subdev/clock.h> +#include <subdev/therm.h> +#include <subdev/volt.h> +#include <subdev/fb.h> + +#include <subdev/bios.h> +#include <subdev/bios/boost.h> +#include <subdev/bios/cstep.h> +#include <subdev/bios/perf.h> + +/****************************************************************************** + * misc + *****************************************************************************/ +static u32 +nouveau_clock_adjust(struct nouveau_clock *clk, bool adjust, +		     u8 pstate, u8 domain, u32 input) +{ +	struct nouveau_bios *bios = nouveau_bios(clk); +	struct nvbios_boostE boostE; +	u8  ver, hdr, cnt, len; +	u16 data; + +	data = nvbios_boostEm(bios, pstate, &ver, &hdr, &cnt, &len, &boostE); +	if (data) { +		struct nvbios_boostS boostS; +		u8  idx = 0, sver, shdr; +		u16 subd; + +		input = max(boostE.min, input); +		input = min(boostE.max, input); +		do { +			sver = ver; +			shdr = hdr; +			subd = nvbios_boostSp(bios, idx++, data, &sver, &shdr, +					      cnt, len, &boostS); +			if (subd && boostS.domain == domain) { +				if (adjust) +					input = input * boostS.percent / 100; +				input = max(boostS.min, input); +				input = min(boostS.max, input); +				break; +			} +		} while (subd); +	} + +	return input; +} + +/****************************************************************************** + * C-States + *****************************************************************************/ +static int +nouveau_cstate_prog(struct nouveau_clock *clk, +		    struct nouveau_pstate *pstate, int cstatei) +{ +	struct nouveau_therm *ptherm = nouveau_therm(clk); +	struct nouveau_volt *volt = nouveau_volt(clk); +	struct nouveau_cstate *cstate; +	int ret; + +	if (!list_empty(&pstate->list)) { +		cstate = list_entry(pstate->list.prev, typeof(*cstate), head); +	} else { +		cstate = &pstate->base; +	} + +	ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, +1); +	if (ret && ret != -ENODEV) { +		nv_error(clk, "failed to raise fan speed: %d\n", ret); +		return ret; +	} + +	ret = volt->set_id(volt, cstate->voltage, +1); +	if (ret && ret != -ENODEV) { +		nv_error(clk, "failed to raise voltage: %d\n", ret); +		return ret; +	} + +	ret = clk->calc(clk, cstate); +	if (ret == 0) { +		ret = clk->prog(clk); +		clk->tidy(clk); +	} + +	ret = volt->set_id(volt, cstate->voltage, -1); +	if (ret && ret != -ENODEV) +		nv_error(clk, "failed to lower voltage: %d\n", ret); + +	ret = nouveau_therm_cstate(ptherm, pstate->fanspeed, -1); +	if (ret && ret != -ENODEV) +		nv_error(clk, "failed to lower fan speed: %d\n", ret); + +	return 0; +} + +static void +nouveau_cstate_del(struct nouveau_cstate *cstate) +{ +	list_del(&cstate->head); +	kfree(cstate); +} + +static int +nouveau_cstate_new(struct nouveau_clock *clk, int idx, +		   struct nouveau_pstate *pstate) +{ +	struct nouveau_bios *bios = nouveau_bios(clk); +	struct nouveau_clocks *domain = clk->domains; +	struct nouveau_cstate *cstate = NULL; +	struct nvbios_cstepX cstepX; +	u8  ver, hdr; +	u16 data; + +	data = nvbios_cstepXp(bios, idx, &ver, &hdr, &cstepX); +	if (!data) +		return -ENOENT; + +	cstate = kzalloc(sizeof(*cstate), GFP_KERNEL); +	if (!cstate) +		return -ENOMEM; + +	*cstate = pstate->base; +	cstate->voltage = cstepX.voltage; + +	while (domain && domain->name != nv_clk_src_max) { +		if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) { +			u32 freq = nouveau_clock_adjust(clk, true, +							pstate->pstate, +							domain->bios, +							cstepX.freq); +			cstate->domain[domain->name] = freq; +		} +		domain++; +	} + +	list_add(&cstate->head, &pstate->list); +	return 0; +} + +/****************************************************************************** + * P-States + *****************************************************************************/ +static int +nouveau_pstate_prog(struct nouveau_clock *clk, int pstatei) +{ +	struct nouveau_fb *pfb = nouveau_fb(clk); +	struct nouveau_pstate *pstate; +	int ret, idx = 0; + +	list_for_each_entry(pstate, &clk->states, head) { +		if (idx++ == pstatei) +			break; +	} + +	nv_debug(clk, "setting performance state %d\n", pstatei); +	clk->pstate = pstatei; + +	if (pfb->ram->calc) { +		int khz = pstate->base.domain[nv_clk_src_mem]; +		do { +			ret = pfb->ram->calc(pfb, khz); +			if (ret == 0) +				ret = pfb->ram->prog(pfb); +		} while (ret > 0); +		pfb->ram->tidy(pfb); +	} + +	return nouveau_cstate_prog(clk, pstate, 0); +} + +static int +nouveau_pstate_calc(struct nouveau_clock *clk) +{ +	int pstate, ret = 0; + +	nv_trace(clk, "P %d U %d A %d T %d D %d\n", clk->pstate, +		 clk->ustate, clk->astate, clk->tstate, clk->dstate); + +	if (clk->state_nr && clk->ustate != -1) { +		pstate = (clk->ustate < 0) ? clk->astate : clk->ustate; +		pstate = min(pstate, clk->state_nr - 1 - clk->tstate); +		pstate = max(pstate, clk->dstate); +	} else { +		pstate = clk->pstate = -1; +	} + +	nv_trace(clk, "-> %d\n", pstate); +	if (pstate != clk->pstate) +		ret = nouveau_pstate_prog(clk, pstate); +	return ret; +} + +static void +nouveau_pstate_info(struct nouveau_clock *clk, struct nouveau_pstate *pstate) +{ +	struct nouveau_clocks *clock = clk->domains - 1; +	struct nouveau_cstate *cstate; +	char info[3][32] = { "", "", "" }; +	char name[4] = "--"; +	int i = -1; + +	if (pstate->pstate != 0xff) +		snprintf(name, sizeof(name), "%02x", pstate->pstate); + +	while ((++clock)->name != nv_clk_src_max) { +		u32 lo = pstate->base.domain[clock->name]; +		u32 hi = lo; +		if (hi == 0) +			continue; + +		nv_debug(clk, "%02x: %10d KHz\n", clock->name, lo); +		list_for_each_entry(cstate, &pstate->list, head) { +			u32 freq = cstate->domain[clock->name]; +			lo = min(lo, freq); +			hi = max(hi, freq); +			nv_debug(clk, "%10d KHz\n", freq); +		} + +		if (clock->mname && ++i < ARRAY_SIZE(info)) { +			lo /= clock->mdiv; +			hi /= clock->mdiv; +			if (lo == hi) { +				snprintf(info[i], sizeof(info[i]), "%s %d MHz", +					 clock->mname, lo); +			} else { +				snprintf(info[i], sizeof(info[i]), +					 "%s %d-%d MHz", clock->mname, lo, hi); +			} +		} +	} + +	nv_info(clk, "%s: %s %s %s\n", name, info[0], info[1], info[2]); +} + +static void +nouveau_pstate_del(struct nouveau_pstate *pstate) +{ +	struct nouveau_cstate *cstate, *temp; + +	list_for_each_entry_safe(cstate, temp, &pstate->list, head) { +		nouveau_cstate_del(cstate); +	} + +	list_del(&pstate->head); +	kfree(pstate); +} + +static int +nouveau_pstate_new(struct nouveau_clock *clk, int idx) +{ +	struct nouveau_bios *bios = nouveau_bios(clk); +	struct nouveau_clocks *domain = clk->domains - 1; +	struct nouveau_pstate *pstate; +	struct nouveau_cstate *cstate; +	struct nvbios_cstepE cstepE; +	struct nvbios_perfE perfE; +	u8  ver, hdr, cnt, len; +	u16 data; + +	data = nvbios_perfEp(bios, idx, &ver, &hdr, &cnt, &len, &perfE); +	if (!data) +		return -EINVAL; +	if (perfE.pstate == 0xff) +		return 0; + +	pstate = kzalloc(sizeof(*pstate), GFP_KERNEL); +	cstate = &pstate->base; +	if (!pstate) +		return -ENOMEM; + +	INIT_LIST_HEAD(&pstate->list); + +	pstate->pstate = perfE.pstate; +	pstate->fanspeed = perfE.fanspeed; +	cstate->voltage = perfE.voltage; +	cstate->domain[nv_clk_src_core] = perfE.core; +	cstate->domain[nv_clk_src_shader] = perfE.shader; +	cstate->domain[nv_clk_src_mem] = perfE.memory; +	cstate->domain[nv_clk_src_vdec] = perfE.vdec; +	cstate->domain[nv_clk_src_dom6] = perfE.disp; + +	while (ver >= 0x40 && (++domain)->name != nv_clk_src_max) { +		struct nvbios_perfS perfS; +		u8  sver = ver, shdr = hdr; +		u32 perfSe = nvbios_perfSp(bios, data, domain->bios, +					  &sver, &shdr, cnt, len, &perfS); +		if (perfSe == 0 || sver != 0x40) +			continue; + +		if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) { +			perfS.v40.freq = nouveau_clock_adjust(clk, false, +							      pstate->pstate, +							      domain->bios, +							      perfS.v40.freq); +		} + +		cstate->domain[domain->name] = perfS.v40.freq; +	} + +	data = nvbios_cstepEm(bios, pstate->pstate, &ver, &hdr, &cstepE); +	if (data) { +		int idx = cstepE.index; +		do { +			nouveau_cstate_new(clk, idx, pstate); +		} while(idx--); +	} + +	nouveau_pstate_info(clk, pstate); +	list_add_tail(&pstate->head, &clk->states); +	clk->state_nr++; +	return 0; +} + +/****************************************************************************** + * Adjustment triggers + *****************************************************************************/ +static int +nouveau_clock_ustate_update(struct nouveau_clock *clk, int req) +{ +	struct nouveau_pstate *pstate; +	int i = 0; + +	if (!clk->allow_reclock) +		return -ENOSYS; + +	if (req != -1 && req != -2) { +		list_for_each_entry(pstate, &clk->states, head) { +			if (pstate->pstate == req) +				break; +			i++; +		} + +		if (pstate->pstate != req) +			return -EINVAL; +		req = i; +	} + +	clk->ustate = req; +	return 0; +} + +int +nouveau_clock_ustate(struct nouveau_clock *clk, int req) +{ +	int ret = nouveau_clock_ustate_update(clk, req); +	if (ret) +		return ret; +	return nouveau_pstate_calc(clk); +} + +int +nouveau_clock_astate(struct nouveau_clock *clk, int req, int rel) +{ +	if (!rel) clk->astate  = req; +	if ( rel) clk->astate += rel; +	clk->astate = min(clk->astate, clk->state_nr - 1); +	clk->astate = max(clk->astate, 0); +	return nouveau_pstate_calc(clk); +} + +int +nouveau_clock_tstate(struct nouveau_clock *clk, int req, int rel) +{ +	if (!rel) clk->tstate  = req; +	if ( rel) clk->tstate += rel; +	clk->tstate = min(clk->tstate, 0); +	clk->tstate = max(clk->tstate, -(clk->state_nr - 1)); +	return nouveau_pstate_calc(clk); +} + +int +nouveau_clock_dstate(struct nouveau_clock *clk, int req, int rel) +{ +	if (!rel) clk->dstate  = req; +	if ( rel) clk->dstate += rel; +	clk->dstate = min(clk->dstate, clk->state_nr - 1); +	clk->dstate = max(clk->dstate, 0); +	return nouveau_pstate_calc(clk); +} + +/****************************************************************************** + * subdev base class implementation + *****************************************************************************/ +int +_nouveau_clock_init(struct nouveau_object *object) +{ +	struct nouveau_clock *clk = (void *)object; +	struct nouveau_clocks *clock = clk->domains; +	int ret; + +	memset(&clk->bstate, 0x00, sizeof(clk->bstate)); +	INIT_LIST_HEAD(&clk->bstate.list); +	clk->bstate.pstate = 0xff; + +	while (clock->name != nv_clk_src_max) { +		ret = clk->read(clk, clock->name); +		if (ret < 0) { +			nv_error(clk, "%02x freq unknown\n", clock->name); +			return ret; +		} +		clk->bstate.base.domain[clock->name] = ret; +		clock++; +	} + +	nouveau_pstate_info(clk, &clk->bstate); + +	clk->astate = clk->state_nr - 1; +	clk->tstate = 0; +	clk->dstate = 0; +	clk->pstate = -1; +	nouveau_pstate_calc(clk); +	return 0; +} + +void +_nouveau_clock_dtor(struct nouveau_object *object) +{ +	struct nouveau_clock *clk = (void *)object; +	struct nouveau_pstate *pstate, *temp; + +	list_for_each_entry_safe(pstate, temp, &clk->states, head) { +		nouveau_pstate_del(pstate); +	} + +	nouveau_subdev_destroy(&clk->base); +} + +int +nouveau_clock_create_(struct nouveau_object *parent, +		      struct nouveau_object *engine, +		      struct nouveau_oclass *oclass, +		      struct nouveau_clocks *clocks, +		      bool allow_reclock, +		      int length, void **object) +{ +	struct nouveau_device *device = nv_device(parent); +	struct nouveau_clock *clk; +	int ret, idx, arglen; +	const char *mode; + +	ret = nouveau_subdev_create_(parent, engine, oclass, 0, "CLK", +				     "clock", length, object); +	clk = *object; +	if (ret) +		return ret; + +	INIT_LIST_HEAD(&clk->states); +	clk->domains = clocks; +	clk->ustate = -1; + +	idx = 0; +	do { +		ret = nouveau_pstate_new(clk, idx++); +	} while (ret == 0); + +	clk->allow_reclock = allow_reclock; + +	mode = nouveau_stropt(device->cfgopt, "NvClkMode", &arglen); +	if (mode) { +		if (!strncasecmpz(mode, "disabled", arglen)) { +			clk->ustate = -1; +		} else { +			char save = mode[arglen]; +			long v; + +			((char *)mode)[arglen] = '\0'; +			if (!kstrtol(mode, 0, &v)) +				nouveau_clock_ustate_update(clk, v); +			((char *)mode)[arglen] = save; +		} +	} + +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c index a1427758659..eb2d4425a49 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv04.c @@ -25,7 +25,7 @@  #include <subdev/bios.h>  #include <subdev/bios/pll.h>  #include <subdev/clock.h> -#include <subdev/devinit/priv.h> +#include <subdev/devinit/nv04.h>  #include "pll.h" @@ -69,6 +69,11 @@ nv04_clock_pll_prog(struct nouveau_clock *clk, u32 reg1,  	return 0;  } +static struct nouveau_clocks +nv04_domain[] = { +	{ nv_clk_src_max } +}; +  static int  nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_oclass *oclass, void *data, u32 size, @@ -77,7 +82,8 @@ nv04_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nv04_clock_priv *priv;  	int ret; -	ret = nouveau_clock_create(parent, engine, oclass, &priv); +	ret = nouveau_clock_create(parent, engine, oclass, nv04_domain, false, +				   &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c index 0db5dbfd91b..8a9e1683979 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv40.c @@ -23,11 +23,188 @@   */  #include <subdev/clock.h> +#include <subdev/bios.h> +#include <subdev/bios/pll.h> + +#include "pll.h"  struct nv40_clock_priv {  	struct nouveau_clock base; +	u32 ctrl; +	u32 npll_ctrl; +	u32 npll_coef; +	u32 spll; +}; + +static struct nouveau_clocks +nv40_domain[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_core   , 0xff, 0, "core", 1000 }, +	{ nv_clk_src_shader , 0xff, 0, "shader", 1000 }, +	{ nv_clk_src_mem    , 0xff, 0, "memory", 1000 }, +	{ nv_clk_src_max }  }; +static u32 +read_pll_1(struct nv40_clock_priv *priv, u32 reg) +{ +	u32 ctrl = nv_rd32(priv, reg + 0x00); +	int P = (ctrl & 0x00070000) >> 16; +	int N = (ctrl & 0x0000ff00) >> 8; +	int M = (ctrl & 0x000000ff) >> 0; +	u32 ref = 27000, clk = 0; + +	if (ctrl & 0x80000000) +		clk = ref * N / M; + +	return clk >> P; +} + +static u32 +read_pll_2(struct nv40_clock_priv *priv, u32 reg) +{ +	u32 ctrl = nv_rd32(priv, reg + 0x00); +	u32 coef = nv_rd32(priv, reg + 0x04); +	int N2 = (coef & 0xff000000) >> 24; +	int M2 = (coef & 0x00ff0000) >> 16; +	int N1 = (coef & 0x0000ff00) >> 8; +	int M1 = (coef & 0x000000ff) >> 0; +	int P = (ctrl & 0x00070000) >> 16; +	u32 ref = 27000, clk = 0; + +	if ((ctrl & 0x80000000) && M1) { +		clk = ref * N1 / M1; +		if ((ctrl & 0x40000100) == 0x40000000) { +			if (M2) +				clk = clk * N2 / M2; +			else +				clk = 0; +		} +	} + +	return clk >> P; +} + +static u32 +read_clk(struct nv40_clock_priv *priv, u32 src) +{ +	switch (src) { +	case 3: +		return read_pll_2(priv, 0x004000); +	case 2: +		return read_pll_1(priv, 0x004008); +	default: +		break; +	} + +	return 0; +} + +static int +nv40_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ +	struct nv40_clock_priv *priv = (void *)clk; +	u32 mast = nv_rd32(priv, 0x00c040); + +	switch (src) { +	case nv_clk_src_crystal: +		return nv_device(priv)->crystal; +	case nv_clk_src_href: +		return 100000; /*XXX: PCIE/AGP differ*/ +	case nv_clk_src_core: +		return read_clk(priv, (mast & 0x00000003) >> 0); +	case nv_clk_src_shader: +		return read_clk(priv, (mast & 0x00000030) >> 4); +	case nv_clk_src_mem: +		return read_pll_2(priv, 0x4020); +	default: +		break; +	} + +	nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); +	return -EINVAL; +} + +static int +nv40_clock_calc_pll(struct nv40_clock_priv *priv, u32 reg, u32 clk, +		    int *N1, int *M1, int *N2, int *M2, int *log2P) +{ +	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvbios_pll pll; +	int ret; + +	ret = nvbios_pll_parse(bios, reg, &pll); +	if (ret) +		return ret; + +	if (clk < pll.vco1.max_freq) +		pll.vco2.max_freq = 0; + +	ret = nv04_pll_calc(nv_subdev(priv), &pll, clk, N1, M1, N2, M2, log2P); +	if (ret == 0) +		return -ERANGE; +	return ret; +} + +static int +nv40_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ +	struct nv40_clock_priv *priv = (void *)clk; +	int gclk = cstate->domain[nv_clk_src_core]; +	int sclk = cstate->domain[nv_clk_src_shader]; +	int N1, M1, N2, M2, log2P; +	int ret; + +	/* core/geometric clock */ +	ret = nv40_clock_calc_pll(priv, 0x004000, gclk, +				 &N1, &M1, &N2, &M2, &log2P); +	if (ret < 0) +		return ret; + +	if (N2 == M2) { +		priv->npll_ctrl = 0x80000100 | (log2P << 16); +		priv->npll_coef = (N1 << 8) | M1; +	} else { +		priv->npll_ctrl = 0xc0000000 | (log2P << 16); +		priv->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; +	} + +	/* use the second pll for shader/rop clock, if it differs from core */ +	if (sclk && sclk != gclk) { +		ret = nv40_clock_calc_pll(priv, 0x004008, sclk, +					 &N1, &M1, NULL, NULL, &log2P); +		if (ret < 0) +			return ret; + +		priv->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; +		priv->ctrl = 0x00000223; +	} else { +		priv->spll = 0x00000000; +		priv->ctrl = 0x00000333; +	} + +	return 0; +} + +static int +nv40_clock_prog(struct nouveau_clock *clk) +{ +	struct nv40_clock_priv *priv = (void *)clk; +	nv_mask(priv, 0x00c040, 0x00000333, 0x00000000); +	nv_wr32(priv, 0x004004, priv->npll_coef); +	nv_mask(priv, 0x004000, 0xc0070100, priv->npll_ctrl); +	nv_mask(priv, 0x004008, 0xc007ffff, priv->spll); +	mdelay(5); +	nv_mask(priv, 0x00c040, 0x00000333, priv->ctrl); +	return 0; +} + +static void +nv40_clock_tidy(struct nouveau_clock *clk) +{ +} +  static int  nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_oclass *oclass, void *data, u32 size, @@ -36,13 +213,18 @@ nv40_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nv40_clock_priv *priv;  	int ret; -	ret = nouveau_clock_create(parent, engine, oclass, &priv); +	ret = nouveau_clock_create(parent, engine, oclass, nv40_domain, true, +				   &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret;  	priv->base.pll_calc = nv04_clock_pll_calc;  	priv->base.pll_prog = nv04_clock_pll_prog; +	priv->base.read = nv40_clock_read; +	priv->base.calc = nv40_clock_calc; +	priv->base.prog = nv40_clock_prog; +	priv->base.tidy = nv40_clock_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c index d09d3e78040..8c132772ba9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.c @@ -22,40 +22,538 @@   * Authors: Ben Skeggs   */ -#include <subdev/clock.h>  #include <subdev/bios.h>  #include <subdev/bios/pll.h> +#include "nv50.h"  #include "pll.h" +#include "seq.h" -struct nv50_clock_priv { -	struct nouveau_clock base; -}; +static u32 +read_div(struct nv50_clock_priv *priv) +{ +	switch (nv_device(priv)->chipset) { +	case 0x50: /* it exists, but only has bit 31, not the dividers.. */ +	case 0x84: +	case 0x86: +	case 0x98: +	case 0xa0: +		return nv_rd32(priv, 0x004700); +	case 0x92: +	case 0x94: +	case 0x96: +		return nv_rd32(priv, 0x004800); +	default: +		return 0x00000000; +	} +} + +static u32 +read_pll_src(struct nv50_clock_priv *priv, u32 base) +{ +	struct nouveau_clock *clk = &priv->base; +	u32 coef, ref = clk->read(clk, nv_clk_src_crystal); +	u32 rsel = nv_rd32(priv, 0x00e18c); +	int P, N, M, id; + +	switch (nv_device(priv)->chipset) { +	case 0x50: +	case 0xa0: +		switch (base) { +		case 0x4020: +		case 0x4028: id = !!(rsel & 0x00000004); break; +		case 0x4008: id = !!(rsel & 0x00000008); break; +		case 0x4030: id = 0; break; +		default: +			nv_error(priv, "ref: bad pll 0x%06x\n", base); +			return 0; +		} + +		coef = nv_rd32(priv, 0x00e81c + (id * 0x0c)); +		ref *=  (coef & 0x01000000) ? 2 : 4; +		P    =  (coef & 0x00070000) >> 16; +		N    = ((coef & 0x0000ff00) >> 8) + 1; +		M    = ((coef & 0x000000ff) >> 0) + 1; +		break; +	case 0x84: +	case 0x86: +	case 0x92: +		coef = nv_rd32(priv, 0x00e81c); +		P    = (coef & 0x00070000) >> 16; +		N    = (coef & 0x0000ff00) >> 8; +		M    = (coef & 0x000000ff) >> 0; +		break; +	case 0x94: +	case 0x96: +	case 0x98: +		rsel = nv_rd32(priv, 0x00c050); +		switch (base) { +		case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; +		case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; +		case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; +		case 0x4030: rsel = 3; break; +		default: +			nv_error(priv, "ref: bad pll 0x%06x\n", base); +			return 0; +		} + +		switch (rsel) { +		case 0: id = 1; break; +		case 1: return clk->read(clk, nv_clk_src_crystal); +		case 2: return clk->read(clk, nv_clk_src_href); +		case 3: id = 0; break; +		} + +		coef =  nv_rd32(priv, 0x00e81c + (id * 0x28)); +		P    = (nv_rd32(priv, 0x00e824 + (id * 0x28)) >> 16) & 7; +		P   += (coef & 0x00070000) >> 16; +		N    = (coef & 0x0000ff00) >> 8; +		M    = (coef & 0x000000ff) >> 0; +		break; +	default: +		BUG_ON(1); +	} + +	if (M) +		return (ref * N / M) >> P; +	return 0; +} + +static u32 +read_pll_ref(struct nv50_clock_priv *priv, u32 base) +{ +	struct nouveau_clock *clk = &priv->base; +	u32 src, mast = nv_rd32(priv, 0x00c040); + +	switch (base) { +	case 0x004028: +		src = !!(mast & 0x00200000); +		break; +	case 0x004020: +		src = !!(mast & 0x00400000); +		break; +	case 0x004008: +		src = !!(mast & 0x00010000); +		break; +	case 0x004030: +		src = !!(mast & 0x02000000); +		break; +	case 0x00e810: +		return clk->read(clk, nv_clk_src_crystal); +	default: +		nv_error(priv, "bad pll 0x%06x\n", base); +		return 0; +	} + +	if (src) +		return clk->read(clk, nv_clk_src_href); +	return read_pll_src(priv, base); +} + +static u32 +read_pll(struct nv50_clock_priv *priv, u32 base) +{ +	struct nouveau_clock *clk = &priv->base; +	u32 mast = nv_rd32(priv, 0x00c040); +	u32 ctrl = nv_rd32(priv, base + 0); +	u32 coef = nv_rd32(priv, base + 4); +	u32 ref = read_pll_ref(priv, base); +	u32 freq = 0; +	int N1, N2, M1, M2; + +	if (base == 0x004028 && (mast & 0x00100000)) { +		/* wtf, appears to only disable post-divider on nva0 */ +		if (nv_device(priv)->chipset != 0xa0) +			return clk->read(clk, nv_clk_src_dom6); +	} + +	N2 = (coef & 0xff000000) >> 24; +	M2 = (coef & 0x00ff0000) >> 16; +	N1 = (coef & 0x0000ff00) >> 8; +	M1 = (coef & 0x000000ff); +	if ((ctrl & 0x80000000) && M1) { +		freq = ref * N1 / M1; +		if ((ctrl & 0x40000100) == 0x40000000) { +			if (M2) +				freq = freq * N2 / M2; +			else +				freq = 0; +		} +	} + +	return freq; +}  static int +nv50_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ +	struct nv50_clock_priv *priv = (void *)clk; +	u32 mast = nv_rd32(priv, 0x00c040); +	u32 P = 0; + +	switch (src) { +	case nv_clk_src_crystal: +		return nv_device(priv)->crystal; +	case nv_clk_src_href: +		return 100000; /* PCIE reference clock */ +	case nv_clk_src_hclk: +		return div_u64((u64)clk->read(clk, nv_clk_src_href) * 27778, 10000); +	case nv_clk_src_hclkm3: +		return clk->read(clk, nv_clk_src_hclk) * 3; +	case nv_clk_src_hclkm3d2: +		return clk->read(clk, nv_clk_src_hclk) * 3 / 2; +	case nv_clk_src_host: +		switch (mast & 0x30000000) { +		case 0x00000000: return clk->read(clk, nv_clk_src_href); +		case 0x10000000: break; +		case 0x20000000: /* !0x50 */ +		case 0x30000000: return clk->read(clk, nv_clk_src_hclk); +		} +		break; +	case nv_clk_src_core: +		if (!(mast & 0x00100000)) +			P = (nv_rd32(priv, 0x004028) & 0x00070000) >> 16; +		switch (mast & 0x00000003) { +		case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P; +		case 0x00000001: return clk->read(clk, nv_clk_src_dom6); +		case 0x00000002: return read_pll(priv, 0x004020) >> P; +		case 0x00000003: return read_pll(priv, 0x004028) >> P; +		} +		break; +	case nv_clk_src_shader: +		P = (nv_rd32(priv, 0x004020) & 0x00070000) >> 16; +		switch (mast & 0x00000030) { +		case 0x00000000: +			if (mast & 0x00000080) +				return clk->read(clk, nv_clk_src_host) >> P; +			return clk->read(clk, nv_clk_src_crystal) >> P; +		case 0x00000010: break; +		case 0x00000020: return read_pll(priv, 0x004028) >> P; +		case 0x00000030: return read_pll(priv, 0x004020) >> P; +		} +		break; +	case nv_clk_src_mem: +		P = (nv_rd32(priv, 0x004008) & 0x00070000) >> 16; +		if (nv_rd32(priv, 0x004008) & 0x00000200) { +			switch (mast & 0x0000c000) { +			case 0x00000000: +				return clk->read(clk, nv_clk_src_crystal) >> P; +			case 0x00008000: +			case 0x0000c000: +				return clk->read(clk, nv_clk_src_href) >> P; +			} +		} else { +			return read_pll(priv, 0x004008) >> P; +		} +		break; +	case nv_clk_src_vdec: +		P = (read_div(priv) & 0x00000700) >> 8; +		switch (nv_device(priv)->chipset) { +		case 0x84: +		case 0x86: +		case 0x92: +		case 0x94: +		case 0x96: +		case 0xa0: +			switch (mast & 0x00000c00) { +			case 0x00000000: +				if (nv_device(priv)->chipset == 0xa0) /* wtf?? */ +					return clk->read(clk, nv_clk_src_core) >> P; +				return clk->read(clk, nv_clk_src_crystal) >> P; +			case 0x00000400: +				return 0; +			case 0x00000800: +				if (mast & 0x01000000) +					return read_pll(priv, 0x004028) >> P; +				return read_pll(priv, 0x004030) >> P; +			case 0x00000c00: +				return clk->read(clk, nv_clk_src_core) >> P; +			} +			break; +		case 0x98: +			switch (mast & 0x00000c00) { +			case 0x00000000: +				return clk->read(clk, nv_clk_src_core) >> P; +			case 0x00000400: +				return 0; +			case 0x00000800: +				return clk->read(clk, nv_clk_src_hclkm3d2) >> P; +			case 0x00000c00: +				return clk->read(clk, nv_clk_src_mem) >> P; +			} +			break; +		} +		break; +	case nv_clk_src_dom6: +		switch (nv_device(priv)->chipset) { +		case 0x50: +		case 0xa0: +			return read_pll(priv, 0x00e810) >> 2; +		case 0x84: +		case 0x86: +		case 0x92: +		case 0x94: +		case 0x96: +		case 0x98: +			P = (read_div(priv) & 0x00000007) >> 0; +			switch (mast & 0x0c000000) { +			case 0x00000000: return clk->read(clk, nv_clk_src_href); +			case 0x04000000: break; +			case 0x08000000: return clk->read(clk, nv_clk_src_hclk); +			case 0x0c000000: +				return clk->read(clk, nv_clk_src_hclkm3) >> P; +			} +			break; +		default: +			break; +		} +	default: +		break; +	} + +	nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); +	return -EINVAL; +} + +static u32 +calc_pll(struct nv50_clock_priv *priv, u32 reg, u32 clk, int *N, int *M, int *P) +{ +	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvbios_pll pll; +	int ret; + +	ret = nvbios_pll_parse(bios, reg, &pll); +	if (ret) +		return 0; + +	pll.vco2.max_freq = 0; +	pll.refclk = read_pll_ref(priv, reg); +	if (!pll.refclk) +		return 0; + +	return nv04_pll_calc(nv_subdev(priv), &pll, clk, N, M, NULL, NULL, P); +} + +static inline u32 +calc_div(u32 src, u32 target, int *div) +{ +	u32 clk0 = src, clk1 = src; +	for (*div = 0; *div <= 7; (*div)++) { +		if (clk0 <= target) { +			clk1 = clk0 << (*div ? 1 : 0); +			break; +		} +		clk0 >>= 1; +	} + +	if (target - clk0 <= clk1 - target) +		return clk0; +	(*div)--; +	return clk1; +} + +static inline u32 +clk_same(u32 a, u32 b) +{ +	return ((a / 1000) == (b / 1000)); +} + +static int +nv50_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ +	struct nv50_clock_priv *priv = (void *)clk; +	struct nv50_clock_hwsq *hwsq = &priv->hwsq; +	const int shader = cstate->domain[nv_clk_src_shader]; +	const int core = cstate->domain[nv_clk_src_core]; +	const int vdec = cstate->domain[nv_clk_src_vdec]; +	const int dom6 = cstate->domain[nv_clk_src_dom6]; +	u32 mastm = 0, mastv = 0; +	u32 divsm = 0, divsv = 0; +	int N, M, P1, P2; +	int freq, out; + +	/* prepare a hwsq script from which we'll perform the reclock */ +	out = clk_init(hwsq, nv_subdev(clk)); +	if (out) +		return out; + +	clk_wr32(hwsq, fifo, 0x00000001); /* block fifo */ +	clk_nsec(hwsq, 8000); +	clk_setf(hwsq, 0x10, 0x00); /* disable fb */ +	clk_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ + +	/* vdec: avoid modifying xpll until we know exactly how the other +	 * clock domains work, i suspect at least some of them can also be +	 * tied to xpll... +	 */ +	if (vdec) { +		/* see how close we can get using nvclk as a source */ +		freq = calc_div(core, vdec, &P1); + +		/* see how close we can get using xpll/hclk as a source */ +		if (nv_device(priv)->chipset != 0x98) +			out = read_pll(priv, 0x004030); +		else +			out = clk->read(clk, nv_clk_src_hclkm3d2); +		out = calc_div(out, vdec, &P2); + +		/* select whichever gets us closest */ +		if (abs(vdec - freq) <= abs(vdec - out)) { +			if (nv_device(priv)->chipset != 0x98) +				mastv |= 0x00000c00; +			divsv |= P1 << 8; +		} else { +			mastv |= 0x00000800; +			divsv |= P2 << 8; +		} + +		mastm |= 0x00000c00; +		divsm |= 0x00000700; +	} + +	/* dom6: nfi what this is, but we're limited to various combinations +	 * of the host clock frequency +	 */ +	if (dom6) { +		if (clk_same(dom6, clk->read(clk, nv_clk_src_href))) { +			mastv |= 0x00000000; +		} else +		if (clk_same(dom6, clk->read(clk, nv_clk_src_hclk))) { +			mastv |= 0x08000000; +		} else { +			freq = clk->read(clk, nv_clk_src_hclk) * 3; +			freq = calc_div(freq, dom6, &P1); + +			mastv |= 0x0c000000; +			divsv |= P1; +		} + +		mastm |= 0x0c000000; +		divsm |= 0x00000007; +	} + +	/* vdec/dom6: switch to "safe" clocks temporarily, update dividers +	 * and then switch to target clocks +	 */ +	clk_mask(hwsq, mast, mastm, 0x00000000); +	clk_mask(hwsq, divs, divsm, divsv); +	clk_mask(hwsq, mast, mastm, mastv); + +	/* core/shader: disconnect nvclk/sclk from their PLLs (nvclk to dom6, +	 * sclk to hclk) before reprogramming +	 */ +	if (nv_device(priv)->chipset < 0x92) +		clk_mask(hwsq, mast, 0x001000b0, 0x00100080); +	else +		clk_mask(hwsq, mast, 0x000000b3, 0x00000081); + +	/* core: for the moment at least, always use nvpll */ +	freq = calc_pll(priv, 0x4028, core, &N, &M, &P1); +	if (freq == 0) +		return -ERANGE; + +	clk_mask(hwsq, nvpll[0], 0xc03f0100, +				 0x80000000 | (P1 << 19) | (P1 << 16)); +	clk_mask(hwsq, nvpll[1], 0x0000ffff, (N << 8) | M); + +	/* shader: tie to nvclk if possible, otherwise use spll.  have to be +	 * very careful that the shader clock is at least twice the core, or +	 * some chipsets will be very unhappy.  i expect most or all of these +	 * cases will be handled by tying to nvclk, but it's possible there's +	 * corners +	 */ +	if (P1-- && shader == (core << 1)) { +		clk_mask(hwsq, spll[0], 0xc03f0100, (P1 << 19) | (P1 << 16)); +		clk_mask(hwsq, mast, 0x00100033, 0x00000023); +	} else { +		freq = calc_pll(priv, 0x4020, shader, &N, &M, &P1); +		if (freq == 0) +			return -ERANGE; + +		clk_mask(hwsq, spll[0], 0xc03f0100, +					0x80000000 | (P1 << 19) | (P1 << 16)); +		clk_mask(hwsq, spll[1], 0x0000ffff, (N << 8) | M); +		clk_mask(hwsq, mast, 0x00100033, 0x00000033); +	} + +	/* restore normal operation */ +	clk_setf(hwsq, 0x10, 0x01); /* enable fb */ +	clk_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */ +	clk_wr32(hwsq, fifo, 0x00000000); /* un-block fifo */ +	return 0; +} + +static int +nv50_clock_prog(struct nouveau_clock *clk) +{ +	struct nv50_clock_priv *priv = (void *)clk; +	return clk_exec(&priv->hwsq, true); +} + +static void +nv50_clock_tidy(struct nouveau_clock *clk) +{ +	struct nv50_clock_priv *priv = (void *)clk; +	clk_exec(&priv->hwsq, false); +} + +int  nv50_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_oclass *oclass, void *data, u32 size,  		struct nouveau_object **pobject)  { +	struct nv50_clock_oclass *pclass = (void *)oclass;  	struct nv50_clock_priv *priv;  	int ret; -	ret = nouveau_clock_create(parent, engine, oclass, &priv); +	ret = nouveau_clock_create(parent, engine, oclass, pclass->domains, +				   false, &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; -	priv->base.pll_calc = nv04_clock_pll_calc; +	priv->hwsq.r_fifo = hwsq_reg(0x002504); +	priv->hwsq.r_spll[0] = hwsq_reg(0x004020); +	priv->hwsq.r_spll[1] = hwsq_reg(0x004024); +	priv->hwsq.r_nvpll[0] = hwsq_reg(0x004028); +	priv->hwsq.r_nvpll[1] = hwsq_reg(0x00402c); +	switch (nv_device(priv)->chipset) { +	case 0x92: +	case 0x94: +	case 0x96: +		priv->hwsq.r_divs = hwsq_reg(0x004800); +		break; +	default: +		priv->hwsq.r_divs = hwsq_reg(0x004700); +		break; +	} +	priv->hwsq.r_mast = hwsq_reg(0x00c040); + +	priv->base.read = nv50_clock_read; +	priv->base.calc = nv50_clock_calc; +	priv->base.prog = nv50_clock_prog; +	priv->base.tidy = nv50_clock_tidy;  	return 0;  } -struct nouveau_oclass -nv50_clock_oclass = { -	.handle = NV_SUBDEV(CLOCK, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +static struct nouveau_clocks +nv50_domains[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_core   , 0xff, 0, "core", 1000 }, +	{ nv_clk_src_shader , 0xff, 0, "shader", 1000 }, +	{ nv_clk_src_mem    , 0xff, 0, "memory", 1000 }, +	{ nv_clk_src_max } +}; + +struct nouveau_oclass * +nv50_clock_oclass = &(struct nv50_clock_oclass) { +	.base.handle = NV_SUBDEV(CLOCK, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_clock_ctor,  		.dtor = _nouveau_clock_dtor,  		.init = _nouveau_clock_init,  		.fini = _nouveau_clock_fini,  	}, -}; +	.domains = nv50_domains, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.h new file mode 100644 index 00000000000..f10917d789e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv50.h @@ -0,0 +1,31 @@ +#ifndef __NVKM_CLK_NV50_H__ +#define __NVKM_CLK_NV50_H__ + +#include <subdev/bus.h> +#include <subdev/bus/hwsq.h> +#include <subdev/clock.h> + +struct nv50_clock_hwsq { +	struct hwsq base; +	struct hwsq_reg r_fifo; +	struct hwsq_reg r_spll[2]; +	struct hwsq_reg r_nvpll[2]; +	struct hwsq_reg r_divs; +	struct hwsq_reg r_mast; +}; + +struct nv50_clock_priv { +	struct nouveau_clock base; +	struct nv50_clock_hwsq hwsq; +}; + +int  nv50_clock_ctor(struct nouveau_object *, struct nouveau_object *, +		     struct nouveau_oclass *, void *, u32, +		     struct nouveau_object **); + +struct nv50_clock_oclass { +	struct nouveau_oclass base; +	struct nouveau_clocks *domains; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nv84.c new file mode 100644 index 00000000000..b0b7c1437f1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nv84.c @@ -0,0 +1,48 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include "nv50.h" + +static struct nouveau_clocks +nv84_domains[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_core   , 0xff, 0, "core", 1000 }, +	{ nv_clk_src_shader , 0xff, 0, "shader", 1000 }, +	{ nv_clk_src_mem    , 0xff, 0, "memory", 1000 }, +	{ nv_clk_src_vdec   , 0xff }, +	{ nv_clk_src_max } +}; + +struct nouveau_oclass * +nv84_clock_oclass = &(struct nv50_clock_oclass) { +	.base.handle = NV_SUBDEV(CLOCK, 0x84), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_clock_ctor, +		.dtor = _nouveau_clock_dtor, +		.init = _nouveau_clock_init, +		.fini = _nouveau_clock_fini, +	}, +	.domains = nv84_domains, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index f074cd20bc9..9fb58354a80 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -22,33 +22,277 @@   * Authors: Ben Skeggs   */ -#include <subdev/clock.h>  #include <subdev/bios.h>  #include <subdev/bios/pll.h> +#include <subdev/timer.h>  #include "pll.h" +#include "nva3.h" +  struct nva3_clock_priv {  	struct nouveau_clock base; +	struct nva3_clock_info eng[nv_clk_src_max];  }; +static u32 read_clk(struct nva3_clock_priv *, int, bool); +static u32 read_pll(struct nva3_clock_priv *, int, u32); + +static u32 +read_vco(struct nva3_clock_priv *priv, int clk) +{ +	u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4)); +	if ((sctl & 0x00000030) != 0x00000030) +		return read_pll(priv, 0x41, 0x00e820); +	return read_pll(priv, 0x42, 0x00e8a0); +} + +static u32 +read_clk(struct nva3_clock_priv *priv, int clk, bool ignore_en) +{ +	u32 sctl, sdiv, sclk; + +	/* refclk for the 0xe8xx plls is a fixed frequency */ +	if (clk >= 0x40) { +		if (nv_device(priv)->chipset == 0xaf) { +			/* no joke.. seriously.. sigh.. */ +			return nv_rd32(priv, 0x00471c) * 1000; +		} + +		return nv_device(priv)->crystal; +	} + +	sctl = nv_rd32(priv, 0x4120 + (clk * 4)); +	if (!ignore_en && !(sctl & 0x00000100)) +		return 0; + +	switch (sctl & 0x00003000) { +	case 0x00000000: +		return nv_device(priv)->crystal; +	case 0x00002000: +		if (sctl & 0x00000040) +			return 108000; +		return 100000; +	case 0x00003000: +		sclk = read_vco(priv, clk); +		sdiv = ((sctl & 0x003f0000) >> 16) + 2; +		return (sclk * 2) / sdiv; +	default: +		return 0; +	} +} + +static u32 +read_pll(struct nva3_clock_priv *priv, int clk, u32 pll) +{ +	u32 ctrl = nv_rd32(priv, pll + 0); +	u32 sclk = 0, P = 1, N = 1, M = 1; + +	if (!(ctrl & 0x00000008)) { +		if (ctrl & 0x00000001) { +			u32 coef = nv_rd32(priv, pll + 4); +			M = (coef & 0x000000ff) >> 0; +			N = (coef & 0x0000ff00) >> 8; +			P = (coef & 0x003f0000) >> 16; + +			/* no post-divider on these.. */ +			if ((pll & 0x00ff00) == 0x00e800) +				P = 1; + +			sclk = read_clk(priv, 0x00 + clk, false); +		} +	} else { +		sclk = read_clk(priv, 0x10 + clk, false); +	} + +	if (M * P) +		return sclk * N / (M * P); +	return 0; +} + +static int +nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ +	struct nva3_clock_priv *priv = (void *)clk; + +	switch (src) { +	case nv_clk_src_crystal: +		return nv_device(priv)->crystal; +	case nv_clk_src_href: +		return 100000; +	case nv_clk_src_core: +		return read_pll(priv, 0x00, 0x4200); +	case nv_clk_src_shader: +		return read_pll(priv, 0x01, 0x4220); +	case nv_clk_src_mem: +		return read_pll(priv, 0x02, 0x4000); +	case nv_clk_src_disp: +		return read_clk(priv, 0x20, false); +	case nv_clk_src_vdec: +		return read_clk(priv, 0x21, false); +	case nv_clk_src_daemon: +		return read_clk(priv, 0x25, false); +	default: +		nv_error(clk, "invalid clock source %d\n", src); +		return -EINVAL; +	} +} +  int -nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, -		    int clk, struct nouveau_pll_vals *pv) +nva3_clock_info(struct nouveau_clock *clock, int clk, u32 pll, u32 khz, +		struct nva3_clock_info *info)  { -	int ret, N, M, P; +	struct nouveau_bios *bios = nouveau_bios(clock); +	struct nva3_clock_priv *priv = (void *)clock; +	struct nvbios_pll limits; +	u32 oclk, sclk, sdiv; +	int P, N, M, diff; +	int ret; + +	info->pll = 0; +	info->clk = 0; + +	switch (khz) { +	case 27000: +		info->clk = 0x00000100; +		return khz; +	case 100000: +		info->clk = 0x00002100; +		return khz; +	case 108000: +		info->clk = 0x00002140; +		return khz; +	default: +		sclk = read_vco(priv, clk); +		sdiv = min((sclk * 2) / (khz - 2999), (u32)65); +		/* if the clock has a PLL attached, and we can get a within +		 * [-2, 3) MHz of a divider, we'll disable the PLL and use +		 * the divider instead. +		 * +		 * divider can go as low as 2, limited here because NVIDIA +		 * and the VBIOS on my NVA8 seem to prefer using the PLL +		 * for 810MHz - is there a good reason? +		 */ +		if (sdiv > 4) { +			oclk = (sclk * 2) / sdiv; +			diff = khz - oclk; +			if (!pll || (diff >= -2000 && diff < 3000)) { +				info->clk = (((sdiv - 2) << 16) | 0x00003100); +				return oclk; +			} +		} + +		if (!pll) +			return -ERANGE; +		break; +	} -	ret = nva3_pll_calc(nv_subdev(clock), info, clk, &N, NULL, &M, &P); +	ret = nvbios_pll_parse(bios, pll, &limits); +	if (ret) +		return ret; + +	limits.refclk = read_clk(priv, clk - 0x10, true); +	if (!limits.refclk) +		return -EINVAL; -	if (ret > 0) { -		pv->refclk = info->refclk; -		pv->N1 = N; -		pv->M1 = M; -		pv->log2P = P; +	ret = nva3_pll_calc(nv_subdev(priv), &limits, khz, &N, NULL, &M, &P); +	if (ret >= 0) { +		info->clk = nv_rd32(priv, 0x4120 + (clk * 4)); +		info->pll = (P << 16) | (N << 8) | M;  	} + +	return ret ? ret : -ERANGE; +} + +static int +calc_clk(struct nva3_clock_priv *priv, struct nouveau_cstate *cstate, +	 int clk, u32 pll, int idx) +{ +	int ret = nva3_clock_info(&priv->base, clk, pll, cstate->domain[idx], +				  &priv->eng[idx]); +	if (ret >= 0) +		return 0;  	return ret;  } +static void +prog_pll(struct nva3_clock_priv *priv, int clk, u32 pll, int idx) +{ +	struct nva3_clock_info *info = &priv->eng[idx]; +	const u32 src0 = 0x004120 + (clk * 4); +	const u32 src1 = 0x004160 + (clk * 4); +	const u32 ctrl = pll + 0; +	const u32 coef = pll + 4; + +	if (info->pll) { +		nv_mask(priv, src0, 0x00000101, 0x00000101); +		nv_wr32(priv, coef, info->pll); +		nv_mask(priv, ctrl, 0x00000015, 0x00000015); +		nv_mask(priv, ctrl, 0x00000010, 0x00000000); +		nv_wait(priv, ctrl, 0x00020000, 0x00020000); +		nv_mask(priv, ctrl, 0x00000010, 0x00000010); +		nv_mask(priv, ctrl, 0x00000008, 0x00000000); +		nv_mask(priv, src1, 0x00000100, 0x00000000); +		nv_mask(priv, src1, 0x00000001, 0x00000000); +	} else { +		nv_mask(priv, src1, 0x003f3141, 0x00000101 | info->clk); +		nv_mask(priv, ctrl, 0x00000018, 0x00000018); +		udelay(20); +		nv_mask(priv, ctrl, 0x00000001, 0x00000000); +		nv_mask(priv, src0, 0x00000100, 0x00000000); +		nv_mask(priv, src0, 0x00000001, 0x00000000); +	} +} + +static void +prog_clk(struct nva3_clock_priv *priv, int clk, int idx) +{ +	struct nva3_clock_info *info = &priv->eng[idx]; +	nv_mask(priv, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | info->clk); +} + +static int +nva3_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ +	struct nva3_clock_priv *priv = (void *)clk; +	int ret; + +	if ((ret = calc_clk(priv, cstate, 0x10, 0x4200, nv_clk_src_core)) || +	    (ret = calc_clk(priv, cstate, 0x11, 0x4220, nv_clk_src_shader)) || +	    (ret = calc_clk(priv, cstate, 0x20, 0x0000, nv_clk_src_disp)) || +	    (ret = calc_clk(priv, cstate, 0x21, 0x0000, nv_clk_src_vdec))) +		return ret; + +	return 0; +} + +static int +nva3_clock_prog(struct nouveau_clock *clk) +{ +	struct nva3_clock_priv *priv = (void *)clk; +	prog_pll(priv, 0x00, 0x004200, nv_clk_src_core); +	prog_pll(priv, 0x01, 0x004220, nv_clk_src_shader); +	prog_clk(priv, 0x20, nv_clk_src_disp); +	prog_clk(priv, 0x21, nv_clk_src_vdec); +	return 0; +} + +static void +nva3_clock_tidy(struct nouveau_clock *clk) +{ +} + +static struct nouveau_clocks +nva3_domain[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_core   , 0x00, 0, "core", 1000 }, +	{ nv_clk_src_shader , 0x01, 0, "shader", 1000 }, +	{ nv_clk_src_mem    , 0x02, 0, "memory", 1000 }, +	{ nv_clk_src_vdec   , 0x03 }, +	{ nv_clk_src_disp   , 0x04 }, +	{ nv_clk_src_max } +};  static int  nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, @@ -58,12 +302,16 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nva3_clock_priv *priv;  	int ret; -	ret = nouveau_clock_create(parent, engine, oclass, &priv); +	ret = nouveau_clock_create(parent, engine, oclass, nva3_domain, false, +				   &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; -	priv->base.pll_calc = nva3_clock_pll_calc; +	priv->base.read = nva3_clock_read; +	priv->base.calc = nva3_clock_calc; +	priv->base.prog = nva3_clock_prog; +	priv->base.tidy = nva3_clock_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h new file mode 100644 index 00000000000..6229a509b42 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.h @@ -0,0 +1,14 @@ +#ifndef __NVKM_CLK_NVA3_H__ +#define __NVKM_CLK_NVA3_H__ + +#include <subdev/clock.h> + +struct nva3_clock_info { +	u32 clk; +	u32 pll; +}; + +int nva3_clock_info(struct nouveau_clock *, int, u32, u32, +		    struct nva3_clock_info *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c new file mode 100644 index 00000000000..6a65fc9e966 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvaa.c @@ -0,0 +1,446 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <engine/fifo.h> +#include <subdev/bios.h> +#include <subdev/bios/pll.h> +#include <subdev/timer.h> +#include <subdev/clock.h> + +#include "pll.h" + +struct nvaa_clock_priv { +	struct nouveau_clock base; +	enum nv_clk_src csrc, ssrc, vsrc; +	u32 cctrl, sctrl; +	u32 ccoef, scoef; +	u32 cpost, spost; +	u32 vdiv; +}; + +static u32 +read_div(struct nouveau_clock *clk) +{ +	return nv_rd32(clk, 0x004600); +} + +static u32 +read_pll(struct nouveau_clock *clk, u32 base) +{ +	u32 ctrl = nv_rd32(clk, base + 0); +	u32 coef = nv_rd32(clk, base + 4); +	u32 ref = clk->read(clk, nv_clk_src_href); +	u32 post_div = 0; +	u32 clock = 0; +	int N1, M1; + +	switch (base){ +	case 0x4020: +		post_div = 1 << ((nv_rd32(clk, 0x4070) & 0x000f0000) >> 16); +		break; +	case 0x4028: +		post_div = (nv_rd32(clk, 0x4040) & 0x000f0000) >> 16; +		break; +	default: +		break; +	} + +	N1 = (coef & 0x0000ff00) >> 8; +	M1 = (coef & 0x000000ff); +	if ((ctrl & 0x80000000) && M1) { +		clock = ref * N1 / M1; +		clock = clock / post_div; +	} + +	return clock; +} + +static int +nvaa_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ +	struct nvaa_clock_priv *priv = (void *)clk; +	u32 mast = nv_rd32(clk, 0x00c054); +	u32 P = 0; + +	switch (src) { +	case nv_clk_src_crystal: +		return nv_device(priv)->crystal; +	case nv_clk_src_href: +		return 100000; /* PCIE reference clock */ +	case nv_clk_src_hclkm4: +		return clk->read(clk, nv_clk_src_href) * 4; +	case nv_clk_src_hclkm2d3: +		return clk->read(clk, nv_clk_src_href) * 2 / 3; +	case nv_clk_src_host: +		switch (mast & 0x000c0000) { +		case 0x00000000: return clk->read(clk, nv_clk_src_hclkm2d3); +		case 0x00040000: break; +		case 0x00080000: return clk->read(clk, nv_clk_src_hclkm4); +		case 0x000c0000: return clk->read(clk, nv_clk_src_cclk); +		} +		break; +	case nv_clk_src_core: +		P = (nv_rd32(clk, 0x004028) & 0x00070000) >> 16; + +		switch (mast & 0x00000003) { +		case 0x00000000: return clk->read(clk, nv_clk_src_crystal) >> P; +		case 0x00000001: return 0; +		case 0x00000002: return clk->read(clk, nv_clk_src_hclkm4) >> P; +		case 0x00000003: return read_pll(clk, 0x004028) >> P; +		} +		break; +	case nv_clk_src_cclk: +		if ((mast & 0x03000000) != 0x03000000) +			return clk->read(clk, nv_clk_src_core); + +		if ((mast & 0x00000200) == 0x00000000) +			return clk->read(clk, nv_clk_src_core); + +		switch (mast & 0x00000c00) { +		case 0x00000000: return clk->read(clk, nv_clk_src_href); +		case 0x00000400: return clk->read(clk, nv_clk_src_hclkm4); +		case 0x00000800: return clk->read(clk, nv_clk_src_hclkm2d3); +		default: return 0; +		} +	case nv_clk_src_shader: +		P = (nv_rd32(clk, 0x004020) & 0x00070000) >> 16; +		switch (mast & 0x00000030) { +		case 0x00000000: +			if (mast & 0x00000040) +				return clk->read(clk, nv_clk_src_href) >> P; +			return clk->read(clk, nv_clk_src_crystal) >> P; +		case 0x00000010: break; +		case 0x00000020: return read_pll(clk, 0x004028) >> P; +		case 0x00000030: return read_pll(clk, 0x004020) >> P; +		} +		break; +	case nv_clk_src_mem: +		return 0; +		break; +	case nv_clk_src_vdec: +		P = (read_div(clk) & 0x00000700) >> 8; + +		switch (mast & 0x00400000) { +		case 0x00400000: +			return clk->read(clk, nv_clk_src_core) >> P; +			break; +		default: +			return 500000 >> P; +			break; +		} +		break; +	default: +		break; +	} + +	nv_debug(priv, "unknown clock source %d 0x%08x\n", src, mast); +	return 0; +} + +static u32 +calc_pll(struct nvaa_clock_priv *priv, u32 reg, +	 u32 clock, int *N, int *M, int *P) +{ +	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvbios_pll pll; +	struct nouveau_clock *clk = &priv->base; +	int ret; + +	ret = nvbios_pll_parse(bios, reg, &pll); +	if (ret) +		return 0; + +	pll.vco2.max_freq = 0; +	pll.refclk = clk->read(clk, nv_clk_src_href); +	if (!pll.refclk) +		return 0; + +	return nv04_pll_calc(nv_subdev(priv), &pll, clock, N, M, NULL, NULL, P); +} + +static inline u32 +calc_P(u32 src, u32 target, int *div) +{ +	u32 clk0 = src, clk1 = src; +	for (*div = 0; *div <= 7; (*div)++) { +		if (clk0 <= target) { +			clk1 = clk0 << (*div ? 1 : 0); +			break; +		} +		clk0 >>= 1; +	} + +	if (target - clk0 <= clk1 - target) +		return clk0; +	(*div)--; +	return clk1; +} + +static int +nvaa_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ +	struct nvaa_clock_priv *priv = (void *)clk; +	const int shader = cstate->domain[nv_clk_src_shader]; +	const int core = cstate->domain[nv_clk_src_core]; +	const int vdec = cstate->domain[nv_clk_src_vdec]; +	u32 out = 0, clock = 0; +	int N, M, P1, P2 = 0; +	int divs = 0; + +	/* cclk: find suitable source, disable PLL if we can */ +	if (core < clk->read(clk, nv_clk_src_hclkm4)) +		out = calc_P(clk->read(clk, nv_clk_src_hclkm4), core, &divs); + +	/* Calculate clock * 2, so shader clock can use it too */ +	clock = calc_pll(priv, 0x4028, (core << 1), &N, &M, &P1); + +	if (abs(core - out) <= +	    abs(core - (clock >> 1))) { +		priv->csrc = nv_clk_src_hclkm4; +		priv->cctrl = divs << 16; +	} else { +		/* NVCTRL is actually used _after_ NVPOST, and after what we +		 * call NVPLL. To make matters worse, NVPOST is an integer +		 * divider instead of a right-shift number. */ +		if(P1 > 2) { +			P2 = P1 - 2; +			P1 = 2; +		} + +		priv->csrc = nv_clk_src_core; +		priv->ccoef = (N << 8) | M; + +		priv->cctrl = (P2 + 1) << 16; +		priv->cpost = (1 << P1) << 16; +	} + +	/* sclk: nvpll + divisor, href or spll */ +	out = 0; +	if (shader == clk->read(clk, nv_clk_src_href)) { +		priv->ssrc = nv_clk_src_href; +	} else { +		clock = calc_pll(priv, 0x4020, shader, &N, &M, &P1); +		if (priv->csrc == nv_clk_src_core) { +			out = calc_P((core << 1), shader, &divs); +		} + +		if (abs(shader - out) <= +		    abs(shader - clock) && +		   (divs + P2) <= 7) { +			priv->ssrc = nv_clk_src_core; +			priv->sctrl = (divs + P2) << 16; +		} else { +			priv->ssrc = nv_clk_src_shader; +			priv->scoef = (N << 8) | M; +			priv->sctrl = P1 << 16; +		} +	} + +	/* vclk */ +	out = calc_P(core, vdec, &divs); +	clock = calc_P(500000, vdec, &P1); +	if(abs(vdec - out) <= +	   abs(vdec - clock)) { +		priv->vsrc = nv_clk_src_cclk; +		priv->vdiv = divs << 16; +	} else { +		priv->vsrc = nv_clk_src_vdec; +		priv->vdiv = P1 << 16; +	} + +	/* Print strategy! */ +	nv_debug(priv, "nvpll: %08x %08x %08x\n", +			priv->ccoef, priv->cpost, priv->cctrl); +	nv_debug(priv, " spll: %08x %08x %08x\n", +			priv->scoef, priv->spost, priv->sctrl); +	nv_debug(priv, " vdiv: %08x\n", priv->vdiv); +	if (priv->csrc == nv_clk_src_hclkm4) +		nv_debug(priv, "core: hrefm4\n"); +	else +		nv_debug(priv, "core: nvpll\n"); + +	if (priv->ssrc == nv_clk_src_hclkm4) +		nv_debug(priv, "shader: hrefm4\n"); +	else if (priv->ssrc == nv_clk_src_core) +		nv_debug(priv, "shader: nvpll\n"); +	else +		nv_debug(priv, "shader: spll\n"); + +	if (priv->vsrc == nv_clk_src_hclkm4) +		nv_debug(priv, "vdec: 500MHz\n"); +	else +		nv_debug(priv, "vdec: core\n"); + +	return 0; +} + +static int +nvaa_clock_prog(struct nouveau_clock *clk) +{ +	struct nvaa_clock_priv *priv = (void *)clk; +	struct nouveau_fifo *pfifo = nouveau_fifo(clk); +	unsigned long flags; +	u32 pllmask = 0, mast, ptherm_gate; +	int ret = -EBUSY; + +	/* halt and idle execution engines */ +	ptherm_gate = nv_mask(clk, 0x020060, 0x00070000, 0x00000000); +	nv_mask(clk, 0x002504, 0x00000001, 0x00000001); +	/* Wait until the interrupt handler is finished */ +	if (!nv_wait(clk, 0x000100, 0xffffffff, 0x00000000)) +		goto resume; + +	if (pfifo) +		pfifo->pause(pfifo, &flags); + +	if (!nv_wait(clk, 0x002504, 0x00000010, 0x00000010)) +		goto resume; +	if (!nv_wait(clk, 0x00251c, 0x0000003f, 0x0000003f)) +		goto resume; + +	/* First switch to safe clocks: href */ +	mast = nv_mask(clk, 0xc054, 0x03400e70, 0x03400640); +	mast &= ~0x00400e73; +	mast |= 0x03000000; + +	switch (priv->csrc) { +	case nv_clk_src_hclkm4: +		nv_mask(clk, 0x4028, 0x00070000, priv->cctrl); +		mast |= 0x00000002; +		break; +	case nv_clk_src_core: +		nv_wr32(clk, 0x402c, priv->ccoef); +		nv_wr32(clk, 0x4028, 0x80000000 | priv->cctrl); +		nv_wr32(clk, 0x4040, priv->cpost); +		pllmask |= (0x3 << 8); +		mast |= 0x00000003; +		break; +	default: +		nv_warn(priv,"Reclocking failed: unknown core clock\n"); +		goto resume; +	} + +	switch (priv->ssrc) { +	case nv_clk_src_href: +		nv_mask(clk, 0x4020, 0x00070000, 0x00000000); +		/* mast |= 0x00000000; */ +		break; +	case nv_clk_src_core: +		nv_mask(clk, 0x4020, 0x00070000, priv->sctrl); +		mast |= 0x00000020; +		break; +	case nv_clk_src_shader: +		nv_wr32(clk, 0x4024, priv->scoef); +		nv_wr32(clk, 0x4020, 0x80000000 | priv->sctrl); +		nv_wr32(clk, 0x4070, priv->spost); +		pllmask |= (0x3 << 12); +		mast |= 0x00000030; +		break; +	default: +		nv_warn(priv,"Reclocking failed: unknown sclk clock\n"); +		goto resume; +	} + +	if (!nv_wait(clk, 0x004080, pllmask, pllmask)) { +		nv_warn(priv,"Reclocking failed: unstable PLLs\n"); +		goto resume; +	} + +	switch (priv->vsrc) { +	case nv_clk_src_cclk: +		mast |= 0x00400000; +	default: +		nv_wr32(clk, 0x4600, priv->vdiv); +	} + +	nv_wr32(clk, 0xc054, mast); +	ret = 0; + +resume: +	if (pfifo) +		pfifo->start(pfifo, &flags); + +	nv_mask(clk, 0x002504, 0x00000001, 0x00000000); +	nv_wr32(clk, 0x020060, ptherm_gate); + +	/* Disable some PLLs and dividers when unused */ +	if (priv->csrc != nv_clk_src_core) { +		nv_wr32(clk, 0x4040, 0x00000000); +		nv_mask(clk, 0x4028, 0x80000000, 0x00000000); +	} + +	if (priv->ssrc != nv_clk_src_shader) { +		nv_wr32(clk, 0x4070, 0x00000000); +		nv_mask(clk, 0x4020, 0x80000000, 0x00000000); +	} + +	return ret; +} + +static void +nvaa_clock_tidy(struct nouveau_clock *clk) +{ +} + +static struct nouveau_clocks +nvaa_domains[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_core   , 0xff, 0, "core", 1000 }, +	{ nv_clk_src_shader , 0xff, 0, "shader", 1000 }, +	{ nv_clk_src_vdec   , 0xff, 0, "vdec", 1000 }, +	{ nv_clk_src_max } +}; + +static int +nvaa_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		struct nouveau_oclass *oclass, void *data, u32 size, +		struct nouveau_object **pobject) +{ +	struct nvaa_clock_priv *priv; +	int ret; + +	ret = nouveau_clock_create(parent, engine, oclass, nvaa_domains, true, +				   &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.read = nvaa_clock_read; +	priv->base.calc = nvaa_clock_calc; +	priv->base.prog = nvaa_clock_prog; +	priv->base.tidy = nvaa_clock_tidy; +	return 0; +} + +struct nouveau_oclass * +nvaa_clock_oclass = &(struct nouveau_oclass) { +	.handle = NV_SUBDEV(CLOCK, 0xaa), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvaa_clock_ctor, +		.dtor = _nouveau_clock_dtor, +		.init = _nouveau_clock_init, +		.fini = _nouveau_clock_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 439d81c2613..dbf8517f54d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -25,11 +25,408 @@  #include <subdev/clock.h>  #include <subdev/bios.h>  #include <subdev/bios/pll.h> +#include <subdev/timer.h>  #include "pll.h" +struct nvc0_clock_info { +	u32 freq; +	u32 ssel; +	u32 mdiv; +	u32 dsrc; +	u32 ddiv; +	u32 coef; +}; +  struct nvc0_clock_priv {  	struct nouveau_clock base; +	struct nvc0_clock_info eng[16]; +}; + +static u32 read_div(struct nvc0_clock_priv *, int, u32, u32); + +static u32 +read_vco(struct nvc0_clock_priv *priv, u32 dsrc) +{ +	struct nouveau_clock *clk = &priv->base; +	u32 ssrc = nv_rd32(priv, dsrc); +	if (!(ssrc & 0x00000100)) +		return clk->read(clk, nv_clk_src_sppll0); +	return clk->read(clk, nv_clk_src_sppll1); +} + +static u32 +read_pll(struct nvc0_clock_priv *priv, u32 pll) +{ +	struct nouveau_clock *clk = &priv->base; +	u32 ctrl = nv_rd32(priv, pll + 0x00); +	u32 coef = nv_rd32(priv, pll + 0x04); +	u32 P = (coef & 0x003f0000) >> 16; +	u32 N = (coef & 0x0000ff00) >> 8; +	u32 M = (coef & 0x000000ff) >> 0; +	u32 sclk; + +	if (!(ctrl & 0x00000001)) +		return 0; + +	switch (pll) { +	case 0x00e800: +	case 0x00e820: +		sclk = nv_device(priv)->crystal; +		P = 1; +		break; +	case 0x132000: +		sclk = clk->read(clk, nv_clk_src_mpllsrc); +		break; +	case 0x132020: +		sclk = clk->read(clk, nv_clk_src_mpllsrcref); +		break; +	case 0x137000: +	case 0x137020: +	case 0x137040: +	case 0x1370e0: +		sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140); +		break; +	default: +		return 0; +	} + +	return sclk * N / M / P; +} + +static u32 +read_div(struct nvc0_clock_priv *priv, int doff, u32 dsrc, u32 dctl) +{ +	u32 ssrc = nv_rd32(priv, dsrc + (doff * 4)); +	u32 sctl = nv_rd32(priv, dctl + (doff * 4)); + +	switch (ssrc & 0x00000003) { +	case 0: +		if ((ssrc & 0x00030000) != 0x00030000) +			return nv_device(priv)->crystal; +		return 108000; +	case 2: +		return 100000; +	case 3: +		if (sctl & 0x80000000) { +			u32 sclk = read_vco(priv, dsrc + (doff * 4)); +			u32 sdiv = (sctl & 0x0000003f) + 2; +			return (sclk * 2) / sdiv; +		} + +		return read_vco(priv, dsrc + (doff * 4)); +	default: +		return 0; +	} +} + +static u32 +read_clk(struct nvc0_clock_priv *priv, int clk) +{ +	u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4)); +	u32 ssel = nv_rd32(priv, 0x137100); +	u32 sclk, sdiv; + +	if (ssel & (1 << clk)) { +		if (clk < 7) +			sclk = read_pll(priv, 0x137000 + (clk * 0x20)); +		else +			sclk = read_pll(priv, 0x1370e0); +		sdiv = ((sctl & 0x00003f00) >> 8) + 2; +	} else { +		sclk = read_div(priv, clk, 0x137160, 0x1371d0); +		sdiv = ((sctl & 0x0000003f) >> 0) + 2; +	} + +	if (sctl & 0x80000000) +		return (sclk * 2) / sdiv; + +	return sclk; +} + +static int +nvc0_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ +	struct nouveau_device *device = nv_device(clk); +	struct nvc0_clock_priv *priv = (void *)clk; + +	switch (src) { +	case nv_clk_src_crystal: +		return device->crystal; +	case nv_clk_src_href: +		return 100000; +	case nv_clk_src_sppll0: +		return read_pll(priv, 0x00e800); +	case nv_clk_src_sppll1: +		return read_pll(priv, 0x00e820); + +	case nv_clk_src_mpllsrcref: +		return read_div(priv, 0, 0x137320, 0x137330); +	case nv_clk_src_mpllsrc: +		return read_pll(priv, 0x132020); +	case nv_clk_src_mpll: +		return read_pll(priv, 0x132000); +	case nv_clk_src_mdiv: +		return read_div(priv, 0, 0x137300, 0x137310); +	case nv_clk_src_mem: +		if (nv_rd32(priv, 0x1373f0) & 0x00000002) +			return clk->read(clk, nv_clk_src_mpll); +		return clk->read(clk, nv_clk_src_mdiv); + +	case nv_clk_src_gpc: +		return read_clk(priv, 0x00); +	case nv_clk_src_rop: +		return read_clk(priv, 0x01); +	case nv_clk_src_hubk07: +		return read_clk(priv, 0x02); +	case nv_clk_src_hubk06: +		return read_clk(priv, 0x07); +	case nv_clk_src_hubk01: +		return read_clk(priv, 0x08); +	case nv_clk_src_copy: +		return read_clk(priv, 0x09); +	case nv_clk_src_daemon: +		return read_clk(priv, 0x0c); +	case nv_clk_src_vdec: +		return read_clk(priv, 0x0e); +	default: +		nv_error(clk, "invalid clock source %d\n", src); +		return -EINVAL; +	} +} + +static u32 +calc_div(struct nvc0_clock_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv) +{ +	u32 div = min((ref * 2) / freq, (u32)65); +	if (div < 2) +		div = 2; + +	*ddiv = div - 2; +	return (ref * 2) / div; +} + +static u32 +calc_src(struct nvc0_clock_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv) +{ +	u32 sclk; + +	/* use one of the fixed frequencies if possible */ +	*ddiv = 0x00000000; +	switch (freq) { +	case  27000: +	case 108000: +		*dsrc = 0x00000000; +		if (freq == 108000) +			*dsrc |= 0x00030000; +		return freq; +	case 100000: +		*dsrc = 0x00000002; +		return freq; +	default: +		*dsrc = 0x00000003; +		break; +	} + +	/* otherwise, calculate the closest divider */ +	sclk = read_vco(priv, 0x137160 + (clk * 4)); +	if (clk < 7) +		sclk = calc_div(priv, clk, sclk, freq, ddiv); +	return sclk; +} + +static u32 +calc_pll(struct nvc0_clock_priv *priv, int clk, u32 freq, u32 *coef) +{ +	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvbios_pll limits; +	int N, M, P, ret; + +	ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); +	if (ret) +		return 0; + +	limits.refclk = read_div(priv, clk, 0x137120, 0x137140); +	if (!limits.refclk) +		return 0; + +	ret = nva3_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P); +	if (ret <= 0) +		return 0; + +	*coef = (P << 16) | (N << 8) | M; +	return ret; +} + +static int +calc_clk(struct nvc0_clock_priv *priv, +	 struct nouveau_cstate *cstate, int clk, int dom) +{ +	struct nvc0_clock_info *info = &priv->eng[clk]; +	u32 freq = cstate->domain[dom]; +	u32 src0, div0, div1D, div1P = 0; +	u32 clk0, clk1 = 0; + +	/* invalid clock domain */ +	if (!freq) +		return 0; + +	/* first possible path, using only dividers */ +	clk0 = calc_src(priv, clk, freq, &src0, &div0); +	clk0 = calc_div(priv, clk, clk0, freq, &div1D); + +	/* see if we can get any closer using PLLs */ +	if (clk0 != freq && (0x00004387 & (1 << clk))) { +		if (clk <= 7) +			clk1 = calc_pll(priv, clk, freq, &info->coef); +		else +			clk1 = cstate->domain[nv_clk_src_hubk06]; +		clk1 = calc_div(priv, clk, clk1, freq, &div1P); +	} + +	/* select the method which gets closest to target freq */ +	if (abs((int)freq - clk0) <= abs((int)freq - clk1)) { +		info->dsrc = src0; +		if (div0) { +			info->ddiv |= 0x80000000; +			info->ddiv |= div0 << 8; +			info->ddiv |= div0; +		} +		if (div1D) { +			info->mdiv |= 0x80000000; +			info->mdiv |= div1D; +		} +		info->ssel = info->coef = 0; +		info->freq = clk0; +	} else { +		if (div1P) { +			info->mdiv |= 0x80000000; +			info->mdiv |= div1P << 8; +		} +		info->ssel = (1 << clk); +		info->freq = clk1; +	} + +	return 0; +} + +static int +nvc0_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ +	struct nvc0_clock_priv *priv = (void *)clk; +	int ret; + +	if ((ret = calc_clk(priv, cstate, 0x00, nv_clk_src_gpc)) || +	    (ret = calc_clk(priv, cstate, 0x01, nv_clk_src_rop)) || +	    (ret = calc_clk(priv, cstate, 0x02, nv_clk_src_hubk07)) || +	    (ret = calc_clk(priv, cstate, 0x07, nv_clk_src_hubk06)) || +	    (ret = calc_clk(priv, cstate, 0x08, nv_clk_src_hubk01)) || +	    (ret = calc_clk(priv, cstate, 0x09, nv_clk_src_copy)) || +	    (ret = calc_clk(priv, cstate, 0x0c, nv_clk_src_daemon)) || +	    (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec))) +		return ret; + +	return 0; +} + +static void +nvc0_clock_prog_0(struct nvc0_clock_priv *priv, int clk) +{ +	struct nvc0_clock_info *info = &priv->eng[clk]; +	if (clk < 7 && !info->ssel) { +		nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); +		nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc); +	} +} + +static void +nvc0_clock_prog_1(struct nvc0_clock_priv *priv, int clk) +{ +	nv_mask(priv, 0x137100, (1 << clk), 0x00000000); +	nv_wait(priv, 0x137100, (1 << clk), 0x00000000); +} + +static void +nvc0_clock_prog_2(struct nvc0_clock_priv *priv, int clk) +{ +	struct nvc0_clock_info *info = &priv->eng[clk]; +	const u32 addr = 0x137000 + (clk * 0x20); +	if (clk <= 7) { +		nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000); +		nv_mask(priv, addr + 0x00, 0x00000001, 0x00000000); +		if (info->coef) { +			nv_wr32(priv, addr + 0x04, info->coef); +			nv_mask(priv, addr + 0x00, 0x00000001, 0x00000001); +			nv_wait(priv, addr + 0x00, 0x00020000, 0x00020000); +			nv_mask(priv, addr + 0x00, 0x00020004, 0x00000004); +		} +	} +} + +static void +nvc0_clock_prog_3(struct nvc0_clock_priv *priv, int clk) +{ +	struct nvc0_clock_info *info = &priv->eng[clk]; +	if (info->ssel) { +		nv_mask(priv, 0x137100, (1 << clk), info->ssel); +		nv_wait(priv, 0x137100, (1 << clk), info->ssel); +	} +} + +static void +nvc0_clock_prog_4(struct nvc0_clock_priv *priv, int clk) +{ +	struct nvc0_clock_info *info = &priv->eng[clk]; +	nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); +} + +static int +nvc0_clock_prog(struct nouveau_clock *clk) +{ +	struct nvc0_clock_priv *priv = (void *)clk; +	struct { +		void (*exec)(struct nvc0_clock_priv *, int); +	} stage[] = { +		{ nvc0_clock_prog_0 }, /* div programming */ +		{ nvc0_clock_prog_1 }, /* select div mode */ +		{ nvc0_clock_prog_2 }, /* (maybe) program pll */ +		{ nvc0_clock_prog_3 }, /* (maybe) select pll mode */ +		{ nvc0_clock_prog_4 }, /* final divider */ +	}; +	int i, j; + +	for (i = 0; i < ARRAY_SIZE(stage); i++) { +		for (j = 0; j < ARRAY_SIZE(priv->eng); j++) { +			if (!priv->eng[j].freq) +				continue; +			stage[i].exec(priv, j); +		} +	} + +	return 0; +} + +static void +nvc0_clock_tidy(struct nouveau_clock *clk) +{ +	struct nvc0_clock_priv *priv = (void *)clk; +	memset(priv->eng, 0x00, sizeof(priv->eng)); +} + +static struct nouveau_clocks +nvc0_domain[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_hubk06 , 0x00 }, +	{ nv_clk_src_hubk01 , 0x01 }, +	{ nv_clk_src_copy   , 0x02 }, +	{ nv_clk_src_gpc    , 0x03, 0, "core", 2000 }, +	{ nv_clk_src_rop    , 0x04 }, +	{ nv_clk_src_mem    , 0x05, 0, "memory", 1000 }, +	{ nv_clk_src_vdec   , 0x06 }, +	{ nv_clk_src_daemon , 0x0a }, +	{ nv_clk_src_hubk07 , 0x0b }, +	{ nv_clk_src_max }  };  static int @@ -40,12 +437,16 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nvc0_clock_priv *priv;  	int ret; -	ret = nouveau_clock_create(parent, engine, oclass, &priv); +	ret = nouveau_clock_create(parent, engine, oclass, nvc0_domain, false, +				   &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; -	priv->base.pll_calc = nva3_clock_pll_calc; +	priv->base.read = nvc0_clock_read; +	priv->base.calc = nvc0_clock_calc; +	priv->base.prog = nvc0_clock_prog; +	priv->base.tidy = nvc0_clock_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c new file mode 100644 index 00000000000..0e62a324014 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nve0.c @@ -0,0 +1,500 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/clock.h> +#include <subdev/timer.h> +#include <subdev/bios.h> +#include <subdev/bios/pll.h> + +#include "pll.h" + +struct nve0_clock_info { +	u32 freq; +	u32 ssel; +	u32 mdiv; +	u32 dsrc; +	u32 ddiv; +	u32 coef; +}; + +struct nve0_clock_priv { +	struct nouveau_clock base; +	struct nve0_clock_info eng[16]; +}; + +static u32 read_div(struct nve0_clock_priv *, int, u32, u32); +static u32 read_pll(struct nve0_clock_priv *, u32); + +static u32 +read_vco(struct nve0_clock_priv *priv, u32 dsrc) +{ +	u32 ssrc = nv_rd32(priv, dsrc); +	if (!(ssrc & 0x00000100)) +		return read_pll(priv, 0x00e800); +	return read_pll(priv, 0x00e820); +} + +static u32 +read_pll(struct nve0_clock_priv *priv, u32 pll) +{ +	u32 ctrl = nv_rd32(priv, pll + 0x00); +	u32 coef = nv_rd32(priv, pll + 0x04); +	u32 P = (coef & 0x003f0000) >> 16; +	u32 N = (coef & 0x0000ff00) >> 8; +	u32 M = (coef & 0x000000ff) >> 0; +	u32 sclk; +	u16 fN = 0xf000; + +	if (!(ctrl & 0x00000001)) +		return 0; + +	switch (pll) { +	case 0x00e800: +	case 0x00e820: +		sclk = nv_device(priv)->crystal; +		P = 1; +		break; +	case 0x132000: +		sclk = read_pll(priv, 0x132020); +		P = (coef & 0x10000000) ? 2 : 1; +		break; +	case 0x132020: +		sclk = read_div(priv, 0, 0x137320, 0x137330); +		fN   = nv_rd32(priv, pll + 0x10) >> 16; +		break; +	case 0x137000: +	case 0x137020: +	case 0x137040: +	case 0x1370e0: +		sclk = read_div(priv, (pll & 0xff) / 0x20, 0x137120, 0x137140); +		break; +	default: +		return 0; +	} + +	if (P == 0) +		P = 1; + +	sclk = (sclk * N) + (((u16)(fN + 4096) * sclk) >> 13); +	return sclk / (M * P); +} + +static u32 +read_div(struct nve0_clock_priv *priv, int doff, u32 dsrc, u32 dctl) +{ +	u32 ssrc = nv_rd32(priv, dsrc + (doff * 4)); +	u32 sctl = nv_rd32(priv, dctl + (doff * 4)); + +	switch (ssrc & 0x00000003) { +	case 0: +		if ((ssrc & 0x00030000) != 0x00030000) +			return nv_device(priv)->crystal; +		return 108000; +	case 2: +		return 100000; +	case 3: +		if (sctl & 0x80000000) { +			u32 sclk = read_vco(priv, dsrc + (doff * 4)); +			u32 sdiv = (sctl & 0x0000003f) + 2; +			return (sclk * 2) / sdiv; +		} + +		return read_vco(priv, dsrc + (doff * 4)); +	default: +		return 0; +	} +} + +static u32 +read_mem(struct nve0_clock_priv *priv) +{ +	switch (nv_rd32(priv, 0x1373f4) & 0x0000000f) { +	case 1: return read_pll(priv, 0x132020); +	case 2: return read_pll(priv, 0x132000); +	default: +		return 0; +	} +} + +static u32 +read_clk(struct nve0_clock_priv *priv, int clk) +{ +	u32 sctl = nv_rd32(priv, 0x137250 + (clk * 4)); +	u32 sclk, sdiv; + +	if (clk < 7) { +		u32 ssel = nv_rd32(priv, 0x137100); +		if (ssel & (1 << clk)) { +			sclk = read_pll(priv, 0x137000 + (clk * 0x20)); +			sdiv = 1; +		} else { +			sclk = read_div(priv, clk, 0x137160, 0x1371d0); +			sdiv = 0; +		} +	} else { +		u32 ssrc = nv_rd32(priv, 0x137160 + (clk * 0x04)); +		if ((ssrc & 0x00000003) == 0x00000003) { +			sclk = read_div(priv, clk, 0x137160, 0x1371d0); +			if (ssrc & 0x00000100) { +				if (ssrc & 0x40000000) +					sclk = read_pll(priv, 0x1370e0); +				sdiv = 1; +			} else { +				sdiv = 0; +			} +		} else { +			sclk = read_div(priv, clk, 0x137160, 0x1371d0); +			sdiv = 0; +		} +	} + +	if (sctl & 0x80000000) { +		if (sdiv) +			sdiv = ((sctl & 0x00003f00) >> 8) + 2; +		else +			sdiv = ((sctl & 0x0000003f) >> 0) + 2; +		return (sclk * 2) / sdiv; +	} + +	return sclk; +} + +static int +nve0_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) +{ +	struct nouveau_device *device = nv_device(clk); +	struct nve0_clock_priv *priv = (void *)clk; + +	switch (src) { +	case nv_clk_src_crystal: +		return device->crystal; +	case nv_clk_src_href: +		return 100000; +	case nv_clk_src_mem: +		return read_mem(priv); +	case nv_clk_src_gpc: +		return read_clk(priv, 0x00); +	case nv_clk_src_rop: +		return read_clk(priv, 0x01); +	case nv_clk_src_hubk07: +		return read_clk(priv, 0x02); +	case nv_clk_src_hubk06: +		return read_clk(priv, 0x07); +	case nv_clk_src_hubk01: +		return read_clk(priv, 0x08); +	case nv_clk_src_daemon: +		return read_clk(priv, 0x0c); +	case nv_clk_src_vdec: +		return read_clk(priv, 0x0e); +	default: +		nv_error(clk, "invalid clock source %d\n", src); +		return -EINVAL; +	} +} + +static u32 +calc_div(struct nve0_clock_priv *priv, int clk, u32 ref, u32 freq, u32 *ddiv) +{ +	u32 div = min((ref * 2) / freq, (u32)65); +	if (div < 2) +		div = 2; + +	*ddiv = div - 2; +	return (ref * 2) / div; +} + +static u32 +calc_src(struct nve0_clock_priv *priv, int clk, u32 freq, u32 *dsrc, u32 *ddiv) +{ +	u32 sclk; + +	/* use one of the fixed frequencies if possible */ +	*ddiv = 0x00000000; +	switch (freq) { +	case  27000: +	case 108000: +		*dsrc = 0x00000000; +		if (freq == 108000) +			*dsrc |= 0x00030000; +		return freq; +	case 100000: +		*dsrc = 0x00000002; +		return freq; +	default: +		*dsrc = 0x00000003; +		break; +	} + +	/* otherwise, calculate the closest divider */ +	sclk = read_vco(priv, 0x137160 + (clk * 4)); +	if (clk < 7) +		sclk = calc_div(priv, clk, sclk, freq, ddiv); +	return sclk; +} + +static u32 +calc_pll(struct nve0_clock_priv *priv, int clk, u32 freq, u32 *coef) +{ +	struct nouveau_bios *bios = nouveau_bios(priv); +	struct nvbios_pll limits; +	int N, M, P, ret; + +	ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); +	if (ret) +		return 0; + +	limits.refclk = read_div(priv, clk, 0x137120, 0x137140); +	if (!limits.refclk) +		return 0; + +	ret = nva3_pll_calc(nv_subdev(priv), &limits, freq, &N, NULL, &M, &P); +	if (ret <= 0) +		return 0; + +	*coef = (P << 16) | (N << 8) | M; +	return ret; +} + +static int +calc_clk(struct nve0_clock_priv *priv, +	 struct nouveau_cstate *cstate, int clk, int dom) +{ +	struct nve0_clock_info *info = &priv->eng[clk]; +	u32 freq = cstate->domain[dom]; +	u32 src0, div0, div1D, div1P = 0; +	u32 clk0, clk1 = 0; + +	/* invalid clock domain */ +	if (!freq) +		return 0; + +	/* first possible path, using only dividers */ +	clk0 = calc_src(priv, clk, freq, &src0, &div0); +	clk0 = calc_div(priv, clk, clk0, freq, &div1D); + +	/* see if we can get any closer using PLLs */ +	if (clk0 != freq && (0x0000ff87 & (1 << clk))) { +		if (clk <= 7) +			clk1 = calc_pll(priv, clk, freq, &info->coef); +		else +			clk1 = cstate->domain[nv_clk_src_hubk06]; +		clk1 = calc_div(priv, clk, clk1, freq, &div1P); +	} + +	/* select the method which gets closest to target freq */ +	if (abs((int)freq - clk0) <= abs((int)freq - clk1)) { +		info->dsrc = src0; +		if (div0) { +			info->ddiv |= 0x80000000; +			info->ddiv |= div0; +		} +		if (div1D) { +			info->mdiv |= 0x80000000; +			info->mdiv |= div1D; +		} +		info->ssel = 0; +		info->freq = clk0; +	} else { +		if (div1P) { +			info->mdiv |= 0x80000000; +			info->mdiv |= div1P << 8; +		} +		info->ssel = (1 << clk); +		info->dsrc = 0x40000100; +		info->freq = clk1; +	} + +	return 0; +} + +static int +nve0_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) +{ +	struct nve0_clock_priv *priv = (void *)clk; +	int ret; + +	if ((ret = calc_clk(priv, cstate, 0x00, nv_clk_src_gpc)) || +	    (ret = calc_clk(priv, cstate, 0x01, nv_clk_src_rop)) || +	    (ret = calc_clk(priv, cstate, 0x02, nv_clk_src_hubk07)) || +	    (ret = calc_clk(priv, cstate, 0x07, nv_clk_src_hubk06)) || +	    (ret = calc_clk(priv, cstate, 0x08, nv_clk_src_hubk01)) || +	    (ret = calc_clk(priv, cstate, 0x0c, nv_clk_src_daemon)) || +	    (ret = calc_clk(priv, cstate, 0x0e, nv_clk_src_vdec))) +		return ret; + +	return 0; +} + +static void +nve0_clock_prog_0(struct nve0_clock_priv *priv, int clk) +{ +	struct nve0_clock_info *info = &priv->eng[clk]; +	if (!info->ssel) { +		nv_mask(priv, 0x1371d0 + (clk * 0x04), 0x8000003f, info->ddiv); +		nv_wr32(priv, 0x137160 + (clk * 0x04), info->dsrc); +	} +} + +static void +nve0_clock_prog_1_0(struct nve0_clock_priv *priv, int clk) +{ +	nv_mask(priv, 0x137100, (1 << clk), 0x00000000); +	nv_wait(priv, 0x137100, (1 << clk), 0x00000000); +} + +static void +nve0_clock_prog_1_1(struct nve0_clock_priv *priv, int clk) +{ +	nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000000); +} + +static void +nve0_clock_prog_2(struct nve0_clock_priv *priv, int clk) +{ +	struct nve0_clock_info *info = &priv->eng[clk]; +	const u32 addr = 0x137000 + (clk * 0x20); +	nv_mask(priv, addr + 0x00, 0x00000004, 0x00000000); +	nv_mask(priv, addr + 0x00, 0x00000001, 0x00000000); +	if (info->coef) { +		nv_wr32(priv, addr + 0x04, info->coef); +		nv_mask(priv, addr + 0x00, 0x00000001, 0x00000001); +		nv_wait(priv, addr + 0x00, 0x00020000, 0x00020000); +		nv_mask(priv, addr + 0x00, 0x00020004, 0x00000004); +	} +} + +static void +nve0_clock_prog_3(struct nve0_clock_priv *priv, int clk) +{ +	struct nve0_clock_info *info = &priv->eng[clk]; +	if (info->ssel) +		nv_mask(priv, 0x137250 + (clk * 0x04), 0x00003f00, info->mdiv); +	else +		nv_mask(priv, 0x137250 + (clk * 0x04), 0x0000003f, info->mdiv); +} + +static void +nve0_clock_prog_4_0(struct nve0_clock_priv *priv, int clk) +{ +	struct nve0_clock_info *info = &priv->eng[clk]; +	if (info->ssel) { +		nv_mask(priv, 0x137100, (1 << clk), info->ssel); +		nv_wait(priv, 0x137100, (1 << clk), info->ssel); +	} +} + +static void +nve0_clock_prog_4_1(struct nve0_clock_priv *priv, int clk) +{ +	struct nve0_clock_info *info = &priv->eng[clk]; +	if (info->ssel) { +		nv_mask(priv, 0x137160 + (clk * 0x04), 0x40000000, 0x40000000); +		nv_mask(priv, 0x137160 + (clk * 0x04), 0x00000100, 0x00000100); +	} +} + +static int +nve0_clock_prog(struct nouveau_clock *clk) +{ +	struct nve0_clock_priv *priv = (void *)clk; +	struct { +		u32 mask; +		void (*exec)(struct nve0_clock_priv *, int); +	} stage[] = { +		{ 0x007f, nve0_clock_prog_0   }, /* div programming */ +		{ 0x007f, nve0_clock_prog_1_0 }, /* select div mode */ +		{ 0xff80, nve0_clock_prog_1_1 }, +		{ 0x00ff, nve0_clock_prog_2   }, /* (maybe) program pll */ +		{ 0xff80, nve0_clock_prog_3   }, /* final divider */ +		{ 0x007f, nve0_clock_prog_4_0 }, /* (maybe) select pll mode */ +		{ 0xff80, nve0_clock_prog_4_1 }, +	}; +	int i, j; + +	for (i = 0; i < ARRAY_SIZE(stage); i++) { +		for (j = 0; j < ARRAY_SIZE(priv->eng); j++) { +			if (!(stage[i].mask & (1 << j))) +				continue; +			if (!priv->eng[j].freq) +				continue; +			stage[i].exec(priv, j); +		} +	} + +	return 0; +} + +static void +nve0_clock_tidy(struct nouveau_clock *clk) +{ +	struct nve0_clock_priv *priv = (void *)clk; +	memset(priv->eng, 0x00, sizeof(priv->eng)); +} + +static struct nouveau_clocks +nve0_domain[] = { +	{ nv_clk_src_crystal, 0xff }, +	{ nv_clk_src_href   , 0xff }, +	{ nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 }, +	{ nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE }, +	{ nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE }, +	{ nv_clk_src_mem    , 0x03, 0, "memory", 500 }, +	{ nv_clk_src_hubk06 , 0x04, NVKM_CLK_DOM_FLAG_CORE }, +	{ nv_clk_src_hubk01 , 0x05 }, +	{ nv_clk_src_vdec   , 0x06 }, +	{ nv_clk_src_daemon , 0x07 }, +	{ nv_clk_src_max } +}; + +static int +nve0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		struct nouveau_oclass *oclass, void *data, u32 size, +		struct nouveau_object **pobject) +{ +	struct nve0_clock_priv *priv; +	int ret; + +	ret = nouveau_clock_create(parent, engine, oclass, nve0_domain, true, +				   &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.read = nve0_clock_read; +	priv->base.calc = nve0_clock_calc; +	priv->base.prog = nve0_clock_prog; +	priv->base.tidy = nve0_clock_tidy; +	return 0; +} + +struct nouveau_oclass +nve0_clock_oclass = { +	.handle = NV_SUBDEV(CLOCK, 0xe0), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nve0_clock_ctor, +		.dtor = _nouveau_clock_dtor, +		.init = _nouveau_clock_init, +		.fini = _nouveau_clock_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c index cf1ed0dc9bc..b47d543ab2e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnv04.c @@ -38,7 +38,7 @@ getMNP_single(struct nouveau_subdev *subdev, struct nvbios_pll *info, int clk,  	 * "clk" parameter in kHz  	 * returns calculated clock  	 */ -	int cv = nouveau_bios(subdev)->version.chip; +	struct nouveau_bios *bios = nouveau_bios(subdev);  	int minvco = info->vco1.min_freq, maxvco = info->vco1.max_freq;  	int minM = info->vco1.min_m, maxM = info->vco1.max_m;  	int minN = info->vco1.min_n, maxN = info->vco1.max_n; @@ -54,18 +54,21 @@ getMNP_single(struct nouveau_subdev *subdev, struct nvbios_pll *info, int clk,  	/* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */  	/* possibly correlated with introduction of 27MHz crystal */ -	if (cv < 0x17 || cv == 0x1a || cv == 0x20) { -		if (clk > 250000) -			maxM = 6; -		if (clk > 340000) -			maxM = 2; -	} else if (cv < 0x40) { -		if (clk > 150000) -			maxM = 6; -		if (clk > 200000) -			maxM = 4; -		if (clk > 340000) -			maxM = 2; +	if (bios->version.major < 0x60) { +		int cv = bios->version.chip; +		if (cv < 0x17 || cv == 0x1a || cv == 0x20) { +			if (clk > 250000) +				maxM = 6; +			if (clk > 340000) +				maxM = 2; +		} else if (cv < 0x40) { +			if (clk > 150000) +				maxM = 6; +			if (clk > 200000) +				maxM = 4; +			if (clk > 340000) +				maxM = 2; +		}  	}  	P = 1 << maxP; @@ -227,10 +230,12 @@ nv04_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info, u32 freq,  {  	int ret; -	if (!info->vco2.max_freq) { +	if (!info->vco2.max_freq || !N2) {  		ret = getMNP_single(subdev, info, freq, N1, M1, P); -		*N2 = 1; -		*M2 = 1; +		if (N2) { +			*N2 = 1; +			*M2 = 1; +		}  	} else {  		ret = getMNP_double(subdev, info, freq, N1, M1, N2, M2, P);  	} diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c index 2fe1f712eef..8eca457c281 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/pllnva3.c @@ -45,6 +45,7 @@ nva3_pll_calc(struct nouveau_subdev *subdev, struct nvbios_pll *info,  	lM = max(lM, (int)info->vco1.min_m);  	hM = (info->refclk + info->vco1.min_inputfreq) / info->vco1.min_inputfreq;  	hM = min(hM, (int)info->vco1.max_m); +	lM = min(lM, hM);  	for (M = lM; M <= hM; M++) {  		u32 tmp = freq * *P * M; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/seq.h b/drivers/gpu/drm/nouveau/core/subdev/clock/seq.h new file mode 100644 index 00000000000..fb33f06ebd5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/seq.h @@ -0,0 +1,17 @@ +#ifndef __NVKM_CLK_SEQ_H__ +#define __NVKM_CLK_SEQ_H__ + +#include <subdev/bus.h> +#include <subdev/bus/hwsq.h> + +#define clk_init(s,p)       hwsq_init(&(s)->base, (p)) +#define clk_exec(s,e)       hwsq_exec(&(s)->base, (e)) +#define clk_have(s,r)       ((s)->r_##r.addr != 0x000000) +#define clk_rd32(s,r)       hwsq_rd32(&(s)->base, &(s)->r_##r) +#define clk_wr32(s,r,d)     hwsq_wr32(&(s)->base, &(s)->r_##r, (d)) +#define clk_mask(s,r,m,d)   hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d)) +#define clk_setf(s,f,d)     hwsq_setf(&(s)->base, (f), (d)) +#define clk_wait(s,f,d)     hwsq_wait(&(s)->base, (f), (d)) +#define clk_nsec(s,n)       hwsq_nsec(&(s)->base, (n)) + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c index 79c81d3d9ba..239acfe876c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/base.c @@ -24,9 +24,11 @@  #include <core/option.h> -#include <subdev/devinit.h>  #include <subdev/bios.h>  #include <subdev/bios/init.h> +#include <subdev/vga.h> + +#include "priv.h"  int  _nouveau_devinit_fini(struct nouveau_object *object, bool suspend) @@ -37,18 +39,41 @@ _nouveau_devinit_fini(struct nouveau_object *object, bool suspend)  	if (suspend)  		devinit->post = true; +	/* unlock the extended vga crtc regs */ +	nv_lockvgac(devinit, false); +  	return nouveau_subdev_fini(&devinit->base, suspend);  }  int  _nouveau_devinit_init(struct nouveau_object *object)  { +	struct nouveau_devinit_impl *impl = (void *)object->oclass;  	struct nouveau_devinit *devinit = (void *)object; -	int ret = nouveau_subdev_init(&devinit->base); +	int ret; + +	ret = nouveau_subdev_init(&devinit->base); +	if (ret) +		return ret; + +	ret = nvbios_init(&devinit->base, devinit->post);  	if (ret)  		return ret; -	return nvbios_init(&devinit->base, devinit->post); +	if (impl->disable) +		nv_device(devinit)->disable_mask |= impl->disable(devinit); +	return 0; +} + +void +_nouveau_devinit_dtor(struct nouveau_object *object) +{ +	struct nouveau_devinit *devinit = (void *)object; + +	/* lock crtc regs */ +	nv_lockvgac(devinit, true); + +	nouveau_subdev_destroy(&devinit->base);  }  int @@ -57,6 +82,7 @@ nouveau_devinit_create_(struct nouveau_object *parent,  			struct nouveau_oclass *oclass,  			int size, void **pobject)  { +	struct nouveau_devinit_impl *impl = (void *)oclass;  	struct nouveau_device *device = nv_device(parent);  	struct nouveau_devinit *devinit;  	int ret; @@ -68,5 +94,8 @@ nouveau_devinit_create_(struct nouveau_object *parent,  		return ret;  	devinit->post = nouveau_boolopt(device->cfgopt, "NvForcePost", false); +	devinit->meminit = impl->meminit; +	devinit->pll_set = impl->pll_set; +	devinit->mmio    = impl->mmio;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h index 6b56a0f4cb4..4fe49cf4c99 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/fbmem.h @@ -24,6 +24,8 @@   *   */ +#include <core/device.h> +  #define NV04_PFB_BOOT_0						0x00100000  #	define NV04_PFB_BOOT_0_RAM_AMOUNT			0x00000003  #	define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB			0x00000000 @@ -60,10 +62,10 @@  #	define NV10_PFB_REFCTRL_VALID_1				(1 << 31)  static inline struct io_mapping * -fbmem_init(struct pci_dev *pdev) +fbmem_init(struct nouveau_device *dev)  { -	return io_mapping_create_wc(pci_resource_start(pdev, 1), -				    pci_resource_len(pdev, 1)); +	return io_mapping_create_wc(nv_device_resource_start(dev, 1), +				    nv_device_resource_len(dev, 1));  }  static inline void diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c new file mode 100644 index 00000000000..c69bc7f54e3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/gm107.c @@ -0,0 +1,56 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +static u64 +gm107_devinit_disable(struct nouveau_devinit *devinit) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r021c00 = nv_rd32(priv, 0x021c00); +	u32 r021c04 = nv_rd32(priv, 0x021c04); +	u64 disable = 0ULL; + +	if (r021c00 & 0x00000001) +		disable |= (1ULL << NVDEV_ENGINE_COPY0); +	if (r021c00 & 0x00000004) +		disable |= (1ULL << NVDEV_ENGINE_COPY2); +	if (r021c04 & 0x00000001) +		disable |= (1ULL << NVDEV_ENGINE_DISP); + +	return disable; +} + +struct nouveau_oclass * +gm107_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x07), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_devinit_ctor, +		.dtor = _nouveau_devinit_dtor, +		.init = nv50_devinit_init, +		.fini = _nouveau_devinit_fini, +	}, +	.pll_set = nvc0_devinit_pll_set, +	.disable = gm107_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c index b22357d9b82..052ad690b46 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.c @@ -27,12 +27,7 @@  #include <subdev/vga.h>  #include "fbmem.h" -#include "priv.h" - -struct nv04_devinit_priv { -	struct nouveau_devinit base; -	int owner; -}; +#include "nv04.h"  static void  nv04_devinit_meminit(struct nouveau_devinit *devinit) @@ -43,7 +38,7 @@ nv04_devinit_meminit(struct nouveau_devinit *devinit)  	int i;  	/* Map the framebuffer aperture */ -	fb = fbmem_init(nv_device(priv)->pdev); +	fb = fbmem_init(nv_device(priv));  	if (!fb) {  		nv_error(priv, "failed to map fb\n");  		return; @@ -168,7 +163,8 @@ setPLL_single(struct nouveau_devinit *devinit, u32 reg,  		/* downclock -- write new NM first */  		nv_wr32(devinit, reg, (oldpll & 0xffff0000) | pv->NM1); -	if (chip_version < 0x17 && chip_version != 0x11) +	if ((chip_version < 0x17 || chip_version == 0x1a) && +	    chip_version != 0x11)  		/* wait a bit on older chips */  		msleep(64);  	nv_rd32(devinit, reg); @@ -392,17 +388,21 @@ int  nv04_devinit_fini(struct nouveau_object *object, bool suspend)  {  	struct nv04_devinit_priv *priv = (void *)object; +	int ret;  	/* make i2c busses accessible */  	nv_mask(priv, 0x000200, 0x00000001, 0x00000001); -	/* unlock extended vga crtc regs, and unslave crtcs */ -	nv_lockvgac(priv, false); +	ret = nouveau_devinit_fini(&priv->base, suspend); +	if (ret) +		return ret; + +	/* unslave crtcs */  	if (priv->owner < 0)  		priv->owner = nv_rdvgaowner(priv);  	nv_wrvgaowner(priv, 0); -	return nouveau_devinit_fini(&priv->base, suspend); +	return 0;  }  int @@ -430,14 +430,13 @@ nv04_devinit_dtor(struct nouveau_object *object)  {  	struct nv04_devinit_priv *priv = (void *)object; -	/* restore vga owner saved at first init, and lock crtc regs  */ +	/* restore vga owner saved at first init */  	nv_wrvgaowner(priv, priv->owner); -	nv_lockvgac(priv, true);  	nouveau_devinit_destroy(&priv->base);  } -static int +int  nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		  struct nouveau_oclass *oclass, void *data, u32 size,  		  struct nouveau_object **pobject) @@ -450,19 +449,19 @@ nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; -	priv->base.meminit = nv04_devinit_meminit; -	priv->base.pll_set = nv04_devinit_pll_set;  	priv->owner = -1;  	return 0;  } -struct nouveau_oclass -nv04_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x04), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_devinit_ctor,  		.dtor = nv04_devinit_dtor,  		.init = nv04_devinit_init,  		.fini = nv04_devinit_fini,  	}, -}; +	.meminit = nv04_devinit_meminit, +	.pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h new file mode 100644 index 00000000000..23470a57510 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv04.h @@ -0,0 +1,23 @@ +#ifndef __NVKM_DEVINIT_NV04_H__ +#define __NVKM_DEVINIT_NV04_H__ + +#include "priv.h" + +struct nv04_devinit_priv { +	struct nouveau_devinit base; +	u8 owner; +}; + +int  nv04_devinit_ctor(struct nouveau_object *, struct nouveau_object *, +		       struct nouveau_oclass *, void *, u32, +		       struct nouveau_object **); +void nv04_devinit_dtor(struct nouveau_object *); +int  nv04_devinit_init(struct nouveau_object *); +int  nv04_devinit_fini(struct nouveau_object *, bool); +int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); +void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); +void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c index b1912a8a894..4a19c10e517 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv05.c @@ -29,12 +29,7 @@  #include <subdev/vga.h>  #include "fbmem.h" -#include "priv.h" - -struct nv05_devinit_priv { -	struct nouveau_devinit base; -	u8 owner; -}; +#include "nv04.h"  static void  nv05_devinit_meminit(struct nouveau_devinit *devinit) @@ -49,7 +44,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)  		{ 0x06, 0x00 },  		{ 0x00, 0x00 }  	}; -	struct nv05_devinit_priv *priv = (void *)devinit; +	struct nv04_devinit_priv *priv = (void *)devinit;  	struct nouveau_bios *bios = nouveau_bios(priv);  	struct io_mapping *fb;  	u32 patt = 0xdeadbeef; @@ -58,7 +53,7 @@ nv05_devinit_meminit(struct nouveau_devinit *devinit)  	int i, v;  	/* Map the framebuffer aperture */ -	fb = fbmem_init(nv_device(priv)->pdev); +	fb = fbmem_init(nv_device(priv));  	if (!fb) {  		nv_error(priv, "failed to map fb\n");  		return; @@ -130,31 +125,15 @@ out:  	fbmem_fini(fb);  } -static int -nv05_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		  struct nouveau_oclass *oclass, void *data, u32 size, -		  struct nouveau_object **pobject) -{ -	struct nv05_devinit_priv *priv; -	int ret; - -	ret = nouveau_devinit_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.meminit = nv05_devinit_meminit; -	priv->base.pll_set = nv04_devinit_pll_set; -	return 0; -} - -struct nouveau_oclass -nv05_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0x05), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv05_devinit_ctor, +struct nouveau_oclass * +nv05_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x05), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_devinit_ctor,  		.dtor = nv04_devinit_dtor,  		.init = nv04_devinit_init,  		.fini = nv04_devinit_fini,  	}, -}; +	.meminit = nv05_devinit_meminit, +	.pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c index 463b08fa096..3b8d657da27 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv10.c @@ -27,25 +27,26 @@  #include <subdev/vga.h>  #include "fbmem.h" -#include "priv.h" - -struct nv10_devinit_priv { -	struct nouveau_devinit base; -	u8 owner; -}; +#include "nv04.h"  static void  nv10_devinit_meminit(struct nouveau_devinit *devinit)  { -	struct nv10_devinit_priv *priv = (void *)devinit; -	const int mem_width[] = { 0x10, 0x00, 0x20 }; -	const int mem_width_count = nv_device(priv)->chipset >= 0x17 ? 3 : 2; +	struct nv04_devinit_priv *priv = (void *)devinit; +	static const int mem_width[] = { 0x10, 0x00, 0x20 }; +	int mem_width_count;  	uint32_t patt = 0xdeadbeef;  	struct io_mapping *fb;  	int i, j, k; +	if (nv_device(priv)->card_type >= NV_11 && +	    nv_device(priv)->chipset >= 0x17) +		mem_width_count = 3; +	else +		mem_width_count = 2; +  	/* Map the framebuffer aperture */ -	fb = fbmem_init(nv_device(priv)->pdev); +	fb = fbmem_init(nv_device(priv));  	if (!fb) {  		nv_error(priv, "failed to map fb\n");  		return; @@ -95,31 +96,15 @@ amount_found:  	fbmem_fini(fb);  } -static int -nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		  struct nouveau_oclass *oclass, void *data, u32 size, -		  struct nouveau_object **pobject) -{ -	struct nv10_devinit_priv *priv; -	int ret; - -	ret = nouveau_devinit_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.meminit = nv10_devinit_meminit; -	priv->base.pll_set = nv04_devinit_pll_set; -	return 0; -} - -struct nouveau_oclass -nv10_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0x10), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv10_devinit_ctor, +struct nouveau_oclass * +nv10_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x10), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_devinit_ctor,  		.dtor = nv04_devinit_dtor,  		.init = nv04_devinit_init,  		.fini = nv04_devinit_fini,  	}, -}; +	.meminit = nv10_devinit_meminit, +	.pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c index e9743cdabe7..526d0c6faac 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv1a.c @@ -22,37 +22,16 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv04.h" -struct nv1a_devinit_priv { -	struct nouveau_devinit base; -	u8 owner; -}; - -static int -nv1a_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		  struct nouveau_oclass *oclass, void *data, u32 size, -		  struct nouveau_object **pobject) -{ -	struct nv1a_devinit_priv *priv; -	int ret; - -	ret = nouveau_devinit_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.pll_set = nv04_devinit_pll_set; -	return 0; -} - -struct nouveau_oclass -nv1a_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0x1a), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv1a_devinit_ctor, +struct nouveau_oclass * +nv1a_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x1a), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_devinit_ctor,  		.dtor = nv04_devinit_dtor,  		.init = nv04_devinit_init,  		.fini = nv04_devinit_fini,  	}, -}; +	.pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c index 6cc6080d3bc..04bc9732644 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv20.c @@ -24,25 +24,20 @@   *   */ -#include "priv.h" +#include "nv04.h"  #include "fbmem.h" -struct nv20_devinit_priv { -	struct nouveau_devinit base; -	u8 owner; -}; -  static void  nv20_devinit_meminit(struct nouveau_devinit *devinit)  { -	struct nv20_devinit_priv *priv = (void *)devinit; +	struct nv04_devinit_priv *priv = (void *)devinit;  	struct nouveau_device *device = nv_device(priv);  	uint32_t mask = (device->chipset >= 0x25 ? 0x300 : 0x900);  	uint32_t amount, off;  	struct io_mapping *fb;  	/* Map the framebuffer aperture */ -	fb = fbmem_init(nv_device(priv)->pdev); +	fb = fbmem_init(nv_device(priv));  	if (!fb) {  		nv_error(priv, "failed to map fb\n");  		return; @@ -65,31 +60,15 @@ nv20_devinit_meminit(struct nouveau_devinit *devinit)  	fbmem_fini(fb);  } -static int -nv20_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		  struct nouveau_oclass *oclass, void *data, u32 size, -		  struct nouveau_object **pobject) -{ -	struct nv20_devinit_priv *priv; -	int ret; - -	ret = nouveau_devinit_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.meminit = nv20_devinit_meminit; -	priv->base.pll_set = nv04_devinit_pll_set; -	return 0; -} - -struct nouveau_oclass -nv20_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0x20), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv20_devinit_ctor, +struct nouveau_oclass * +nv20_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x20), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_devinit_ctor,  		.dtor = nv04_devinit_dtor,  		.init = nv04_devinit_init,  		.fini = nv04_devinit_fini,  	}, -}; +	.meminit = nv20_devinit_meminit, +	.pll_set = nv04_devinit_pll_set, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c index 6df72247c47..b46c62a1d5d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c @@ -28,9 +28,9 @@  #include <subdev/bios/init.h>  #include <subdev/vga.h> -#include "priv.h" +#include "nv50.h" -static int +int  nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)  {  	struct nv50_devinit_priv *priv = (void *)devinit; @@ -74,6 +74,19 @@ nv50_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)  	return 0;  } +static u64 +nv50_devinit_disable(struct nouveau_devinit *devinit) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r001540 = nv_rd32(priv, 0x001540); +	u64 disable = 0ULL; + +	if (!(r001540 & 0x40000000)) +		disable |= (1ULL << NVDEV_ENGINE_MPEG); + +	return disable; +} +  int  nv50_devinit_init(struct nouveau_object *object)  { @@ -120,7 +133,7 @@ nv50_devinit_init(struct nouveau_object *object)  	return 0;  } -static int +int  nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		  struct nouveau_oclass *oclass, void *data, u32 size,  		  struct nouveau_object **pobject) @@ -133,17 +146,18 @@ nv50_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; -	priv->base.pll_set = nv50_devinit_pll_set;  	return 0;  } -struct nouveau_oclass -nv50_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_devinit_ctor,  		.dtor = _nouveau_devinit_dtor,  		.init = nv50_devinit_init,  		.fini = _nouveau_devinit_fini,  	}, -}; +	.pll_set = nv50_devinit_pll_set, +	.disable = nv50_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h new file mode 100644 index 00000000000..51d5076333e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.h @@ -0,0 +1,21 @@ +#ifndef __NVKM_DEVINIT_NV50_H__ +#define __NVKM_DEVINIT_NV50_H__ + +#include "priv.h" + +struct nv50_devinit_priv { +	struct nouveau_devinit base; +	u32 r001540; +}; + +int  nv50_devinit_ctor(struct nouveau_object *, struct nouveau_object *, +		       struct nouveau_oclass *, void *, u32, +		       struct nouveau_object **); +int  nv50_devinit_init(struct nouveau_object *); +int  nv50_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +int  nva3_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +int  nvc0_devinit_pll_set(struct nouveau_devinit *, u32, u32); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c new file mode 100644 index 00000000000..787422505d8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv84.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +static u64 +nv84_devinit_disable(struct nouveau_devinit *devinit) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r001540 = nv_rd32(priv, 0x001540); +	u32 r00154c = nv_rd32(priv, 0x00154c); +	u64 disable = 0ULL; + +	if (!(r001540 & 0x40000000)) { +		disable |= (1ULL << NVDEV_ENGINE_MPEG); +		disable |= (1ULL << NVDEV_ENGINE_VP); +		disable |= (1ULL << NVDEV_ENGINE_BSP); +		disable |= (1ULL << NVDEV_ENGINE_CRYPT); +	} + +	if (!(r00154c & 0x00000004)) +		disable |= (1ULL << NVDEV_ENGINE_DISP); +	if (!(r00154c & 0x00000020)) +		disable |= (1ULL << NVDEV_ENGINE_BSP); +	if (!(r00154c & 0x00000040)) +		disable |= (1ULL << NVDEV_ENGINE_CRYPT); + +	return disable; +} + +struct nouveau_oclass * +nv84_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x84), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_devinit_ctor, +		.dtor = _nouveau_devinit_dtor, +		.init = nv50_devinit_init, +		.fini = _nouveau_devinit_fini, +	}, +	.pll_set = nv50_devinit_pll_set, +	.disable = nv84_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c new file mode 100644 index 00000000000..2b0e963fc6f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nv98.c @@ -0,0 +1,62 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +static u64 +nv98_devinit_disable(struct nouveau_devinit *devinit) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r001540 = nv_rd32(priv, 0x001540); +	u32 r00154c = nv_rd32(priv, 0x00154c); +	u64 disable = 0ULL; + +	if (!(r001540 & 0x40000000)) { +		disable |= (1ULL << NVDEV_ENGINE_VP); +		disable |= (1ULL << NVDEV_ENGINE_BSP); +		disable |= (1ULL << NVDEV_ENGINE_PPP); +	} + +	if (!(r00154c & 0x00000004)) +		disable |= (1ULL << NVDEV_ENGINE_DISP); +	if (!(r00154c & 0x00000020)) +		disable |= (1ULL << NVDEV_ENGINE_BSP); +	if (!(r00154c & 0x00000040)) +		disable |= (1ULL << NVDEV_ENGINE_CRYPT); + +	return disable; +} + +struct nouveau_oclass * +nv98_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0x98), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_devinit_ctor, +		.dtor = _nouveau_devinit_dtor, +		.init = nv50_devinit_init, +		.fini = _nouveau_devinit_fini, +	}, +	.pll_set = nv50_devinit_pll_set, +	.disable = nv98_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c index 76a68b29014..006cf348bda 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nva3.c @@ -22,12 +22,12 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv50.h" -static int +int  nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)  { -	struct nva3_devinit_priv *priv = (void *)devinit; +	struct nv50_devinit_priv *priv = (void *)devinit;  	struct nouveau_bios *bios = nouveau_bios(priv);  	struct nvbios_pll info;  	int N, fN, M, P; @@ -58,30 +58,88 @@ nva3_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)  	return ret;  } -static int -nva3_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		  struct nouveau_oclass *oclass, void *data, u32 size, -		  struct nouveau_object **pobject) +static u64 +nva3_devinit_disable(struct nouveau_devinit *devinit)  { -	struct nv50_devinit_priv *priv; -	int ret; +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r001540 = nv_rd32(priv, 0x001540); +	u32 r00154c = nv_rd32(priv, 0x00154c); +	u64 disable = 0ULL; -	ret = nouveau_devinit_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; +	if (!(r001540 & 0x40000000)) { +		disable |= (1ULL << NVDEV_ENGINE_VP); +		disable |= (1ULL << NVDEV_ENGINE_PPP); +	} + +	if (!(r00154c & 0x00000004)) +		disable |= (1ULL << NVDEV_ENGINE_DISP); +	if (!(r00154c & 0x00000020)) +		disable |= (1ULL << NVDEV_ENGINE_BSP); +	if (!(r00154c & 0x00000200)) +		disable |= (1ULL << NVDEV_ENGINE_COPY0); + +	return disable; +} -	priv->base.pll_set = nva3_devinit_pll_set; -	return 0; +static u32 +nva3_devinit_mmio_part[] = { +	0x100720, 0x1008bc, 4, +	0x100a20, 0x100adc, 4, +	0x100d80, 0x100ddc, 4, +	0x110000, 0x110f9c, 4, +	0x111000, 0x11103c, 8, +	0x111080, 0x1110fc, 4, +	0x111120, 0x1111fc, 4, +	0x111300, 0x1114bc, 4, +	0, +}; + +static u32 +nva3_devinit_mmio(struct nouveau_devinit *devinit, u32 addr) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 *mmio = nva3_devinit_mmio_part; + +	/* the init tables on some boards have INIT_RAM_RESTRICT_ZM_REG_GROUP +	 * instructions which touch registers that may not even exist on +	 * some configurations (Quadro 400), which causes the register +	 * interface to screw up for some amount of time after attempting to +	 * write to one of these, and results in all sorts of things going +	 * horribly wrong. +	 * +	 * the binary driver avoids touching these registers at all, however, +	 * the video bios doesn't care and does what the scripts say.  it's +	 * presumed that the io-port access to priv registers isn't effected +	 * by the screw-up bug mentioned above. +	 * +	 * really, a new opcode should've been invented to handle these +	 * requirements, but whatever, it's too late for that now. +	 */ +	while (mmio[0]) { +		if (addr >= mmio[0] && addr <= mmio[1]) { +			u32 part = (addr / mmio[2]) & 7; +			if (!priv->r001540) +				priv->r001540 = nv_rd32(priv, 0x001540); +			if (part >= hweight8((priv->r001540 >> 16) & 0xff)) +				return ~0; +			return addr; +		} +		mmio += 3; +	} + +	return addr;  } -struct nouveau_oclass -nva3_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0xa3), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nva3_devinit_ctor, +struct nouveau_oclass * +nva3_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0xa3), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_devinit_ctor,  		.dtor = _nouveau_devinit_dtor,  		.init = nv50_devinit_init,  		.fini = _nouveau_devinit_fini,  	}, -}; +	.pll_set = nva3_devinit_pll_set, +	.disable = nva3_devinit_disable, +	.mmio    = nva3_devinit_mmio, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c new file mode 100644 index 00000000000..4fc68d27eff --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvaf.c @@ -0,0 +1,63 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +static u64 +nvaf_devinit_disable(struct nouveau_devinit *devinit) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r001540 = nv_rd32(priv, 0x001540); +	u32 r00154c = nv_rd32(priv, 0x00154c); +	u64 disable = 0; + +	if (!(r001540 & 0x40000000)) { +		disable |= (1ULL << NVDEV_ENGINE_VP); +		disable |= (1ULL << NVDEV_ENGINE_PPP); +	} + +	if (!(r00154c & 0x00000004)) +		disable |= (1ULL << NVDEV_ENGINE_DISP); +	if (!(r00154c & 0x00000020)) +		disable |= (1ULL << NVDEV_ENGINE_BSP); +	if (!(r00154c & 0x00000040)) +		disable |= (1ULL << NVDEV_ENGINE_VIC); +	if (!(r00154c & 0x00000200)) +		disable |= (1ULL << NVDEV_ENGINE_COPY0); + +	return disable; +} + +struct nouveau_oclass * +nvaf_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0xaf), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_devinit_ctor, +		.dtor = _nouveau_devinit_dtor, +		.init = nv50_devinit_init, +		.fini = _nouveau_devinit_fini, +	}, +	.pll_set = nva3_devinit_pll_set, +	.disable = nvaf_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c index 19e265bf457..30c765747ee 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/nvc0.c @@ -22,12 +22,12 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv50.h" -static int +int  nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)  { -	struct nvc0_devinit_priv *priv = (void *)devinit; +	struct nv50_devinit_priv *priv = (void *)devinit;  	struct nouveau_bios *bios = nouveau_bios(priv);  	struct nvbios_pll info;  	int N, fN, M, P; @@ -59,6 +59,33 @@ nvc0_devinit_pll_set(struct nouveau_devinit *devinit, u32 type, u32 freq)  	return ret;  } +static u64 +nvc0_devinit_disable(struct nouveau_devinit *devinit) +{ +	struct nv50_devinit_priv *priv = (void *)devinit; +	u32 r022500 = nv_rd32(priv, 0x022500); +	u64 disable = 0ULL; + +	if (r022500 & 0x00000001) +		disable |= (1ULL << NVDEV_ENGINE_DISP); + +	if (r022500 & 0x00000002) { +		disable |= (1ULL << NVDEV_ENGINE_VP); +		disable |= (1ULL << NVDEV_ENGINE_PPP); +	} + +	if (r022500 & 0x00000004) +		disable |= (1ULL << NVDEV_ENGINE_BSP); +	if (r022500 & 0x00000008) +		disable |= (1ULL << NVDEV_ENGINE_VENC); +	if (r022500 & 0x00000100) +		disable |= (1ULL << NVDEV_ENGINE_COPY0); +	if (r022500 & 0x00000200) +		disable |= (1ULL << NVDEV_ENGINE_COPY1); + +	return disable; +} +  static int  nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		  struct nouveau_oclass *oclass, void *data, u32 size, @@ -72,19 +99,20 @@ nvc0_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; -	priv->base.pll_set = nvc0_devinit_pll_set;  	if (nv_rd32(priv, 0x022500) & 0x00000001)  		priv->base.post = true;  	return 0;  } -struct nouveau_oclass -nvc0_devinit_oclass = { -	.handle = NV_SUBDEV(DEVINIT, 0xc0), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nvc0_devinit_oclass = &(struct nouveau_devinit_impl) { +	.base.handle = NV_SUBDEV(DEVINIT, 0xc0), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvc0_devinit_ctor,  		.dtor = _nouveau_devinit_dtor,  		.init = nv50_devinit_init,  		.fini = _nouveau_devinit_fini,  	}, -}; +	.pll_set = nvc0_devinit_pll_set, +	.disable = nvc0_devinit_disable, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h index 7d622e2b017..f0e8683ad84 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/devinit/priv.h @@ -6,20 +6,33 @@  #include <subdev/clock/pll.h>  #include <subdev/devinit.h> -void nv04_devinit_dtor(struct nouveau_object *); -int  nv04_devinit_init(struct nouveau_object *); -int  nv04_devinit_fini(struct nouveau_object *, bool); -int  nv04_devinit_pll_set(struct nouveau_devinit *, u32, u32); - -void setPLL_single(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); -void setPLL_double_highregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); -void setPLL_double_lowregs(struct nouveau_devinit *, u32, struct nouveau_pll_vals *); - - -struct nv50_devinit_priv { -	struct nouveau_devinit base; +struct nouveau_devinit_impl { +	struct nouveau_oclass base; +	void (*meminit)(struct nouveau_devinit *); +	int  (*pll_set)(struct nouveau_devinit *, u32 type, u32 freq); +	u64  (*disable)(struct nouveau_devinit *); +	u32  (*mmio)(struct nouveau_devinit *, u32);  }; -int  nv50_devinit_init(struct nouveau_object *); +#define nouveau_devinit_create(p,e,o,d)                                        \ +	nouveau_devinit_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_devinit_destroy(p) ({                                          \ +	struct nouveau_devinit *d = (p);                                       \ +	_nouveau_devinit_dtor(nv_object(d));                                   \ +}) +#define nouveau_devinit_init(p) ({                                             \ +	struct nouveau_devinit *d = (p);                                       \ +	_nouveau_devinit_init(nv_object(d));                                   \ +}) +#define nouveau_devinit_fini(p,s) ({                                           \ +	struct nouveau_devinit *d = (p);                                       \ +	_nouveau_devinit_fini(nv_object(d), (s));                              \ +}) + +int nouveau_devinit_create_(struct nouveau_object *, struct nouveau_object *, +			    struct nouveau_oclass *, int, void **); +void _nouveau_devinit_dtor(struct nouveau_object *); +int _nouveau_devinit_init(struct nouveau_object *); +int _nouveau_devinit_fini(struct nouveau_object *, bool suspend);  #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c index 821cd75b86a..f009d8a39d9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c @@ -22,9 +22,10 @@   * Authors: Ben Skeggs   */ -#include "subdev/fb.h" -#include "subdev/bios.h" -#include "subdev/bios/bit.h" +#include <subdev/bios.h> +#include <subdev/bios/bit.h> + +#include "priv.h"  int  nouveau_fb_bios_memtype(struct nouveau_bios *bios) @@ -106,9 +107,9 @@ _nouveau_fb_dtor(struct nouveau_object *object)  int  nouveau_fb_create_(struct nouveau_object *parent, struct nouveau_object *engine, -		   struct nouveau_oclass *oclass, struct nouveau_oclass *ramcls, -		   int length, void **pobject) +		   struct nouveau_oclass *oclass, int length, void **pobject)  { +	struct nouveau_fb_impl *impl = (void *)oclass;  	static const char *name[] = {  		[NV_MEM_TYPE_UNKNOWN] = "unknown",  		[NV_MEM_TYPE_STOLEN ] = "stolen system memory", @@ -132,8 +133,10 @@ nouveau_fb_create_(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; +	pfb->memtype_valid = impl->memtype; +  	ret = nouveau_object_ctor(nv_object(pfb), nv_object(pfb), -				  ramcls, NULL, 0, &ram); +				  impl->ram, NULL, 0, &ram);  	if (ret) {  		nv_fatal(pfb, "error detecting memory configuration!!\n");  		return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c new file mode 100644 index 00000000000..66fe959b4f7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gddr5.c @@ -0,0 +1,122 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include <subdev/bios.h> +#include "priv.h" + +/* binary driver only executes this path if the condition (a) is true + * for any configuration (combination of rammap+ramcfg+timing) that + * can be reached on a given card.  for now, we will execute the branch + * unconditionally in the hope that a "false everywhere" in the bios + * tables doesn't actually mean "don't touch this". + */ +#define NOTE00(a) 1 + +int +nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts) +{ +	int pd, lf, xd, vh, vr, vo, l3; +	int WL, CL, WR, at[2], dt, ds; +	int rq = ram->freq < 1000000; /* XXX */ + +	switch (ram->ramcfg.version) { +	case 0x11: +		pd =  ram->next->bios.ramcfg_11_01_80; +		lf =  ram->next->bios.ramcfg_11_01_40; +		xd = !ram->next->bios.ramcfg_11_01_20; +		vh =  ram->next->bios.ramcfg_11_02_10; +		vr =  ram->next->bios.ramcfg_11_02_04; +		vo =  ram->next->bios.ramcfg_11_06; +		l3 = !ram->next->bios.ramcfg_11_07_02; +		break; +	default: +		return -ENOSYS; +	} + +	switch (ram->timing.version) { +	case 0x20: +		WL = (ram->next->bios.timing[1] & 0x00000f80) >> 7; +		CL = (ram->next->bios.timing[1] & 0x0000001f); +		WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; +		at[0] = ram->next->bios.timing_20_2e_c0; +		at[1] = ram->next->bios.timing_20_2e_30; +		dt =  ram->next->bios.timing_20_2e_03; +		ds =  ram->next->bios.timing_20_2f_03; +		break; +	default: +		return -ENOSYS; +	} + +	if (WL < 1 || WL > 7 || CL < 5 || CL > 36 || WR < 4 || WR > 35) +		return -EINVAL; +	CL -= 5; +	WR -= 4; + +	ram->mr[0] &= ~0xf7f; +	ram->mr[0] |= (WR & 0x0f) << 8; +	ram->mr[0] |= (CL & 0x0f) << 3; +	ram->mr[0] |= (WL & 0x07) << 0; + +	ram->mr[1] &= ~0x0bf; +	ram->mr[1] |= (xd & 0x01) << 7; +	ram->mr[1] |= (at[0] & 0x03) << 4; +	ram->mr[1] |= (dt & 0x03) << 2; +	ram->mr[1] |= (ds & 0x03) << 0; + +	/* this seems wrong, alternate field used for the broadcast +	 * on nuts vs non-nuts configs..  meh, it matches for now. +	 */ +	ram->mr1_nuts = ram->mr[1]; +	if (nuts) { +		ram->mr[1] &= ~0x030; +		ram->mr[1] |= (at[1] & 0x03) << 4; +	} + +	ram->mr[3] &= ~0x020; +	ram->mr[3] |= (rq & 0x01) << 5; + +	ram->mr[5] &= ~0x004; +	ram->mr[5] |= (l3 << 2); + +	if (!vo) +		vo = (ram->mr[6] & 0xff0) >> 4; +	if (ram->mr[6] & 0x001) +		pd = 1; /* binary driver does this.. bug? */ +	ram->mr[6] &= ~0xff1; +	ram->mr[6] |= (vo & 0xff) << 4; +	ram->mr[6] |= (pd & 0x01) << 0; + +	if (NOTE00(vr)) { +		ram->mr[7] &= ~0x300; +		ram->mr[7] |= (vr & 0x03) << 8; +	} +	ram->mr[7] &= ~0x088; +	ram->mr[7] |= (vh & 0x01) << 7; +	ram->mr[7] |= (lf & 0x01) << 3; + +	ram->mr[8] &= ~0x003; +	ram->mr[8] |= (WR & 0x10) >> 3; +	ram->mr[8] |= (CL & 0x10) >> 4; +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c new file mode 100644 index 00000000000..a16024a7477 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gk20a.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "nvc0.h" + +struct gk20a_fb_priv { +	struct nouveau_fb base; +}; + +static int +gk20a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	     struct nouveau_oclass *oclass, void *data, u32 size, +	     struct nouveau_object **pobject) +{ +	struct gk20a_fb_priv *priv; +	int ret; + +	ret = nouveau_fb_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	return 0; +} + +struct nouveau_oclass * +gk20a_fb_oclass = &(struct nouveau_fb_impl) { +	.base.handle = NV_SUBDEV(FB, 0xea), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = gk20a_fb_ctor, +		.dtor = _nouveau_fb_dtor, +		.init = _nouveau_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.memtype = nvc0_fb_memtype_valid, +	.ram = &gk20a_ram_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c new file mode 100644 index 00000000000..c4840aedc2d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/gm107.c @@ -0,0 +1,38 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nvc0.h" + +struct nouveau_oclass * +gm107_fb_oclass = &(struct nouveau_fb_impl) { +	.base.handle = NV_SUBDEV(FB, 0x07), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_fb_ctor, +		.dtor = nvc0_fb_dtor, +		.init = nvc0_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.memtype = nvc0_fb_memtype_valid, +	.ram = &gm107_ram_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c index 1f103c7b89f..8309fe33fe8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.c @@ -22,14 +22,10 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv04.h"  #define NV04_PFB_CFG0						0x00100200 -struct nv04_fb_priv { -	struct nouveau_fb base; -}; -  bool  nv04_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)  { @@ -57,30 +53,37 @@ nv04_fb_init(struct nouveau_object *object)  	return 0;  } -static int +int  nv04_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	     struct nouveau_oclass *oclass, void *data, u32 size,  	     struct nouveau_object **pobject)  { +	struct nv04_fb_impl *impl = (void *)oclass;  	struct nv04_fb_priv *priv;  	int ret; -	ret = nouveau_fb_create(parent, engine, oclass, &nv04_ram_oclass, &priv); +	ret = nouveau_fb_create(parent, engine, oclass, &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; -	priv->base.memtype_valid = nv04_fb_memtype_valid; +	priv->base.tile.regions = impl->tile.regions; +	priv->base.tile.init = impl->tile.init; +	priv->base.tile.comp = impl->tile.comp; +	priv->base.tile.fini = impl->tile.fini; +	priv->base.tile.prog = impl->tile.prog;  	return 0;  } -struct nouveau_oclass -nv04_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x04), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv04_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv04_ram_oclass, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.h new file mode 100644 index 00000000000..06ce71f87a7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv04.h @@ -0,0 +1,55 @@ +#ifndef __NVKM_FB_NV04_H__ +#define __NVKM_FB_NV04_H__ + +#include "priv.h" + +struct nv04_fb_priv { +	struct nouveau_fb base; +}; + +int  nv04_fb_ctor(struct nouveau_object *, struct nouveau_object *, +		  struct nouveau_oclass *, void *, u32, +		  struct nouveau_object **); + +struct nv04_fb_impl { +	struct nouveau_fb_impl base; +	struct { +		int regions; +		void (*init)(struct nouveau_fb *, int i, u32 addr, u32 size, +			     u32 pitch, u32 flags, struct nouveau_fb_tile *); +		void (*comp)(struct nouveau_fb *, int i, u32 size, u32 flags, +			     struct nouveau_fb_tile *); +		void (*fini)(struct nouveau_fb *, int i, +			     struct nouveau_fb_tile *); +		void (*prog)(struct nouveau_fb *, int i, +			     struct nouveau_fb_tile *); +	} tile; +}; + +void nv10_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, +		       u32 pitch, u32 flags, struct nouveau_fb_tile *); +void nv10_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); +void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +void nv20_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, +		       u32 pitch, u32 flags, struct nouveau_fb_tile *); +void nv20_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); +void nv20_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +int  nv30_fb_init(struct nouveau_object *); +void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, +		       u32 pitch, u32 flags, struct nouveau_fb_tile *); + +void nv40_fb_tile_comp(struct nouveau_fb *, int i, u32 size, u32 flags, +		       struct nouveau_fb_tile *); + +int  nv41_fb_init(struct nouveau_object *); +void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +int  nv44_fb_init(struct nouveau_object *); +void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); + +void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, +		       u32 pitch, u32 flags, struct nouveau_fb_tile *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c index be069b5306b..ffb7ec6d97a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv10.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv10_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  void  nv10_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, @@ -57,34 +53,19 @@ nv10_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)  	nv_rd32(pfb, 0x100240 + (i * 0x10));  } -static int -nv10_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv10_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv10_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv10_fb_tile_init; -	priv->base.tile.fini = nv10_fb_tile_fini; -	priv->base.tile.prog = nv10_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv10_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x10), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv10_fb_ctor, +struct nouveau_oclass * +nv10_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x10), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = _nouveau_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv10_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv10_fb_tile_init, +	.tile.fini = nv10_fb_tile_fini, +	.tile.prog = nv10_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c index 57a2af0079b..265d1253624 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv1a.c @@ -24,40 +24,21 @@   *   */ -#include "priv.h" +#include "nv04.h" -struct nv1a_fb_priv { -	struct nouveau_fb base; -}; - -static int -nv1a_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv1a_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv1a_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv10_fb_tile_init; -	priv->base.tile.fini = nv10_fb_tile_fini; -	priv->base.tile.prog = nv10_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv1a_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x1a), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv1a_fb_ctor, +struct nouveau_oclass * +nv1a_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x1a), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = _nouveau_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv1a_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv10_fb_tile_init, +	.tile.fini = nv10_fb_tile_fini, +	.tile.prog = nv10_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c index b18c4e63bb4..f003c1b1893 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv20_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  void  nv20_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, @@ -80,35 +76,20 @@ nv20_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)  	nv_wr32(pfb, 0x100300 + (i * 0x04), tile->zcomp);  } -static int -nv20_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv20_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv20_fb_tile_init; -	priv->base.tile.comp = nv20_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv20_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv20_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x20), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv20_fb_ctor, +struct nouveau_oclass * +nv20_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x20), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = _nouveau_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv20_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv20_fb_tile_init, +	.tile.comp = nv20_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv20_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c index 32ccabf10c4..f34f4223210 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv25_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  static void  nv25_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, @@ -46,35 +42,20 @@ nv25_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,  	}  } -static int -nv25_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv25_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv20_fb_tile_init; -	priv->base.tile.comp = nv25_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv20_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv25_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x25), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv25_fb_ctor, +struct nouveau_oclass * +nv25_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x25), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = _nouveau_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv20_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv20_fb_tile_init, +	.tile.comp = nv25_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv20_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c index bef756d43d3..69093f7151f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv30.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv30_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  void  nv30_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, @@ -67,7 +63,7 @@ nv30_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,  }  static int -calc_bias(struct nv30_fb_priv *priv, int k, int i, int j) +calc_bias(struct nv04_fb_priv *priv, int k, int i, int j)  {  	struct nouveau_device *device = nv_device(priv);  	int b = (device->chipset > 0x30 ? @@ -78,7 +74,7 @@ calc_bias(struct nv30_fb_priv *priv, int k, int i, int j)  }  static int -calc_ref(struct nv30_fb_priv *priv, int l, int k, int i) +calc_ref(struct nv04_fb_priv *priv, int l, int k, int i)  {  	int j, x = 0; @@ -95,7 +91,7 @@ int  nv30_fb_init(struct nouveau_object *object)  {  	struct nouveau_device *device = nv_device(object); -	struct nv30_fb_priv *priv = (void *)object; +	struct nv04_fb_priv *priv = (void *)object;  	int ret, i, j;  	ret = nouveau_fb_init(&priv->base); @@ -124,35 +120,20 @@ nv30_fb_init(struct nouveau_object *object)  	return 0;  } -static int -nv30_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv30_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv30_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv20_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv30_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x30), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv30_fb_ctor, +struct nouveau_oclass * +nv30_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x30), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv30_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv20_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv30_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv20_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c index 097d8e3824f..161b06e8fc3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv35.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv35_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  static void  nv35_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, @@ -47,35 +43,20 @@ nv35_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,  	}  } -static int -nv35_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv35_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv35_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv20_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv35_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x35), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv35_fb_ctor, +struct nouveau_oclass * +nv35_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x35), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv30_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv20_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv35_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv20_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv36.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv36.c index 9d6d9df896d..2dd3d0aab6b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv36.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv36.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv36_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  static void  nv36_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, @@ -47,35 +43,20 @@ nv36_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,  	}  } -static int -nv36_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv36_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv20_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv36_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv20_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv36_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x36), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv36_fb_ctor, +struct nouveau_oclass * +nv36_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x36), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv30_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv20_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv36_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv20_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c index 33b4393a782..95a115ab0c8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv40_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  void  nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags, @@ -50,7 +46,7 @@ nv40_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,  static int  nv40_fb_init(struct nouveau_object *object)  { -	struct nv40_fb_priv *priv = (void *)object; +	struct nv04_fb_priv *priv = (void *)object;  	int ret;  	ret = nouveau_fb_init(&priv->base); @@ -61,36 +57,20 @@ nv40_fb_init(struct nouveau_object *object)  	return 0;  } -static int -nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv40_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv40_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 8; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv40_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv20_fb_tile_prog; -	return 0; -} - - -struct nouveau_oclass -nv40_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x40), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv40_fb_ctor, +struct nouveau_oclass * +nv40_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x40), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv40_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv40_ram_oclass, +	.tile.regions = 8, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv40_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv20_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.h b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.h new file mode 100644 index 00000000000..581f808527f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv40.h @@ -0,0 +1,17 @@ +#ifndef __NVKM_FB_NV40_H__ +#define __NVKM_FB_NV40_H__ + +#include "priv.h" + +struct nv40_ram { +	struct nouveau_ram base; +	u32 ctrl; +	u32 coef; +}; + + +int  nv40_ram_calc(struct nouveau_fb *, u32); +int  nv40_ram_prog(struct nouveau_fb *); +void nv40_ram_tidy(struct nouveau_fb *); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c index 02cd83789cd..b239a861559 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv41.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv41_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  void  nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile) @@ -43,7 +39,7 @@ nv41_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)  int  nv41_fb_init(struct nouveau_object *object)  { -	struct nv41_fb_priv *priv = (void *)object; +	struct nv04_fb_priv *priv = (void *)object;  	int ret;  	ret = nouveau_fb_init(&priv->base); @@ -54,36 +50,20 @@ nv41_fb_init(struct nouveau_object *object)  	return 0;  } -static int -nv41_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv41_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv41_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 12; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv40_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv41_fb_tile_prog; -	return 0; -} - - -struct nouveau_oclass -nv41_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x41), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv41_fb_ctor, +struct nouveau_oclass * +nv41_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x41), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv41_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv41_ram_oclass, +	.tile.regions = 12, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv40_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv41_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c index c5246c29f29..d8478208a68 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv44.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv44_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  static void  nv44_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, @@ -52,7 +48,7 @@ nv44_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)  int  nv44_fb_init(struct nouveau_object *object)  { -	struct nv44_fb_priv *priv = (void *)object; +	struct nv04_fb_priv *priv = (void *)object;  	int ret;  	ret = nouveau_fb_init(&priv->base); @@ -64,35 +60,19 @@ nv44_fb_init(struct nouveau_object *object)  	return 0;  } -static int -nv44_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv44_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv44_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 12; -	priv->base.tile.init = nv44_fb_tile_init; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv44_fb_tile_prog; -	return 0; -} - - -struct nouveau_oclass -nv44_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x44), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv44_fb_ctor, +struct nouveau_oclass * +nv44_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x44), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv44_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv44_ram_oclass, +	.tile.regions = 12, +	.tile.init = nv44_fb_tile_init, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv44_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c index e2b57909bfc..a5b77514d35 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv46.c @@ -24,11 +24,7 @@   *   */ -#include "priv.h" - -struct nv46_fb_priv { -	struct nouveau_fb base; -}; +#include "nv04.h"  void  nv46_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch, @@ -44,35 +40,19 @@ nv46_fb_tile_init(struct nouveau_fb *pfb, int i, u32 addr, u32 size, u32 pitch,  	tile->pitch = pitch;  } -static int -nv46_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv46_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv44_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 15; -	priv->base.tile.init = nv46_fb_tile_init; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv44_fb_tile_prog; -	return 0; -} - - -struct nouveau_oclass -nv46_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x46), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv46_fb_ctor, +struct nouveau_oclass * +nv46_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x46), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv44_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv44_ram_oclass, +	.tile.regions = 15, +	.tile.init = nv46_fb_tile_init, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv44_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c index fe6a2278621..3bea142376b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv47.c @@ -24,42 +24,22 @@   *   */ -#include "priv.h" +#include "nv04.h" -struct nv47_fb_priv { -	struct nouveau_fb base; -}; - -static int -nv47_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv47_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv41_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 15; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv40_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv41_fb_tile_prog; -	return 0; -} - - -struct nouveau_oclass -nv47_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x47), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv47_fb_ctor, +struct nouveau_oclass * +nv47_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x47), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv41_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv41_ram_oclass, +	.tile.regions = 15, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv40_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv41_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c index 5eca99b8c7e..666cbd5d47f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv49.c @@ -24,42 +24,22 @@   *   */ -#include "priv.h" +#include "nv04.h" -struct nv49_fb_priv { -	struct nouveau_fb base; -}; - -static int -nv49_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv49_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv49_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 15; -	priv->base.tile.init = nv30_fb_tile_init; -	priv->base.tile.comp = nv40_fb_tile_comp; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv41_fb_tile_prog; -	return 0; -} - - -struct nouveau_oclass -nv49_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x49), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv49_fb_ctor, +struct nouveau_oclass * +nv49_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x49), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv41_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv49_ram_oclass, +	.tile.regions = 15, +	.tile.init = nv30_fb_tile_init, +	.tile.comp = nv40_fb_tile_comp, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv41_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c index 1190b78a1e9..42e64f364ec 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv4e.c @@ -24,40 +24,21 @@   *   */ -#include "priv.h" +#include "nv04.h" -struct nv4e_fb_priv { -	struct nouveau_fb base; -}; - -static int -nv4e_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv4e_fb_priv *priv; -	int ret; - -	ret = nouveau_fb_create(parent, engine, oclass, &nv4e_ram_oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.memtype_valid = nv04_fb_memtype_valid; -	priv->base.tile.regions = 12; -	priv->base.tile.init = nv46_fb_tile_init; -	priv->base.tile.fini = nv20_fb_tile_fini; -	priv->base.tile.prog = nv44_fb_tile_prog; -	return 0; -} - -struct nouveau_oclass -nv4e_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x4e), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv4e_fb_ctor, +struct nouveau_oclass * +nv4e_fb_oclass = &(struct nv04_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x4e), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_fb_ctor,  		.dtor = _nouveau_fb_dtor,  		.init = nv44_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv04_fb_memtype_valid, +	.base.ram = &nv4e_ram_oclass, +	.tile.regions = 12, +	.tile.init = nv46_fb_tile_init, +	.tile.fini = nv20_fb_tile_fini, +	.tile.prog = nv44_fb_tile_prog, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index da614ec5564..1fc55c1e91a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -27,14 +27,9 @@  #include <core/engctx.h>  #include <core/object.h> -#include "priv.h"  #include <subdev/bios.h> -struct nv50_fb_priv { -	struct nouveau_fb base; -	struct page *r100c08_page; -	dma_addr_t r100c08; -}; +#include "nv50.h"  int  nv50_fb_memtype[0x80] = { @@ -48,7 +43,7 @@ nv50_fb_memtype[0x80] = {  	1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0  }; -static bool +bool  nv50_fb_memtype_valid(struct nouveau_fb *pfb, u32 memtype)  {  	return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0; @@ -239,7 +234,7 @@ nv50_fb_intr(struct nouveau_subdev *subdev)  		pr_cont("0x%08x\n", st1);  } -static int +int  nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	     struct nouveau_oclass *oclass, void *data, u32 size,  	     struct nouveau_object **pobject) @@ -248,46 +243,42 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nv50_fb_priv *priv;  	int ret; -	ret = nouveau_fb_create(parent, engine, oclass, &nv50_ram_oclass, &priv); +	ret = nouveau_fb_create(parent, engine, oclass, &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret;  	priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);  	if (priv->r100c08_page) { -		priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page, -					     0, PAGE_SIZE, -					     PCI_DMA_BIDIRECTIONAL); -		if (pci_dma_mapping_error(device->pdev, priv->r100c08)) +		priv->r100c08 = nv_device_map_page(device, priv->r100c08_page); +		if (!priv->r100c08)  			nv_warn(priv, "failed 0x100c08 page map\n");  	} else {  		nv_warn(priv, "failed 0x100c08 page alloc\n");  	} -	priv->base.memtype_valid = nv50_fb_memtype_valid;  	nv_subdev(priv)->intr = nv50_fb_intr;  	return 0;  } -static void +void  nv50_fb_dtor(struct nouveau_object *object)  {  	struct nouveau_device *device = nv_device(object);  	struct nv50_fb_priv *priv = (void *)object;  	if (priv->r100c08_page) { -		pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE, -			       PCI_DMA_BIDIRECTIONAL); +		nv_device_unmap_page(device, priv->r100c08);  		__free_page(priv->r100c08_page);  	}  	nouveau_fb_destroy(&priv->base);  } -static int +int  nv50_fb_init(struct nouveau_object *object)  { -	struct nouveau_device *device = nv_device(object); +	struct nv50_fb_impl *impl = (void *)object->oclass;  	struct nv50_fb_priv *priv = (void *)object;  	int ret; @@ -303,33 +294,20 @@ nv50_fb_init(struct nouveau_object *object)  	/* This is needed to get meaningful information from 100c90  	 * on traps. No idea what these values mean exactly. */ -	switch (device->chipset) { -	case 0x50: -		nv_wr32(priv, 0x100c90, 0x000707ff); -		break; -	case 0xa3: -	case 0xa5: -	case 0xa8: -		nv_wr32(priv, 0x100c90, 0x000d0fff); -		break; -	case 0xaf: -		nv_wr32(priv, 0x100c90, 0x089d1fff); -		break; -	default: -		nv_wr32(priv, 0x100c90, 0x001d07ff); -		break; -	} - +	nv_wr32(priv, 0x100c90, impl->trap);  	return 0;  } -struct nouveau_oclass -nv50_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_fb_oclass = &(struct nv50_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x50), +	.base.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_fb_ctor,  		.dtor = nv50_fb_dtor,  		.init = nv50_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.base.memtype = nv50_fb_memtype_valid, +	.base.ram = &nv50_ram_oclass, +	.trap = 0x000707ff, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h new file mode 100644 index 00000000000..c5e5a888c60 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.h @@ -0,0 +1,33 @@ +#ifndef __NVKM_FB_NV50_H__ +#define __NVKM_FB_NV50_H__ + +#include "priv.h" + +struct nv50_fb_priv { +	struct nouveau_fb base; +	struct page *r100c08_page; +	dma_addr_t r100c08; +}; + +int  nv50_fb_ctor(struct nouveau_object *, struct nouveau_object *, +		  struct nouveau_oclass *, void *, u32, +		  struct nouveau_object **); +void nv50_fb_dtor(struct nouveau_object *); +int  nv50_fb_init(struct nouveau_object *); + +struct nv50_fb_impl { +	struct nouveau_fb_impl base; +	u32 trap; +}; + +#define nv50_ram_create(p,e,o,d)                                               \ +	nv50_ram_create_((p), (e), (o), sizeof(**d), (void **)d) +int  nv50_ram_create_(struct nouveau_object *, struct nouveau_object *, +		      struct nouveau_oclass *, int, void **); +int  nv50_ram_get(struct nouveau_fb *, u64 size, u32 align, u32 ncmin, +		  u32 memtype, struct nouveau_mem **); +void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **); +void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *); +extern int nv50_fb_memtype[0x80]; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv84.c new file mode 100644 index 00000000000..cf0e767d383 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv84.c @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +struct nouveau_oclass * +nv84_fb_oclass = &(struct nv50_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0x84), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_fb_ctor, +		.dtor = nv50_fb_dtor, +		.init = nv50_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.base.memtype = nv50_fb_memtype_valid, +	.base.ram = &nv50_ram_oclass, +	.trap = 0x001d07ff, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nva3.c new file mode 100644 index 00000000000..dab6e1c63d4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nva3.c @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +struct nouveau_oclass * +nva3_fb_oclass = &(struct nv50_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0xa3), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_fb_ctor, +		.dtor = nv50_fb_dtor, +		.init = nv50_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.base.memtype = nv50_fb_memtype_valid, +	.base.ram = &nva3_ram_oclass, +	.trap = 0x000d0fff, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c new file mode 100644 index 00000000000..cba8e681803 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaa.c @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +struct nouveau_oclass * +nvaa_fb_oclass = &(struct nv50_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0xaa), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_fb_ctor, +		.dtor = nv50_fb_dtor, +		.init = nv50_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.base.memtype = nv50_fb_memtype_valid, +	.base.ram = &nvaa_ram_oclass, +	.trap = 0x001d07ff, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvaf.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaf.c new file mode 100644 index 00000000000..5423faa2c09 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvaf.c @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +struct nouveau_oclass * +nvaf_fb_oclass = &(struct nv50_fb_impl) { +	.base.base.handle = NV_SUBDEV(FB, 0xaf), +	.base.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv50_fb_ctor, +		.dtor = nv50_fb_dtor, +		.init = nv50_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.base.memtype = nv50_fb_memtype_valid, +	.base.ram = &nvaa_ram_oclass, +	.trap = 0x089d1fff, +}.base.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index f35d76fd746..0670ae33ee4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c @@ -22,24 +22,33 @@   * Authors: Ben Skeggs   */ -#include "priv.h" - -struct nvc0_fb_priv { -	struct nouveau_fb base; -	struct page *r100c10_page; -	dma_addr_t r100c10; -}; +#include "nvc0.h"  extern const u8 nvc0_pte_storage_type_map[256]; -static bool +bool  nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags)  {  	u8 memtype = (tile_flags & 0x0000ff00) >> 8;  	return likely((nvc0_pte_storage_type_map[memtype] != 0xff));  } -static int +static void +nvc0_fb_intr(struct nouveau_subdev *subdev) +{ +	struct nvc0_fb_priv *priv = (void *)subdev; +	u32 intr = nv_rd32(priv, 0x000100); +	if (intr & 0x08000000) { +		nv_debug(priv, "PFFB intr\n"); +		intr &= ~0x08000000; +	} +	if (intr & 0x00002000) { +		nv_debug(priv, "PBFB intr\n"); +		intr &= ~0x00002000; +	} +} + +int  nvc0_fb_init(struct nouveau_object *object)  {  	struct nvc0_fb_priv *priv = (void *)object; @@ -54,22 +63,21 @@ nvc0_fb_init(struct nouveau_object *object)  	return 0;  } -static void +void  nvc0_fb_dtor(struct nouveau_object *object)  {  	struct nouveau_device *device = nv_device(object);  	struct nvc0_fb_priv *priv = (void *)object;  	if (priv->r100c10_page) { -		pci_unmap_page(device->pdev, priv->r100c10, PAGE_SIZE, -			       PCI_DMA_BIDIRECTIONAL); +		nv_device_unmap_page(device, priv->r100c10);  		__free_page(priv->r100c10_page);  	}  	nouveau_fb_destroy(&priv->base);  } -static int +int  nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	     struct nouveau_oclass *oclass, void *data, u32 size,  	     struct nouveau_object **pobject) @@ -78,33 +86,31 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nvc0_fb_priv *priv;  	int ret; -	ret = nouveau_fb_create(parent, engine, oclass, &nvc0_ram_oclass, &priv); +	ret = nouveau_fb_create(parent, engine, oclass, &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; -	priv->base.memtype_valid = nvc0_fb_memtype_valid; -  	priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);  	if (priv->r100c10_page) { -		priv->r100c10 = pci_map_page(device->pdev, priv->r100c10_page, -					     0, PAGE_SIZE, -					     PCI_DMA_BIDIRECTIONAL); -		if (pci_dma_mapping_error(device->pdev, priv->r100c10)) +		priv->r100c10 = nv_device_map_page(device, priv->r100c10_page); +		if (!priv->r100c10)  			return -EFAULT;  	} +	nv_subdev(priv)->intr = nvc0_fb_intr;  	return 0;  } - -struct nouveau_oclass -nvc0_fb_oclass = { -	.handle = NV_SUBDEV(FB, 0xc0), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nvc0_fb_oclass = &(struct nouveau_fb_impl) { +	.base.handle = NV_SUBDEV(FB, 0xc0), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nvc0_fb_ctor,  		.dtor = nvc0_fb_dtor,  		.init = nvc0_fb_init,  		.fini = _nouveau_fb_fini,  	}, -}; +	.memtype = nvc0_fb_memtype_valid, +	.ram = &nvc0_ram_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h new file mode 100644 index 00000000000..705a06d755a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.h @@ -0,0 +1,31 @@ +#ifndef __NVKM_RAM_NVC0_H__ +#define __NVKM_RAM_NVC0_H__ + +#include "priv.h" +#include "nv50.h" + +struct nvc0_fb_priv { +	struct nouveau_fb base; +	struct page *r100c10_page; +	dma_addr_t r100c10; +}; + +int  nvc0_fb_ctor(struct nouveau_object *, struct nouveau_object *, +		  struct nouveau_oclass *, void *, u32, +		  struct nouveau_object **); +void nvc0_fb_dtor(struct nouveau_object *); +int  nvc0_fb_init(struct nouveau_object *); +bool nvc0_fb_memtype_valid(struct nouveau_fb *, u32); + + +#define nvc0_ram_create(p,e,o,m,d)                                             \ +	nvc0_ram_create_((p), (e), (o), (m), sizeof(**d), (void **)d) +int  nvc0_ram_create_(struct nouveau_object *, struct nouveau_object *, +		      struct nouveau_oclass *, u32, int, void **); +int  nvc0_ram_get(struct nouveau_fb *, u64, u32, u32, u32, +		  struct nouveau_mem **); +void nvc0_ram_put(struct nouveau_fb *, struct nouveau_mem **); + +int  nve0_ram_init(struct nouveau_object*); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nve0.c new file mode 100644 index 00000000000..595db50cfef --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nve0.c @@ -0,0 +1,38 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nvc0.h" + +struct nouveau_oclass * +nve0_fb_oclass = &(struct nouveau_fb_impl) { +	.base.handle = NV_SUBDEV(FB, 0xe0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_fb_ctor, +		.dtor = nvc0_fb_dtor, +		.init = nvc0_fb_init, +		.fini = _nouveau_fb_fini, +	}, +	.memtype = nvc0_fb_memtype_valid, +	.ram = &nve0_ram_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h index db9d6ddde52..82273f832e4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h @@ -12,6 +12,8 @@  #define nouveau_ram_fini(p,s)                                                  \  	nouveau_object_fini(&(p)->base, (s)) +#define nouveau_ram_create_(p,e,o,s,d)                                         \ +	nouveau_object_create_((p), (e), (o), 0, (s), (void **)d)  #define _nouveau_ram_dtor nouveau_object_destroy  #define _nouveau_ram_init nouveau_object_init  #define _nouveau_ram_fini nouveau_object_fini @@ -26,10 +28,18 @@ extern struct nouveau_oclass nv44_ram_oclass;  extern struct nouveau_oclass nv49_ram_oclass;  extern struct nouveau_oclass nv4e_ram_oclass;  extern struct nouveau_oclass nv50_ram_oclass; +extern struct nouveau_oclass nva3_ram_oclass; +extern struct nouveau_oclass nvaa_ram_oclass;  extern struct nouveau_oclass nvc0_ram_oclass; +extern struct nouveau_oclass nve0_ram_oclass; +extern struct nouveau_oclass gk20a_ram_oclass; +extern struct nouveau_oclass gm107_ram_oclass; -#define nouveau_fb_create(p,e,c,r,d)                                           \ -	nouveau_fb_create_((p), (e), (c), (r), sizeof(**d), (void **)d) +int nouveau_sddr3_calc(struct nouveau_ram *ram); +int nouveau_gddr5_calc(struct nouveau_ram *ram, bool nuts); + +#define nouveau_fb_create(p,e,c,d)                                             \ +	nouveau_fb_create_((p), (e), (c), sizeof(**d), (void **)d)  #define nouveau_fb_destroy(p) ({                                               \  	struct nouveau_fb *pfb = (p);                                          \  	_nouveau_fb_dtor(nv_object(pfb));                                      \ @@ -44,44 +54,21 @@ extern struct nouveau_oclass nvc0_ram_oclass;  })  int nouveau_fb_create_(struct nouveau_object *, struct nouveau_object *, -		       struct nouveau_oclass *, struct nouveau_oclass *, -		       int length, void **pobject); +		       struct nouveau_oclass *, int, void **);  void _nouveau_fb_dtor(struct nouveau_object *);  int  _nouveau_fb_init(struct nouveau_object *);  int  _nouveau_fb_fini(struct nouveau_object *, bool); -struct nouveau_bios; -int  nouveau_fb_bios_memtype(struct nouveau_bios *); +struct nouveau_fb_impl { +	struct nouveau_oclass base; +	struct nouveau_oclass *ram; +	bool (*memtype)(struct nouveau_fb *, u32); +};  bool nv04_fb_memtype_valid(struct nouveau_fb *, u32 memtype); +bool nv50_fb_memtype_valid(struct nouveau_fb *, u32 memtype); -void nv10_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, -		       u32 pitch, u32 flags, struct nouveau_fb_tile *); -void nv10_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); -void nv10_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); - -void nv20_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, -		       u32 pitch, u32 flags, struct nouveau_fb_tile *); -void nv20_fb_tile_fini(struct nouveau_fb *, int i, struct nouveau_fb_tile *); -void nv20_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); - -int  nv30_fb_init(struct nouveau_object *); -void nv30_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, -		       u32 pitch, u32 flags, struct nouveau_fb_tile *); - -void nv40_fb_tile_comp(struct nouveau_fb *, int i, u32 size, u32 flags, -		       struct nouveau_fb_tile *); - -int  nv41_fb_init(struct nouveau_object *); -void nv41_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); - -int  nv44_fb_init(struct nouveau_object *); -void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *); - -void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, -		       u32 pitch, u32 flags, struct nouveau_fb_tile *); - -void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *); -extern int nv50_fb_memtype[0x80]; +struct nouveau_bios; +int  nouveau_fb_bios_memtype(struct nouveau_bios *);  #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramfuc.h b/drivers/gpu/drm/nouveau/core/subdev/fb/ramfuc.h new file mode 100644 index 00000000000..2af9cfd2c60 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramfuc.h @@ -0,0 +1,118 @@ +#ifndef __NVKM_FBRAM_FUC_H__ +#define __NVKM_FBRAM_FUC_H__ + +#include <subdev/pwr.h> + +struct ramfuc { +	struct nouveau_memx *memx; +	struct nouveau_fb *pfb; +	int sequence; +}; + +struct ramfuc_reg { +	int sequence; +	bool force; +	u32 addr[2]; +	u32 data; +}; + +static inline struct ramfuc_reg +ramfuc_reg2(u32 addr1, u32 addr2) +{ +	return (struct ramfuc_reg) { +		.sequence = 0, +		.addr = { addr1, addr2 }, +		.data = 0xdeadbeef, +	}; +} + +static noinline struct ramfuc_reg +ramfuc_reg(u32 addr) +{ +	return ramfuc_reg2(addr, addr); +} + +static inline int +ramfuc_init(struct ramfuc *ram, struct nouveau_fb *pfb) +{ +	struct nouveau_pwr *ppwr = nouveau_pwr(pfb); +	int ret; + +	ret = nouveau_memx_init(ppwr, &ram->memx); +	if (ret) +		return ret; + +	ram->sequence++; +	ram->pfb = pfb; +	return 0; +} + +static inline int +ramfuc_exec(struct ramfuc *ram, bool exec) +{ +	int ret = 0; +	if (ram->pfb) { +		ret = nouveau_memx_fini(&ram->memx, exec); +		ram->pfb = NULL; +	} +	return ret; +} + +static inline u32 +ramfuc_rd32(struct ramfuc *ram, struct ramfuc_reg *reg) +{ +	if (reg->sequence != ram->sequence) +		reg->data = nv_rd32(ram->pfb, reg->addr[0]); +	return reg->data; +} + +static inline void +ramfuc_wr32(struct ramfuc *ram, struct ramfuc_reg *reg, u32 data) +{ +	reg->sequence = ram->sequence; +	reg->data = data; +	if (reg->addr[0] != reg->addr[1]) +		nouveau_memx_wr32(ram->memx, reg->addr[1], reg->data); +	nouveau_memx_wr32(ram->memx, reg->addr[0], reg->data); +} + +static inline void +ramfuc_nuke(struct ramfuc *ram, struct ramfuc_reg *reg) +{ +	reg->force = true; +} + +static inline u32 +ramfuc_mask(struct ramfuc *ram, struct ramfuc_reg *reg, u32 mask, u32 data) +{ +	u32 temp = ramfuc_rd32(ram, reg); +	if (temp != ((temp & ~mask) | data) || reg->force) { +		ramfuc_wr32(ram, reg, (temp & ~mask) | data); +		reg->force = false; +	} +	return temp; +} + +static inline void +ramfuc_wait(struct ramfuc *ram, u32 addr, u32 mask, u32 data, u32 nsec) +{ +	nouveau_memx_wait(ram->memx, addr, mask, data, nsec); +} + +static inline void +ramfuc_nsec(struct ramfuc *ram, u32 nsec) +{ +	nouveau_memx_nsec(ram->memx, nsec); +} + +#define ram_init(s,p)       ramfuc_init(&(s)->base, (p)) +#define ram_exec(s,e)       ramfuc_exec(&(s)->base, (e)) +#define ram_have(s,r)       ((s)->r_##r.addr[0] != 0x000000) +#define ram_rd32(s,r)       ramfuc_rd32(&(s)->base, &(s)->r_##r) +#define ram_wr32(s,r,d)     ramfuc_wr32(&(s)->base, &(s)->r_##r, (d)) +#define ram_nuke(s,r)       ramfuc_nuke(&(s)->base, &(s)->r_##r) +#define ram_mask(s,r,m,d)   ramfuc_mask(&(s)->base, &(s)->r_##r, (m), (d)) +#define ram_wait(s,r,m,d,n) ramfuc_wait(&(s)->base, (r), (m), (d), (n)) +#define ram_nsec(s,n)       ramfuc_nsec(&(s)->base, (n)) + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c new file mode 100644 index 00000000000..4d77d75e467 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgk20a.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "priv.h" + +#include <subdev/fb.h> + +struct gk20a_mem { +	struct nouveau_mem base; +	void *cpuaddr; +	dma_addr_t handle; +}; +#define to_gk20a_mem(m) container_of(m, struct gk20a_mem, base) + +static void +gk20a_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) +{ +	struct device *dev = nv_device_base(nv_device(pfb)); +	struct gk20a_mem *mem = to_gk20a_mem(*pmem); + +	*pmem = NULL; +	if (unlikely(mem == NULL)) +		return; + +	if (likely(mem->cpuaddr)) +		dma_free_coherent(dev, mem->base.size << PAGE_SHIFT, +				  mem->cpuaddr, mem->handle); + +	kfree(mem->base.pages); +	kfree(mem); +} + +static int +gk20a_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, +	     u32 memtype, struct nouveau_mem **pmem) +{ +	struct device *dev = nv_device_base(nv_device(pfb)); +	struct gk20a_mem *mem; +	u32 type = memtype & 0xff; +	u32 npages, order; +	int i; + +	nv_debug(pfb, "%s: size: %llx align: %x, ncmin: %x\n", __func__, size, +		 align, ncmin); + +	npages = size >> PAGE_SHIFT; +	if (npages == 0) +		npages = 1; + +	if (align == 0) +		align = PAGE_SIZE; +	align >>= PAGE_SHIFT; + +	/* round alignment to the next power of 2, if needed */ +	order = fls(align); +	if ((align & (align - 1)) == 0) +		order--; +	align = BIT(order); + +	/* ensure returned address is correctly aligned */ +	npages = max(align, npages); + +	mem = kzalloc(sizeof(*mem), GFP_KERNEL); +	if (!mem) +		return -ENOMEM; + +	mem->base.size = npages; +	mem->base.memtype = type; + +	mem->base.pages = kzalloc(sizeof(dma_addr_t) * npages, GFP_KERNEL); +	if (!mem->base.pages) { +		kfree(mem); +		return -ENOMEM; +	} + +	*pmem = &mem->base; + +	mem->cpuaddr = dma_alloc_coherent(dev, npages << PAGE_SHIFT, +					  &mem->handle, GFP_KERNEL); +	if (!mem->cpuaddr) { +		nv_error(pfb, "%s: cannot allocate memory!\n", __func__); +		gk20a_ram_put(pfb, pmem); +		return -ENOMEM; +	} + +	align <<= PAGE_SHIFT; + +	/* alignment check */ +	if (unlikely(mem->handle & (align - 1))) +		nv_warn(pfb, "memory not aligned as requested: %pad (0x%x)\n", +			&mem->handle, align); + +	nv_debug(pfb, "alloc size: 0x%x, align: 0x%x, paddr: %pad, vaddr: %p\n", +		 npages << PAGE_SHIFT, align, &mem->handle, mem->cpuaddr); + +	for (i = 0; i < npages; i++) +		mem->base.pages[i] = mem->handle + (PAGE_SIZE * i); + +	mem->base.offset = (u64)mem->base.pages[0]; + +	return 0; +} + +static int +gk20a_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 datasize, +	      struct nouveau_object **pobject) +{ +	struct nouveau_ram *ram; +	int ret; + +	ret = nouveau_ram_create(parent, engine, oclass, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; +	ram->type = NV_MEM_TYPE_STOLEN; +	ram->size = get_num_physpages() << PAGE_SHIFT; + +	ram->get = gk20a_ram_get; +	ram->put = gk20a_ram_put; + +	return 0; +} + +struct nouveau_oclass +gk20a_ram_oclass = { +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = gk20a_ram_ctor, +		.dtor = _nouveau_ram_dtor, +		.init = _nouveau_ram_init, +		.fini = _nouveau_ram_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c new file mode 100644 index 00000000000..4c6363595c7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramgm107.c @@ -0,0 +1,56 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nvc0.h" + +struct gm107_ram { +	struct nouveau_ram base; +}; + +static int +gm107_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct gm107_ram *ram; +	int ret; + +	ret = nvc0_ram_create(parent, engine, oclass, 0x021c14, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; + +	return 0; +} + +struct nouveau_oclass +gm107_ram_oclass = { +	.handle = 0, +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = gm107_ram_ctor, +		.dtor = _nouveau_ram_dtor, +		.init = nve0_ram_init, +		.fini = _nouveau_ram_fini, +	} +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv40.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv40.c index ee49ac4dbdb..7648beb1119 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv40.c @@ -22,7 +22,154 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/pll.h> +#include <subdev/bios/init.h> +#include <subdev/clock.h> +#include <subdev/clock/pll.h> +#include <subdev/timer.h> + +#include <engine/fifo.h> + +#include "nv40.h" + +int +nv40_ram_calc(struct nouveau_fb *pfb, u32 freq) +{ +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nv40_ram *ram = (void *)pfb->ram; +	struct nvbios_pll pll; +	int N1, M1, N2, M2; +	int log2P, ret; + +	ret = nvbios_pll_parse(bios, 0x04, &pll); +	if (ret) { +		nv_error(pfb, "mclk pll data not found\n"); +		return ret; +	} + +	ret = nv04_pll_calc(nv_subdev(pfb), &pll, freq, +			    &N1, &M1, &N2, &M2, &log2P); +	if (ret < 0) +		return ret; + +	ram->ctrl  = 0x80000000 | (log2P << 16); +	ram->ctrl |= min(pll.bias_p + log2P, (int)pll.max_p) << 20; +	if (N2 == M2) { +		ram->ctrl |= 0x00000100; +		ram->coef  = (N1 << 8) | M1; +	} else { +		ram->ctrl |= 0x40000000; +		ram->coef  = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; +	} + +	return 0; +} + +int +nv40_ram_prog(struct nouveau_fb *pfb) +{ +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nv40_ram *ram = (void *)pfb->ram; +	struct bit_entry M; +	u32 crtc_mask = 0; +	u8  sr1[2]; +	int i; + +	/* determine which CRTCs are active, fetch VGA_SR1 for each */ +	for (i = 0; i < 2; i++) { +		u32 vbl = nv_rd32(pfb, 0x600808 + (i * 0x2000)); +		u32 cnt = 0; +		do { +			if (vbl != nv_rd32(pfb, 0x600808 + (i * 0x2000))) { +				nv_wr08(pfb, 0x0c03c4 + (i * 0x2000), 0x01); +				sr1[i] = nv_rd08(pfb, 0x0c03c5 + (i * 0x2000)); +				if (!(sr1[i] & 0x20)) +					crtc_mask |= (1 << i); +				break; +			} +			udelay(1); +		} while (cnt++ < 32); +	} + +	/* wait for vblank start on active crtcs, disable memory access */ +	for (i = 0; i < 2; i++) { +		if (!(crtc_mask & (1 << i))) +			continue; +		nv_wait(pfb, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); +		nv_wait(pfb, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); +		nv_wr08(pfb, 0x0c03c4 + (i * 0x2000), 0x01); +		nv_wr08(pfb, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); +	} + +	/* prepare ram for reclocking */ +	nv_wr32(pfb, 0x1002d4, 0x00000001); /* precharge */ +	nv_wr32(pfb, 0x1002d0, 0x00000001); /* refresh */ +	nv_wr32(pfb, 0x1002d0, 0x00000001); /* refresh */ +	nv_mask(pfb, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ +	nv_wr32(pfb, 0x1002dc, 0x00000001); /* enable self-refresh */ + +	/* change the PLL of each memory partition */ +	nv_mask(pfb, 0x00c040, 0x0000c000, 0x00000000); +	switch (nv_device(pfb)->chipset) { +	case 0x40: +	case 0x45: +	case 0x41: +	case 0x42: +	case 0x47: +		nv_mask(pfb, 0x004044, 0xc0771100, ram->ctrl); +		nv_mask(pfb, 0x00402c, 0xc0771100, ram->ctrl); +		nv_wr32(pfb, 0x004048, ram->coef); +		nv_wr32(pfb, 0x004030, ram->coef); +	case 0x43: +	case 0x49: +	case 0x4b: +		nv_mask(pfb, 0x004038, 0xc0771100, ram->ctrl); +		nv_wr32(pfb, 0x00403c, ram->coef); +	default: +		nv_mask(pfb, 0x004020, 0xc0771100, ram->ctrl); +		nv_wr32(pfb, 0x004024, ram->coef); +		break; +	} +	udelay(100); +	nv_mask(pfb, 0x00c040, 0x0000c000, 0x0000c000); + +	/* re-enable normal operation of memory controller */ +	nv_wr32(pfb, 0x1002dc, 0x00000000); +	nv_mask(pfb, 0x100210, 0x80000000, 0x80000000); +	udelay(100); + +	/* execute memory reset script from vbios */ +	if (!bit_entry(bios, 'M', &M)) { +		struct nvbios_init init = { +			.subdev = nv_subdev(pfb), +			.bios = bios, +			.offset = nv_ro16(bios, M.offset + 0x00), +			.execute = 1, +		}; + +		nvbios_exec(&init); +	} + +	/* make sure we're in vblank (hopefully the same one as before), and +	 * then re-enable crtc memory access +	 */ +	for (i = 0; i < 2; i++) { +		if (!(crtc_mask & (1 << i))) +			continue; +		nv_wait(pfb, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); +		nv_wr08(pfb, 0x0c03c4 + (i * 0x2000), 0x01); +		nv_wr08(pfb, 0x0c03c5 + (i * 0x2000), sr1[i]); +	} + +	return 0; +} + +void +nv40_ram_tidy(struct nouveau_fb *pfb) +{ +}  static int  nv40_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, @@ -30,7 +177,7 @@ nv40_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_object **pobject)  {  	struct nouveau_fb *pfb = nouveau_fb(parent); -	struct nouveau_ram *ram; +	struct nv40_ram *ram;  	u32 pbus1218 = nv_rd32(pfb, 0x001218);  	int ret; @@ -40,15 +187,18 @@ nv40_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		return ret;  	switch (pbus1218 & 0x00000300) { -	case 0x00000000: ram->type = NV_MEM_TYPE_SDRAM; break; -	case 0x00000100: ram->type = NV_MEM_TYPE_DDR1; break; -	case 0x00000200: ram->type = NV_MEM_TYPE_GDDR3; break; -	case 0x00000300: ram->type = NV_MEM_TYPE_DDR2; break; +	case 0x00000000: ram->base.type = NV_MEM_TYPE_SDRAM; break; +	case 0x00000100: ram->base.type = NV_MEM_TYPE_DDR1; break; +	case 0x00000200: ram->base.type = NV_MEM_TYPE_GDDR3; break; +	case 0x00000300: ram->base.type = NV_MEM_TYPE_DDR2; break;  	} -	ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000; -	ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; -	ram->tags  =  nv_rd32(pfb, 0x100320); +	ram->base.size  =  nv_rd32(pfb, 0x10020c) & 0xff000000; +	ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; +	ram->base.tags  =  nv_rd32(pfb, 0x100320); +	ram->base.calc = nv40_ram_calc; +	ram->base.prog = nv40_ram_prog; +	ram->base.tidy = nv40_ram_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv41.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv41.c index 1dab7e12aba..d64498a4d9e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv41.c @@ -22,7 +22,7 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv40.h"  static int  nv41_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, @@ -30,7 +30,7 @@ nv41_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_object **pobject)  {  	struct nouveau_fb *pfb = nouveau_fb(parent); -	struct nouveau_ram *ram; +	struct nv40_ram *ram;  	u32 pfb474 = nv_rd32(pfb, 0x100474);  	int ret; @@ -40,15 +40,18 @@ nv41_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		return ret;  	if (pfb474 & 0x00000004) -		ram->type = NV_MEM_TYPE_GDDR3; +		ram->base.type = NV_MEM_TYPE_GDDR3;  	if (pfb474 & 0x00000002) -		ram->type = NV_MEM_TYPE_DDR2; +		ram->base.type = NV_MEM_TYPE_DDR2;  	if (pfb474 & 0x00000001) -		ram->type = NV_MEM_TYPE_DDR1; +		ram->base.type = NV_MEM_TYPE_DDR1; -	ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000; -	ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; -	ram->tags  =  nv_rd32(pfb, 0x100320); +	ram->base.size  =  nv_rd32(pfb, 0x10020c) & 0xff000000; +	ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; +	ram->base.tags  =  nv_rd32(pfb, 0x100320); +	ram->base.calc = nv40_ram_calc; +	ram->base.prog = nv40_ram_prog; +	ram->base.tidy = nv40_ram_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv44.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv44.c index 25fff842e5c..089acac810c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv44.c @@ -22,7 +22,7 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv40.h"  static int  nv44_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, @@ -30,7 +30,7 @@ nv44_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_object **pobject)  {  	struct nouveau_fb *pfb = nouveau_fb(parent); -	struct nouveau_ram *ram; +	struct nv40_ram *ram;  	u32 pfb474 = nv_rd32(pfb, 0x100474);  	int ret; @@ -40,13 +40,16 @@ nv44_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		return ret;  	if (pfb474 & 0x00000004) -		ram->type = NV_MEM_TYPE_GDDR3; +		ram->base.type = NV_MEM_TYPE_GDDR3;  	if (pfb474 & 0x00000002) -		ram->type = NV_MEM_TYPE_DDR2; +		ram->base.type = NV_MEM_TYPE_DDR2;  	if (pfb474 & 0x00000001) -		ram->type = NV_MEM_TYPE_DDR1; +		ram->base.type = NV_MEM_TYPE_DDR1; -	ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; +	ram->base.size = nv_rd32(pfb, 0x10020c) & 0xff000000; +	ram->base.calc = nv40_ram_calc; +	ram->base.prog = nv40_ram_prog; +	ram->base.tidy = nv40_ram_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c index ab7ef0ac9e3..baa013afa57 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c @@ -22,7 +22,7 @@   * Authors: Ben Skeggs   */ -#include "priv.h" +#include "nv40.h"  static int  nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, @@ -30,7 +30,7 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		struct nouveau_object **pobject)  {  	struct nouveau_fb *pfb = nouveau_fb(parent); -	struct nouveau_ram *ram; +	struct nv40_ram *ram;  	u32 pfb914 = nv_rd32(pfb, 0x100914);  	int ret; @@ -40,15 +40,18 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  		return ret;  	switch (pfb914 & 0x00000003) { -	case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break; -	case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break; -	case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break; +	case 0x00000000: ram->base.type = NV_MEM_TYPE_DDR1; break; +	case 0x00000001: ram->base.type = NV_MEM_TYPE_DDR2; break; +	case 0x00000002: ram->base.type = NV_MEM_TYPE_GDDR3; break;  	case 0x00000003: break;  	} -	ram->size  =  nv_rd32(pfb, 0x10020c) & 0xff000000; -	ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; -	ram->tags  =  nv_rd32(pfb, 0x100320); +	ram->base.size  =  nv_rd32(pfb, 0x10020c) & 0xff000000; +	ram->base.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; +	ram->base.tags  =  nv_rd32(pfb, 0x100320); +	ram->base.calc = nv40_ram_calc; +	ram->base.prog = nv40_ram_prog; +	ram->base.tidy = nv40_ram_tidy;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c index 903baff77fd..e5d12c24cc4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c @@ -23,8 +23,205 @@   */  #include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/pll.h> +#include <subdev/bios/perf.h> +#include <subdev/bios/timing.h> +#include <subdev/clock/pll.h> +#include <subdev/fb.h> + +#include <core/option.h>  #include <core/mm.h> -#include "priv.h" + +#include "ramseq.h" + +#include "nv50.h" + +struct nv50_ramseq { +	struct hwsq base; +	struct hwsq_reg r_0x002504; +	struct hwsq_reg r_0x004008; +	struct hwsq_reg r_0x00400c; +	struct hwsq_reg r_0x00c040; +	struct hwsq_reg r_0x100210; +	struct hwsq_reg r_0x1002d0; +	struct hwsq_reg r_0x1002d4; +	struct hwsq_reg r_0x1002dc; +	struct hwsq_reg r_0x100da0[8]; +	struct hwsq_reg r_0x100e20; +	struct hwsq_reg r_0x100e24; +	struct hwsq_reg r_0x611200; +	struct hwsq_reg r_timing[9]; +	struct hwsq_reg r_mr[4]; +}; + +struct nv50_ram { +	struct nouveau_ram base; +	struct nv50_ramseq hwsq; +}; + +#define QFX5800NVA0 1 + +static int +nv50_ram_calc(struct nouveau_fb *pfb, u32 freq) +{ +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nv50_ram *ram = (void *)pfb->ram; +	struct nv50_ramseq *hwsq = &ram->hwsq; +	struct nvbios_perfE perfE; +	struct nvbios_pll mpll; +	struct { +		u32 data; +		u8  size; +	} ramcfg, timing; +	u8  ver, hdr, cnt, len, strap; +	int N1, M1, N2, M2, P; +	int ret, i; + +	/* lookup closest matching performance table entry for frequency */ +	i = 0; +	do { +		ramcfg.data = nvbios_perfEp(bios, i++, &ver, &hdr, &cnt, +					   &ramcfg.size, &perfE); +		if (!ramcfg.data || (ver < 0x25 || ver >= 0x40) || +		    (ramcfg.size < 2)) { +			nv_error(pfb, "invalid/missing perftab entry\n"); +			return -EINVAL; +		} +	} while (perfE.memory < freq); + +	/* locate specific data set for the attached memory */ +	strap = nvbios_ramcfg_index(nv_subdev(pfb)); +	if (strap >= cnt) { +		nv_error(pfb, "invalid ramcfg strap\n"); +		return -EINVAL; +	} + +	ramcfg.data += hdr + (strap * ramcfg.size); + +	/* lookup memory timings, if bios says they're present */ +	strap = nv_ro08(bios, ramcfg.data + 0x01); +	if (strap != 0xff) { +		timing.data = nvbios_timingEe(bios, strap, &ver, &hdr, +					     &cnt, &len); +		if (!timing.data || ver != 0x10 || hdr < 0x12) { +			nv_error(pfb, "invalid/missing timing entry " +				 "%02x %04x %02x %02x\n", +				 strap, timing.data, ver, hdr); +			return -EINVAL; +		} +	} else { +		timing.data = 0; +	} + +	ret = ram_init(hwsq, nv_subdev(pfb)); +	if (ret) +		return ret; + +	ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */ +	ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */ +	ram_wr32(hwsq, 0x611200, 0x00003300); +	ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */ +	ram_nsec(hwsq, 8000); +	ram_setf(hwsq, 0x10, 0x00); /* disable fb */ +	ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ + +	ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */ +	ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ +	ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ +	ram_wr32(hwsq, 0x100210, 0x00000000); /* disable auto-refresh */ +	ram_wr32(hwsq, 0x1002dc, 0x00000001); /* enable self-refresh */ + +	ret = nvbios_pll_parse(bios, 0x004008, &mpll); +	mpll.vco2.max_freq = 0; +	if (ret == 0) { +		ret = nv04_pll_calc(nv_subdev(pfb), &mpll, freq, +				   &N1, &M1, &N2, &M2, &P); +		if (ret == 0) +			ret = -EINVAL; +	} + +	if (ret < 0) +		return ret; + +	ram_mask(hwsq, 0x00c040, 0xc000c000, 0x0000c000); +	ram_mask(hwsq, 0x004008, 0x00000200, 0x00000200); +	ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); +	ram_mask(hwsq, 0x004008, 0x81ff0000, 0x80000000 | (mpll.bias_p << 19) | +					     (P << 22) | (P << 16)); +#if QFX5800NVA0 +	for (i = 0; i < 8; i++) +		ram_mask(hwsq, 0x100da0[i], 0x00000000, 0x00000000); /*XXX*/ +#endif +	ram_nsec(hwsq, 96000); /*XXX*/ +	ram_mask(hwsq, 0x004008, 0x00002200, 0x00002000); + +	ram_wr32(hwsq, 0x1002dc, 0x00000000); /* disable self-refresh */ +	ram_wr32(hwsq, 0x100210, 0x80000000); /* enable auto-refresh */ + +	ram_nsec(hwsq, 12000); + +	switch (ram->base.type) { +	case NV_MEM_TYPE_DDR2: +		ram_nuke(hwsq, mr[0]); /* force update */ +		ram_mask(hwsq, mr[0], 0x000, 0x000); +		break; +	case NV_MEM_TYPE_GDDR3: +		ram_mask(hwsq, mr[2], 0x000, 0x000); +		ram_nuke(hwsq, mr[0]); /* force update */ +		ram_mask(hwsq, mr[0], 0x000, 0x000); +		break; +	default: +		break; +	} + +	ram_mask(hwsq, timing[3], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[1], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[6], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[7], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[8], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[2], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[4], 0x00000000, 0x00000000); /*XXX*/ +	ram_mask(hwsq, timing[5], 0x00000000, 0x00000000); /*XXX*/ + +	ram_mask(hwsq, timing[0], 0x00000000, 0x00000000); /*XXX*/ + +#if QFX5800NVA0 +	ram_nuke(hwsq, 0x100e24); +	ram_mask(hwsq, 0x100e24, 0x00000000, 0x00000000); +	ram_nuke(hwsq, 0x100e20); +	ram_mask(hwsq, 0x100e20, 0x00000000, 0x00000000); +#endif + +	ram_mask(hwsq, mr[0], 0x100, 0x100); +	ram_mask(hwsq, mr[0], 0x100, 0x000); + +	ram_setf(hwsq, 0x10, 0x01); /* enable fb */ +	ram_wait(hwsq, 0x00, 0x00); /* wait for fb enabled */ +	ram_wr32(hwsq, 0x611200, 0x00003330); +	ram_wr32(hwsq, 0x002504, 0x00000000); /* un-block fifo */ +	return 0; +} + +static int +nv50_ram_prog(struct nouveau_fb *pfb) +{ +	struct nouveau_device *device = nv_device(pfb); +	struct nv50_ram *ram = (void *)pfb->ram; +	struct nv50_ramseq *hwsq = &ram->hwsq; + +	ram_exec(hwsq, nouveau_boolopt(device->cfgopt, "NvMemExec", true)); +	return 0; +} + +static void +nv50_ram_tidy(struct nouveau_fb *pfb) +{ +	struct nv50_ram *ram = (void *)pfb->ram; +	struct nv50_ramseq *hwsq = &ram->hwsq; +	ram_exec(hwsq, false); +}  void  __nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem *mem) @@ -57,7 +254,7 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)  	kfree(mem);  } -static int +int  nv50_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,  	     u32 memtype, struct nouveau_mem **pmem)  { @@ -160,77 +357,114 @@ nv50_fb_vram_rblock(struct nouveau_fb *pfb, struct nouveau_ram *ram)  	return rblock_size;  } -static int -nv50_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, -		struct nouveau_oclass *oclass, void *data, u32 datasize, -		struct nouveau_object **pobject) +int +nv50_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine, +		 struct nouveau_oclass *oclass, int length, void **pobject)  { -	struct nouveau_fb *pfb = nouveau_fb(parent); -	struct nouveau_device *device = nv_device(pfb); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nouveau_ram *ram;  	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */  	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ -	u32 size; +	struct nouveau_bios *bios = nouveau_bios(parent); +	struct nouveau_fb *pfb = nouveau_fb(parent); +	struct nouveau_ram *ram;  	int ret; -	ret = nouveau_ram_create(parent, engine, oclass, &ram); -	*pobject = nv_object(ram); +	ret = nouveau_ram_create_(parent, engine, oclass, length, pobject); +	ram = *pobject;  	if (ret)  		return ret;  	ram->size = nv_rd32(pfb, 0x10020c); -	ram->size = (ram->size & 0xffffff00) | -		       ((ram->size & 0x000000ff) << 32); - -	size = (ram->size >> 12) - rsvd_head - rsvd_tail; -	switch (device->chipset) { -	case 0xaa: -	case 0xac: -	case 0xaf: /* IGPs, no reordering, no real VRAM */ -		ret = nouveau_mm_init(&pfb->vram, rsvd_head, size, 1); -		if (ret) -			return ret; +	ram->size = (ram->size & 0xffffff00) | ((ram->size & 0x000000ff) << 32); -		ram->type   = NV_MEM_TYPE_STOLEN; -		ram->stolen = (u64)nv_rd32(pfb, 0x100e10) << 12; +	switch (nv_rd32(pfb, 0x100714) & 0x00000007) { +	case 0: ram->type = NV_MEM_TYPE_DDR1; break; +	case 1: +		if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3) +			ram->type = NV_MEM_TYPE_DDR3; +		else +			ram->type = NV_MEM_TYPE_DDR2;  		break; +	case 2: ram->type = NV_MEM_TYPE_GDDR3; break; +	case 3: ram->type = NV_MEM_TYPE_GDDR4; break; +	case 4: ram->type = NV_MEM_TYPE_GDDR5; break;  	default: -		switch (nv_rd32(pfb, 0x100714) & 0x00000007) { -		case 0: ram->type = NV_MEM_TYPE_DDR1; break; -		case 1: -			if (nouveau_fb_bios_memtype(bios) == NV_MEM_TYPE_DDR3) -				ram->type = NV_MEM_TYPE_DDR3; -			else -				ram->type = NV_MEM_TYPE_DDR2; -			break; -		case 2: ram->type = NV_MEM_TYPE_GDDR3; break; -		case 3: ram->type = NV_MEM_TYPE_GDDR4; break; -		case 4: ram->type = NV_MEM_TYPE_GDDR5; break; -		default: -			break; -		} - -		ret = nouveau_mm_init(&pfb->vram, rsvd_head, size, -				      nv50_fb_vram_rblock(pfb, ram) >> 12); -		if (ret) -			return ret; - -		ram->ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1; -		ram->tags  =  nv_rd32(pfb, 0x100320);  		break;  	} +	ret = nouveau_mm_init(&pfb->vram, rsvd_head, (ram->size >> 12) - +			      (rsvd_head + rsvd_tail), +			      nv50_fb_vram_rblock(pfb, ram) >> 12); +	if (ret) +		return ret; + +	ram->ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1; +	ram->tags  =  nv_rd32(pfb, 0x100320);  	ram->get = nv50_ram_get;  	ram->put = nv50_ram_put;  	return 0;  } +static int +nv50_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 datasize, +	      struct nouveau_object **pobject) +{ +	struct nv50_ram *ram; +	int ret, i; + +	ret = nv50_ram_create(parent, engine, oclass, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; + +	switch (ram->base.type) { +	case NV_MEM_TYPE_DDR2: +	case NV_MEM_TYPE_GDDR3: +		ram->base.calc = nv50_ram_calc; +		ram->base.prog = nv50_ram_prog; +		ram->base.tidy = nv50_ram_tidy; +		break; +	default: +		nv_warn(ram, "reclocking of this ram type unsupported\n"); +		return 0; +	} + +	ram->hwsq.r_0x002504 = hwsq_reg(0x002504); +	ram->hwsq.r_0x00c040 = hwsq_reg(0x00c040); +	ram->hwsq.r_0x004008 = hwsq_reg(0x004008); +	ram->hwsq.r_0x00400c = hwsq_reg(0x00400c); +	ram->hwsq.r_0x100210 = hwsq_reg(0x100210); +	ram->hwsq.r_0x1002d0 = hwsq_reg(0x1002d0); +	ram->hwsq.r_0x1002d4 = hwsq_reg(0x1002d4); +	ram->hwsq.r_0x1002dc = hwsq_reg(0x1002dc); +	for (i = 0; i < 8; i++) +		ram->hwsq.r_0x100da0[i] = hwsq_reg(0x100da0 + (i * 0x04)); +	ram->hwsq.r_0x100e20 = hwsq_reg(0x100e20); +	ram->hwsq.r_0x100e24 = hwsq_reg(0x100e24); +	ram->hwsq.r_0x611200 = hwsq_reg(0x611200); + +	for (i = 0; i < 9; i++) +		ram->hwsq.r_timing[i] = hwsq_reg(0x100220 + (i * 0x04)); + +	if (ram->base.ranks > 1) { +		ram->hwsq.r_mr[0] = hwsq_reg2(0x1002c0, 0x1002c8); +		ram->hwsq.r_mr[1] = hwsq_reg2(0x1002c4, 0x1002cc); +		ram->hwsq.r_mr[2] = hwsq_reg2(0x1002e0, 0x1002e8); +		ram->hwsq.r_mr[3] = hwsq_reg2(0x1002e4, 0x1002ec); +	} else { +		ram->hwsq.r_mr[0] = hwsq_reg(0x1002c0); +		ram->hwsq.r_mr[1] = hwsq_reg(0x1002c4); +		ram->hwsq.r_mr[2] = hwsq_reg(0x1002e0); +		ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4); +	} + +	return 0; +} +  struct nouveau_oclass  nv50_ram_oclass = { -	.handle = 0,  	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv50_ram_create, +		.ctor = nv50_ram_ctor,  		.dtor = _nouveau_ram_dtor,  		.init = _nouveau_ram_init,  		.fini = _nouveau_ram_fini, diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c new file mode 100644 index 00000000000..8076fb195dd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnva3.c @@ -0,0 +1,439 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/bios.h> +#include <subdev/bios/bit.h> +#include <subdev/bios/pll.h> +#include <subdev/bios/rammap.h> +#include <subdev/bios/timing.h> + +#include <subdev/clock/nva3.h> +#include <subdev/clock/pll.h> + +#include <core/option.h> + +#include "ramfuc.h" + +#include "nv50.h" + +struct nva3_ramfuc { +	struct ramfuc base; +	struct ramfuc_reg r_0x004000; +	struct ramfuc_reg r_0x004004; +	struct ramfuc_reg r_0x004018; +	struct ramfuc_reg r_0x004128; +	struct ramfuc_reg r_0x004168; +	struct ramfuc_reg r_0x100200; +	struct ramfuc_reg r_0x100210; +	struct ramfuc_reg r_0x100220[9]; +	struct ramfuc_reg r_0x1002d0; +	struct ramfuc_reg r_0x1002d4; +	struct ramfuc_reg r_0x1002dc; +	struct ramfuc_reg r_0x10053c; +	struct ramfuc_reg r_0x1005a0; +	struct ramfuc_reg r_0x1005a4; +	struct ramfuc_reg r_0x100714; +	struct ramfuc_reg r_0x100718; +	struct ramfuc_reg r_0x10071c; +	struct ramfuc_reg r_0x100760; +	struct ramfuc_reg r_0x1007a0; +	struct ramfuc_reg r_0x1007e0; +	struct ramfuc_reg r_0x10f804; +	struct ramfuc_reg r_0x1110e0; +	struct ramfuc_reg r_0x111100; +	struct ramfuc_reg r_0x111104; +	struct ramfuc_reg r_0x611200; +	struct ramfuc_reg r_mr[4]; +}; + +struct nva3_ram { +	struct nouveau_ram base; +	struct nva3_ramfuc fuc; +}; + +static int +nva3_ram_calc(struct nouveau_fb *pfb, u32 freq) +{ +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nva3_ram *ram = (void *)pfb->ram; +	struct nva3_ramfuc *fuc = &ram->fuc; +	struct nva3_clock_info mclk; +	u8  ver, cnt, len, strap; +	u32 data; +	struct { +		u32 data; +		u8  size; +	} rammap, ramcfg, timing; +	u32 r004018, r100760, ctrl; +	u32 unk714, unk718, unk71c; +	int ret; + +	/* lookup memory config data relevant to the target frequency */ +	rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size, +				     &cnt, &ramcfg.size); +	if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { +		nv_error(pfb, "invalid/missing rammap entry\n"); +		return -EINVAL; +	} + +	/* locate specific data set for the attached memory */ +	strap = nvbios_ramcfg_index(nv_subdev(pfb)); +	if (strap >= cnt) { +		nv_error(pfb, "invalid ramcfg strap\n"); +		return -EINVAL; +	} + +	ramcfg.data = rammap.data + rammap.size + (strap * ramcfg.size); +	if (!ramcfg.data || ver != 0x10 || ramcfg.size < 0x0e) { +		nv_error(pfb, "invalid/missing ramcfg entry\n"); +		return -EINVAL; +	} + +	/* lookup memory timings, if bios says they're present */ +	strap = nv_ro08(bios, ramcfg.data + 0x01); +	if (strap != 0xff) { +		timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size, +					     &cnt, &len); +		if (!timing.data || ver != 0x10 || timing.size < 0x19) { +			nv_error(pfb, "invalid/missing timing entry\n"); +			return -EINVAL; +		} +	} else { +		timing.data = 0; +	} + +	ret = nva3_clock_info(nouveau_clock(pfb), 0x12, 0x4000, freq, &mclk); +	if (ret < 0) { +		nv_error(pfb, "failed mclk calculation\n"); +		return ret; +	} + +	ret = ram_init(fuc, pfb); +	if (ret) +		return ret; + +	/* XXX: where the fuck does 750MHz come from? */ +	if (freq <= 750000) { +		r004018 = 0x10000000; +		r100760 = 0x22222222; +	} else { +		r004018 = 0x00000000; +		r100760 = 0x00000000; +	} + +	ctrl = ram_rd32(fuc, 0x004000); +	if (ctrl & 0x00000008) { +		if (mclk.pll) { +			ram_mask(fuc, 0x004128, 0x00000101, 0x00000101); +			ram_wr32(fuc, 0x004004, mclk.pll); +			ram_wr32(fuc, 0x004000, (ctrl |= 0x00000001)); +			ram_wr32(fuc, 0x004000, (ctrl &= 0xffffffef)); +			ram_wait(fuc, 0x004000, 0x00020000, 0x00020000, 64000); +			ram_wr32(fuc, 0x004000, (ctrl |= 0x00000010)); +			ram_wr32(fuc, 0x004018, 0x00005000 | r004018); +			ram_wr32(fuc, 0x004000, (ctrl |= 0x00000004)); +		} +	} else { +		u32 ssel = 0x00000101; +		if (mclk.clk) +			ssel |= mclk.clk; +		else +			ssel |= 0x00080000; /* 324MHz, shouldn't matter... */ +		ram_mask(fuc, 0x004168, 0x003f3141, ctrl); +	} + +	if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x10)) { +		ram_mask(fuc, 0x111104, 0x00000600, 0x00000000); +	} else { +		ram_mask(fuc, 0x111100, 0x40000000, 0x40000000); +		ram_mask(fuc, 0x111104, 0x00000180, 0x00000000); +	} + +	if (!(nv_ro08(bios, rammap.data + 0x04) & 0x02)) +		ram_mask(fuc, 0x100200, 0x00000800, 0x00000000); +	ram_wr32(fuc, 0x611200, 0x00003300); +	if (!(nv_ro08(bios, ramcfg.data + 0x02) & 0x10)) +		ram_wr32(fuc, 0x111100, 0x4c020000); /*XXX*/ + +	ram_wr32(fuc, 0x1002d4, 0x00000001); +	ram_wr32(fuc, 0x1002d0, 0x00000001); +	ram_wr32(fuc, 0x1002d0, 0x00000001); +	ram_wr32(fuc, 0x100210, 0x00000000); +	ram_wr32(fuc, 0x1002dc, 0x00000001); +	ram_nsec(fuc, 2000); + +	ctrl = ram_rd32(fuc, 0x004000); +	if (!(ctrl & 0x00000008) && mclk.pll) { +		ram_wr32(fuc, 0x004000, (ctrl |=  0x00000008)); +		ram_mask(fuc, 0x1110e0, 0x00088000, 0x00088000); +		ram_wr32(fuc, 0x004018, 0x00001000); +		ram_wr32(fuc, 0x004000, (ctrl &= ~0x00000001)); +		ram_wr32(fuc, 0x004004, mclk.pll); +		ram_wr32(fuc, 0x004000, (ctrl |=  0x00000001)); +		udelay(64); +		ram_wr32(fuc, 0x004018, 0x00005000 | r004018); +		udelay(20); +	} else +	if (!mclk.pll) { +		ram_mask(fuc, 0x004168, 0x003f3040, mclk.clk); +		ram_wr32(fuc, 0x004000, (ctrl |= 0x00000008)); +		ram_mask(fuc, 0x1110e0, 0x00088000, 0x00088000); +		ram_wr32(fuc, 0x004018, 0x0000d000 | r004018); +	} + +	if ( (nv_ro08(bios, rammap.data + 0x04) & 0x08)) { +		u32 unk5a0 = (nv_ro16(bios, ramcfg.data + 0x05) << 8) | +			      nv_ro08(bios, ramcfg.data + 0x05); +		u32 unk5a4 = (nv_ro16(bios, ramcfg.data + 0x07)); +		u32 unk804 = (nv_ro08(bios, ramcfg.data + 0x09) & 0xf0) << 16 | +			     (nv_ro08(bios, ramcfg.data + 0x03) & 0x0f) << 16 | +			     (nv_ro08(bios, ramcfg.data + 0x09) & 0x0f) | +			     0x80000000; +		ram_wr32(fuc, 0x1005a0, unk5a0); +		ram_wr32(fuc, 0x1005a4, unk5a4); +		ram_wr32(fuc, 0x10f804, unk804); +		ram_mask(fuc, 0x10053c, 0x00001000, 0x00000000); +	} else { +		ram_mask(fuc, 0x10053c, 0x00001000, 0x00001000); +		ram_mask(fuc, 0x10f804, 0x80000000, 0x00000000); +		ram_mask(fuc, 0x100760, 0x22222222, r100760); +		ram_mask(fuc, 0x1007a0, 0x22222222, r100760); +		ram_mask(fuc, 0x1007e0, 0x22222222, r100760); +	} + +	if (mclk.pll) { +		ram_mask(fuc, 0x1110e0, 0x00088000, 0x00011000); +		ram_wr32(fuc, 0x004000, (ctrl &= ~0x00000008)); +	} + +	/*XXX: LEAVE */ +	ram_wr32(fuc, 0x1002dc, 0x00000000); +	ram_wr32(fuc, 0x1002d4, 0x00000001); +	ram_wr32(fuc, 0x100210, 0x80000000); +	ram_nsec(fuc, 1000); +	ram_nsec(fuc, 1000); + +	ram_mask(fuc, mr[2], 0x00000000, 0x00000000); +	ram_nsec(fuc, 1000); +	ram_nuke(fuc, mr[0]); +	ram_mask(fuc, mr[0], 0x00000000, 0x00000000); +	ram_nsec(fuc, 1000); + +	ram_mask(fuc, 0x100220[3], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[1], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[6], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[7], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[2], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[4], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[5], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[0], 0x00000000, 0x00000000); +	ram_mask(fuc, 0x100220[8], 0x00000000, 0x00000000); + +	data = (nv_ro08(bios, ramcfg.data + 0x02) & 0x08) ? 0x00000000 : 0x00001000; +	ram_mask(fuc, 0x100200, 0x00001000, data); + +	unk714 = ram_rd32(fuc, 0x100714) & ~0xf0000010; +	unk718 = ram_rd32(fuc, 0x100718) & ~0x00000100; +	unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100; +	if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x20)) +		unk714 |= 0xf0000000; +	if (!(nv_ro08(bios, ramcfg.data + 0x02) & 0x04)) +		unk714 |= 0x00000010; +	ram_wr32(fuc, 0x100714, unk714); + +	if (nv_ro08(bios, ramcfg.data + 0x02) & 0x01) +		unk71c |= 0x00000100; +	ram_wr32(fuc, 0x10071c, unk71c); + +	if (nv_ro08(bios, ramcfg.data + 0x02) & 0x02) +		unk718 |= 0x00000100; +	ram_wr32(fuc, 0x100718, unk718); + +	if (nv_ro08(bios, ramcfg.data + 0x02) & 0x10) +		ram_wr32(fuc, 0x111100, 0x48000000); /*XXX*/ + +	ram_mask(fuc, mr[0], 0x100, 0x100); +	ram_nsec(fuc, 1000); +	ram_mask(fuc, mr[0], 0x100, 0x000); +	ram_nsec(fuc, 1000); + +	ram_nsec(fuc, 2000); +	ram_nsec(fuc, 12000); + +	ram_wr32(fuc, 0x611200, 0x00003330); +	if ( (nv_ro08(bios, rammap.data + 0x04) & 0x02)) +		ram_mask(fuc, 0x100200, 0x00000800, 0x00000800); +	if ( (nv_ro08(bios, ramcfg.data + 0x02) & 0x10)) { +		ram_mask(fuc, 0x111104, 0x00000180, 0x00000180); +		ram_mask(fuc, 0x111100, 0x40000000, 0x00000000); +	} else { +		ram_mask(fuc, 0x111104, 0x00000600, 0x00000600); +	} + +	if (mclk.pll) { +		ram_mask(fuc, 0x004168, 0x00000001, 0x00000000); +		ram_mask(fuc, 0x004168, 0x00000100, 0x00000000); +	} else { +		ram_mask(fuc, 0x004000, 0x00000001, 0x00000000); +		ram_mask(fuc, 0x004128, 0x00000001, 0x00000000); +		ram_mask(fuc, 0x004128, 0x00000100, 0x00000000); +	} + +	return 0; +} + +static int +nva3_ram_prog(struct nouveau_fb *pfb) +{ +	struct nouveau_device *device = nv_device(pfb); +	struct nva3_ram *ram = (void *)pfb->ram; +	struct nva3_ramfuc *fuc = &ram->fuc; +	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true)); +	return 0; +} + +static void +nva3_ram_tidy(struct nouveau_fb *pfb) +{ +	struct nva3_ram *ram = (void *)pfb->ram; +	struct nva3_ramfuc *fuc = &ram->fuc; +	ram_exec(fuc, false); +} + +static int +nva3_ram_init(struct nouveau_object *object) +{ +	struct nouveau_fb *pfb = (void *)object->parent; +	struct nva3_ram   *ram = (void *)object; +	int ret, i; + +	ret = nouveau_ram_init(&ram->base); +	if (ret) +		return ret; + +	/* prepare for ddr link training, and load training patterns */ +	switch (ram->base.type) { +	case NV_MEM_TYPE_DDR3: { +		if (nv_device(pfb)->chipset == 0xa8) { +			static const u32 pattern[16] = { +				0xaaaaaaaa, 0xcccccccc, 0xdddddddd, 0xeeeeeeee, +				0x00000000, 0x11111111, 0x44444444, 0xdddddddd, +				0x33333333, 0x55555555, 0x77777777, 0x66666666, +				0x99999999, 0x88888888, 0xeeeeeeee, 0xbbbbbbbb, +			}; + +			nv_wr32(pfb, 0x100538, 0x10001ff6); /*XXX*/ +			nv_wr32(pfb, 0x1005a8, 0x0000ffff); +			nv_mask(pfb, 0x10f800, 0x00000001, 0x00000001); +			for (i = 0; i < 0x30; i++) { +				nv_wr32(pfb, 0x10f8c0, (i << 8) | i); +				nv_wr32(pfb, 0x10f8e0, (i << 8) | i); +				nv_wr32(pfb, 0x10f900, pattern[i % 16]); +				nv_wr32(pfb, 0x10f920, pattern[i % 16]); +			} +		} +	} +		break; +	default: +		break; +	} + +	return 0; +} + +static int +nva3_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 datasize, +	      struct nouveau_object **pobject) +{ +	struct nva3_ram *ram; +	int ret, i; + +	ret = nv50_ram_create(parent, engine, oclass, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; + +	switch (ram->base.type) { +	case NV_MEM_TYPE_DDR3: +		ram->base.calc = nva3_ram_calc; +		ram->base.prog = nva3_ram_prog; +		ram->base.tidy = nva3_ram_tidy; +		break; +	default: +		nv_warn(ram, "reclocking of this ram type unsupported\n"); +		return 0; +	} + +	ram->fuc.r_0x004000 = ramfuc_reg(0x004000); +	ram->fuc.r_0x004004 = ramfuc_reg(0x004004); +	ram->fuc.r_0x004018 = ramfuc_reg(0x004018); +	ram->fuc.r_0x004128 = ramfuc_reg(0x004128); +	ram->fuc.r_0x004168 = ramfuc_reg(0x004168); +	ram->fuc.r_0x100200 = ramfuc_reg(0x100200); +	ram->fuc.r_0x100210 = ramfuc_reg(0x100210); +	for (i = 0; i < 9; i++) +		ram->fuc.r_0x100220[i] = ramfuc_reg(0x100220 + (i * 4)); +	ram->fuc.r_0x1002d0 = ramfuc_reg(0x1002d0); +	ram->fuc.r_0x1002d4 = ramfuc_reg(0x1002d4); +	ram->fuc.r_0x1002dc = ramfuc_reg(0x1002dc); +	ram->fuc.r_0x10053c = ramfuc_reg(0x10053c); +	ram->fuc.r_0x1005a0 = ramfuc_reg(0x1005a0); +	ram->fuc.r_0x1005a4 = ramfuc_reg(0x1005a4); +	ram->fuc.r_0x100714 = ramfuc_reg(0x100714); +	ram->fuc.r_0x100718 = ramfuc_reg(0x100718); +	ram->fuc.r_0x10071c = ramfuc_reg(0x10071c); +	ram->fuc.r_0x100760 = ramfuc_reg(0x100760); +	ram->fuc.r_0x1007a0 = ramfuc_reg(0x1007a0); +	ram->fuc.r_0x1007e0 = ramfuc_reg(0x1007e0); +	ram->fuc.r_0x10f804 = ramfuc_reg(0x10f804); +	ram->fuc.r_0x1110e0 = ramfuc_reg(0x1110e0); +	ram->fuc.r_0x111100 = ramfuc_reg(0x111100); +	ram->fuc.r_0x111104 = ramfuc_reg(0x111104); +	ram->fuc.r_0x611200 = ramfuc_reg(0x611200); + +	if (ram->base.ranks > 1) { +		ram->fuc.r_mr[0] = ramfuc_reg2(0x1002c0, 0x1002c8); +		ram->fuc.r_mr[1] = ramfuc_reg2(0x1002c4, 0x1002cc); +		ram->fuc.r_mr[2] = ramfuc_reg2(0x1002e0, 0x1002e8); +		ram->fuc.r_mr[3] = ramfuc_reg2(0x1002e4, 0x1002ec); +	} else { +		ram->fuc.r_mr[0] = ramfuc_reg(0x1002c0); +		ram->fuc.r_mr[1] = ramfuc_reg(0x1002c4); +		ram->fuc.r_mr[2] = ramfuc_reg(0x1002e0); +		ram->fuc.r_mr[3] = ramfuc_reg(0x1002e4); +	} + +	return 0; +} + +struct nouveau_oclass +nva3_ram_oclass = { +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nva3_ram_ctor, +		.dtor = _nouveau_ram_dtor, +		.init = nva3_ram_init, +		.fini = _nouveau_ram_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c new file mode 100644 index 00000000000..00f2ca7e44a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c @@ -0,0 +1,66 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +static int +nvaa_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 datasize, +	      struct nouveau_object **pobject) +{ +	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ +	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ +	struct nouveau_fb *pfb = nouveau_fb(parent); +	struct nouveau_ram *ram; +	int ret; + +	ret = nouveau_ram_create(parent, engine, oclass, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; + +	ram->size = nv_rd32(pfb, 0x10020c); +	ram->size = (ram->size & 0xffffff00) | ((ram->size & 0x000000ff) << 32); + +	ret = nouveau_mm_init(&pfb->vram, rsvd_head, (ram->size >> 12) - +			      (rsvd_head + rsvd_tail), 1); +	if (ret) +		return ret; + +	ram->type   = NV_MEM_TYPE_STOLEN; +	ram->stolen = (u64)nv_rd32(pfb, 0x100e10) << 12; +	ram->get = nv50_ram_get; +	ram->put = nv50_ram_put; +	return 0; +} + +struct nouveau_oclass +nvaa_ram_oclass = { +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvaa_ram_ctor, +		.dtor = _nouveau_ram_dtor, +		.init = _nouveau_ram_init, +		.fini = _nouveau_ram_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c index cf97c4de4a6..5a6a5027f74 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c @@ -23,9 +23,402 @@   */  #include <subdev/bios.h> +#include <subdev/bios/pll.h> +#include <subdev/bios/rammap.h> +#include <subdev/bios/timing.h>  #include <subdev/ltcg.h> -#include "priv.h" +#include <subdev/clock.h> +#include <subdev/clock/pll.h> + +#include <core/option.h> + +#include "ramfuc.h" + +#include "nvc0.h" + +struct nvc0_ramfuc { +	struct ramfuc base; + +	struct ramfuc_reg r_0x10fe20; +	struct ramfuc_reg r_0x10fe24; +	struct ramfuc_reg r_0x137320; +	struct ramfuc_reg r_0x137330; + +	struct ramfuc_reg r_0x132000; +	struct ramfuc_reg r_0x132004; +	struct ramfuc_reg r_0x132100; + +	struct ramfuc_reg r_0x137390; + +	struct ramfuc_reg r_0x10f290; +	struct ramfuc_reg r_0x10f294; +	struct ramfuc_reg r_0x10f298; +	struct ramfuc_reg r_0x10f29c; +	struct ramfuc_reg r_0x10f2a0; + +	struct ramfuc_reg r_0x10f300; +	struct ramfuc_reg r_0x10f338; +	struct ramfuc_reg r_0x10f340; +	struct ramfuc_reg r_0x10f344; +	struct ramfuc_reg r_0x10f348; + +	struct ramfuc_reg r_0x10f910; +	struct ramfuc_reg r_0x10f914; + +	struct ramfuc_reg r_0x100b0c; +	struct ramfuc_reg r_0x10f050; +	struct ramfuc_reg r_0x10f090; +	struct ramfuc_reg r_0x10f200; +	struct ramfuc_reg r_0x10f210; +	struct ramfuc_reg r_0x10f310; +	struct ramfuc_reg r_0x10f314; +	struct ramfuc_reg r_0x10f610; +	struct ramfuc_reg r_0x10f614; +	struct ramfuc_reg r_0x10f800; +	struct ramfuc_reg r_0x10f808; +	struct ramfuc_reg r_0x10f824; +	struct ramfuc_reg r_0x10f830; +	struct ramfuc_reg r_0x10f988; +	struct ramfuc_reg r_0x10f98c; +	struct ramfuc_reg r_0x10f990; +	struct ramfuc_reg r_0x10f998; +	struct ramfuc_reg r_0x10f9b0; +	struct ramfuc_reg r_0x10f9b4; +	struct ramfuc_reg r_0x10fb04; +	struct ramfuc_reg r_0x10fb08; +	struct ramfuc_reg r_0x137300; +	struct ramfuc_reg r_0x137310; +	struct ramfuc_reg r_0x137360; +	struct ramfuc_reg r_0x1373ec; +	struct ramfuc_reg r_0x1373f0; +	struct ramfuc_reg r_0x1373f8; + +	struct ramfuc_reg r_0x61c140; +	struct ramfuc_reg r_0x611200; + +	struct ramfuc_reg r_0x13d8f4; +}; + +struct nvc0_ram { +	struct nouveau_ram base; +	struct nvc0_ramfuc fuc; +	struct nvbios_pll refpll; +	struct nvbios_pll mempll; +}; + +static void +nvc0_ram_train(struct nvc0_ramfuc *fuc, u32 magic) +{ +	struct nvc0_ram *ram = container_of(fuc, typeof(*ram), fuc); +	struct nouveau_fb *pfb = nouveau_fb(ram); +	u32 part = nv_rd32(pfb, 0x022438), i; +	u32 mask = nv_rd32(pfb, 0x022554); +	u32 addr = 0x110974; + +	ram_wr32(fuc, 0x10f910, magic); +	ram_wr32(fuc, 0x10f914, magic); + +	for (i = 0; (magic & 0x80000000) && i < part; addr += 0x1000, i++) { +		if (mask & (1 << i)) +			continue; +		ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000); +	} +} + +static int +nvc0_ram_calc(struct nouveau_fb *pfb, u32 freq) +{ +	struct nouveau_clock *clk = nouveau_clock(pfb); +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nvc0_ram *ram = (void *)pfb->ram; +	struct nvc0_ramfuc *fuc = &ram->fuc; +	u8  ver, cnt, len, strap; +	struct { +		u32 data; +		u8  size; +	} rammap, ramcfg, timing; +	int ref, div, out; +	int from, mode; +	int N1, M1, P; +	int ret; + +	/* lookup memory config data relevant to the target frequency */ +	rammap.data = nvbios_rammapEm(bios, freq / 1000, &ver, &rammap.size, +				     &cnt, &ramcfg.size); +	if (!rammap.data || ver != 0x10 || rammap.size < 0x0e) { +		nv_error(pfb, "invalid/missing rammap entry\n"); +		return -EINVAL; +	} + +	/* locate specific data set for the attached memory */ +	strap = nvbios_ramcfg_index(nv_subdev(pfb)); +	if (strap >= cnt) { +		nv_error(pfb, "invalid ramcfg strap\n"); +		return -EINVAL; +	} + +	ramcfg.data = rammap.data + rammap.size + (strap * ramcfg.size); +	if (!ramcfg.data || ver != 0x10 || ramcfg.size < 0x0e) { +		nv_error(pfb, "invalid/missing ramcfg entry\n"); +		return -EINVAL; +	} + +	/* lookup memory timings, if bios says they're present */ +	strap = nv_ro08(bios, ramcfg.data + 0x01); +	if (strap != 0xff) { +		timing.data = nvbios_timingEe(bios, strap, &ver, &timing.size, +					     &cnt, &len); +		if (!timing.data || ver != 0x10 || timing.size < 0x19) { +			nv_error(pfb, "invalid/missing timing entry\n"); +			return -EINVAL; +		} +	} else { +		timing.data = 0; +	} + +	ret = ram_init(fuc, pfb); +	if (ret) +		return ret; + +	/* determine current mclk configuration */ +	from = !!(ram_rd32(fuc, 0x1373f0) & 0x00000002); /*XXX: ok? */ + +	/* determine target mclk configuration */ +	if (!(ram_rd32(fuc, 0x137300) & 0x00000100)) +		ref = clk->read(clk, nv_clk_src_sppll0); +	else +		ref = clk->read(clk, nv_clk_src_sppll1); +	div = max(min((ref * 2) / freq, (u32)65), (u32)2) - 2; +	out = (ref * 2) / (div + 2); +	mode = freq != out; + +	ram_mask(fuc, 0x137360, 0x00000002, 0x00000000); + +	if ((ram_rd32(fuc, 0x132000) & 0x00000002) || 0 /*XXX*/) { +		ram_nuke(fuc, 0x132000); +		ram_mask(fuc, 0x132000, 0x00000002, 0x00000002); +		ram_mask(fuc, 0x132000, 0x00000002, 0x00000000); +	} + +	if (mode == 1) { +		ram_nuke(fuc, 0x10fe20); +		ram_mask(fuc, 0x10fe20, 0x00000002, 0x00000002); +		ram_mask(fuc, 0x10fe20, 0x00000002, 0x00000000); +	} + +// 0x00020034 // 0x0000000a +	ram_wr32(fuc, 0x132100, 0x00000001); + +	if (mode == 1 && from == 0) { +		/* calculate refpll */ +		ret = nva3_pll_calc(nv_subdev(pfb), &ram->refpll, +				    ram->mempll.refclk, &N1, NULL, &M1, &P); +		if (ret <= 0) { +			nv_error(pfb, "unable to calc refpll\n"); +			return ret ? ret : -ERANGE; +		} + +		ram_wr32(fuc, 0x10fe20, 0x20010000); +		ram_wr32(fuc, 0x137320, 0x00000003); +		ram_wr32(fuc, 0x137330, 0x81200006); +		ram_wr32(fuc, 0x10fe24, (P << 16) | (N1 << 8) | M1); +		ram_wr32(fuc, 0x10fe20, 0x20010001); +		ram_wait(fuc, 0x137390, 0x00020000, 0x00020000, 64000); + +		/* calculate mempll */ +		ret = nva3_pll_calc(nv_subdev(pfb), &ram->mempll, freq, +				   &N1, NULL, &M1, &P); +		if (ret <= 0) { +			nv_error(pfb, "unable to calc refpll\n"); +			return ret ? ret : -ERANGE; +		} + +		ram_wr32(fuc, 0x10fe20, 0x20010005); +		ram_wr32(fuc, 0x132004, (P << 16) | (N1 << 8) | M1); +		ram_wr32(fuc, 0x132000, 0x18010101); +		ram_wait(fuc, 0x137390, 0x00000002, 0x00000002, 64000); +	} else +	if (mode == 0) { +		ram_wr32(fuc, 0x137300, 0x00000003); +	} + +	if (from == 0) { +		ram_nuke(fuc, 0x10fb04); +		ram_mask(fuc, 0x10fb04, 0x0000ffff, 0x00000000); +		ram_nuke(fuc, 0x10fb08); +		ram_mask(fuc, 0x10fb08, 0x0000ffff, 0x00000000); +		ram_wr32(fuc, 0x10f988, 0x2004ff00); +		ram_wr32(fuc, 0x10f98c, 0x003fc040); +		ram_wr32(fuc, 0x10f990, 0x20012001); +		ram_wr32(fuc, 0x10f998, 0x00011a00); +		ram_wr32(fuc, 0x13d8f4, 0x00000000); +	} else { +		ram_wr32(fuc, 0x10f988, 0x20010000); +		ram_wr32(fuc, 0x10f98c, 0x00000000); +		ram_wr32(fuc, 0x10f990, 0x20012001); +		ram_wr32(fuc, 0x10f998, 0x00010a00); +	} + +	if (from == 0) { +// 0x00020039 // 0x000000ba +	} + +// 0x0002003a // 0x00000002 +	ram_wr32(fuc, 0x100b0c, 0x00080012); +// 0x00030014 // 0x00000000 // 0x02b5f070 +// 0x00030014 // 0x00010000 // 0x02b5f070 +	ram_wr32(fuc, 0x611200, 0x00003300); +// 0x00020034 // 0x0000000a +// 0x00030020 // 0x00000001 // 0x00000000 + +	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000); +	ram_wr32(fuc, 0x10f210, 0x00000000); +	ram_nsec(fuc, 1000); +	if (mode == 0) +		nvc0_ram_train(fuc, 0x000c1001); +	ram_wr32(fuc, 0x10f310, 0x00000001); +	ram_nsec(fuc, 1000); +	ram_wr32(fuc, 0x10f090, 0x00000061); +	ram_wr32(fuc, 0x10f090, 0xc000007f); +	ram_nsec(fuc, 1000); + +	if (from == 0) { +		ram_wr32(fuc, 0x10f824, 0x00007fd4); +	} else { +		ram_wr32(fuc, 0x1373ec, 0x00020404); +	} + +	if (mode == 0) { +		ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000); +		ram_mask(fuc, 0x10f200, 0x00008000, 0x00008000); +		ram_wr32(fuc, 0x10f830, 0x41500010); +		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000); +		ram_mask(fuc, 0x132100, 0x00000100, 0x00000100); +		ram_wr32(fuc, 0x10f050, 0xff000090); +		ram_wr32(fuc, 0x1373ec, 0x00020f0f); +		ram_wr32(fuc, 0x1373f0, 0x00000003); +		ram_wr32(fuc, 0x137310, 0x81201616); +		ram_wr32(fuc, 0x132100, 0x00000001); +// 0x00020039 // 0x000000ba +		ram_wr32(fuc, 0x10f830, 0x00300017); +		ram_wr32(fuc, 0x1373f0, 0x00000001); +		ram_wr32(fuc, 0x10f824, 0x00007e77); +		ram_wr32(fuc, 0x132000, 0x18030001); +		ram_wr32(fuc, 0x10f090, 0x4000007e); +		ram_nsec(fuc, 2000); +		ram_wr32(fuc, 0x10f314, 0x00000001); +		ram_wr32(fuc, 0x10f210, 0x80000000); +		ram_wr32(fuc, 0x10f338, 0x00300220); +		ram_wr32(fuc, 0x10f300, 0x0000011d); +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f290, 0x02060505); +		ram_wr32(fuc, 0x10f294, 0x34208288); +		ram_wr32(fuc, 0x10f298, 0x44050411); +		ram_wr32(fuc, 0x10f29c, 0x0000114c); +		ram_wr32(fuc, 0x10f2a0, 0x42e10069); +		ram_wr32(fuc, 0x10f614, 0x40044f77); +		ram_wr32(fuc, 0x10f610, 0x40044f77); +		ram_wr32(fuc, 0x10f344, 0x00600009); +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f348, 0x00700008); +		ram_wr32(fuc, 0x61c140, 0x19240000); +		ram_wr32(fuc, 0x10f830, 0x00300017); +		nvc0_ram_train(fuc, 0x80021001); +		nvc0_ram_train(fuc, 0x80081001); +		ram_wr32(fuc, 0x10f340, 0x00500004); +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f830, 0x01300017); +		ram_wr32(fuc, 0x10f830, 0x00300017); +// 0x00030020 // 0x00000000 // 0x00000000 +// 0x00020034 // 0x0000000b +		ram_wr32(fuc, 0x100b0c, 0x00080028); +		ram_wr32(fuc, 0x611200, 0x00003330); +	} else { +		ram_wr32(fuc, 0x10f800, 0x00001800); +		ram_wr32(fuc, 0x13d8f4, 0x00000000); +		ram_wr32(fuc, 0x1373ec, 0x00020404); +		ram_wr32(fuc, 0x1373f0, 0x00000003); +		ram_wr32(fuc, 0x10f830, 0x40700010); +		ram_wr32(fuc, 0x10f830, 0x40500010); +		ram_wr32(fuc, 0x13d8f4, 0x00000000); +		ram_wr32(fuc, 0x1373f8, 0x00000000); +		ram_wr32(fuc, 0x132100, 0x00000101); +		ram_wr32(fuc, 0x137310, 0x89201616); +		ram_wr32(fuc, 0x10f050, 0xff000090); +		ram_wr32(fuc, 0x1373ec, 0x00030404); +		ram_wr32(fuc, 0x1373f0, 0x00000002); +	// 0x00020039 // 0x00000011 +		ram_wr32(fuc, 0x132100, 0x00000001); +		ram_wr32(fuc, 0x1373f8, 0x00002000); +		ram_nsec(fuc, 2000); +		ram_wr32(fuc, 0x10f808, 0x7aaa0050); +		ram_wr32(fuc, 0x10f830, 0x00500010); +		ram_wr32(fuc, 0x10f200, 0x00ce1000); +		ram_wr32(fuc, 0x10f090, 0x4000007e); +		ram_nsec(fuc, 2000); +		ram_wr32(fuc, 0x10f314, 0x00000001); +		ram_wr32(fuc, 0x10f210, 0x80000000); +		ram_wr32(fuc, 0x10f338, 0x00300200); +		ram_wr32(fuc, 0x10f300, 0x0000084d); +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f290, 0x0b343825); +		ram_wr32(fuc, 0x10f294, 0x3483028e); +		ram_wr32(fuc, 0x10f298, 0x440c0600); +		ram_wr32(fuc, 0x10f29c, 0x0000214c); +		ram_wr32(fuc, 0x10f2a0, 0x42e20069); +		ram_wr32(fuc, 0x10f200, 0x00ce0000); +		ram_wr32(fuc, 0x10f614, 0x60044e77); +		ram_wr32(fuc, 0x10f610, 0x60044e77); +		ram_wr32(fuc, 0x10f340, 0x00500000); +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f344, 0x00600228); +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f348, 0x00700000); +		ram_wr32(fuc, 0x13d8f4, 0x00000000); +		ram_wr32(fuc, 0x61c140, 0x09a40000); + +		nvc0_ram_train(fuc, 0x800e1008); + +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f800, 0x00001804); +	// 0x00030020 // 0x00000000 // 0x00000000 +	// 0x00020034 // 0x0000000b +		ram_wr32(fuc, 0x13d8f4, 0x00000000); +		ram_wr32(fuc, 0x100b0c, 0x00080028); +		ram_wr32(fuc, 0x611200, 0x00003330); +		ram_nsec(fuc, 100000); +		ram_wr32(fuc, 0x10f9b0, 0x05313f41); +		ram_wr32(fuc, 0x10f9b4, 0x00002f50); + +		nvc0_ram_train(fuc, 0x010c1001); +	} + +	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000800); +// 0x00020016 // 0x00000000 + +	if (mode == 0) +		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000); +	return 0; +} + +static int +nvc0_ram_prog(struct nouveau_fb *pfb) +{ +	struct nouveau_device *device = nv_device(pfb); +	struct nvc0_ram *ram = (void *)pfb->ram; +	struct nvc0_ramfuc *fuc = &ram->fuc; +	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true)); +	return 0; +} + +static void +nvc0_ram_tidy(struct nouveau_fb *pfb) +{ +	struct nvc0_ram *ram = (void *)pfb->ram; +	struct nvc0_ramfuc *fuc = &ram->fuc; +	ram_exec(fuc, false); +}  extern const u8 nvc0_pte_storage_type_map[256]; @@ -110,10 +503,10 @@ nvc0_ram_get(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin,  	return 0;  } -static int -nvc0_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, -		struct nouveau_oclass *oclass, void *data, u32 size, -		struct nouveau_object **pobject) +int +nvc0_ram_create_(struct nouveau_object *parent, struct nouveau_object *engine, +		 struct nouveau_oclass *oclass, u32 maskaddr, int size, +		 void **pobject)  {  	struct nouveau_fb *pfb = nouveau_fb(parent);  	struct nouveau_bios *bios = nouveau_bios(pfb); @@ -121,14 +514,14 @@ nvc0_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  	const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */  	const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */  	u32 parts = nv_rd32(pfb, 0x022438); -	u32 pmask = nv_rd32(pfb, 0x022554); +	u32 pmask = nv_rd32(pfb, maskaddr);  	u32 bsize = nv_rd32(pfb, 0x10f20c);  	u32 offset, length;  	bool uniform = true;  	int ret, part; -	ret = nouveau_ram_create(parent, engine, oclass, &ram); -	*pobject = nv_object(ram); +	ret = nouveau_ram_create_(parent, engine, oclass, size, pobject); +	ram = *pobject;  	if (ret)  		return ret; @@ -182,13 +575,158 @@ nvc0_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } +static int +nvc0_ram_init(struct nouveau_object *object) +{ +	struct nouveau_fb *pfb = (void *)object->parent; +	struct nvc0_ram   *ram = (void *)object; +	int ret, i; + +	ret = nouveau_ram_init(&ram->base); +	if (ret) +		return ret; + +	/* prepare for ddr link training, and load training patterns */ +	switch (ram->base.type) { +	case NV_MEM_TYPE_GDDR5: { +		static const u8  train0[] = { +			0x00, 0xff, 0x55, 0xaa, 0x33, 0xcc, +			0x00, 0xff, 0xff, 0x00, 0xff, 0x00, +		}; +		static const u32 train1[] = { +			0x00000000, 0xffffffff, +			0x55555555, 0xaaaaaaaa, +			0x33333333, 0xcccccccc, +			0xf0f0f0f0, 0x0f0f0f0f, +			0x00ff00ff, 0xff00ff00, +			0x0000ffff, 0xffff0000, +		}; + +		for (i = 0; i < 0x30; i++) { +			nv_wr32(pfb, 0x10f968, 0x00000000 | (i << 8)); +			nv_wr32(pfb, 0x10f96c, 0x00000000 | (i << 8)); +			nv_wr32(pfb, 0x10f920, 0x00000100 | train0[i % 12]); +			nv_wr32(pfb, 0x10f924, 0x00000100 | train0[i % 12]); +			nv_wr32(pfb, 0x10f918,              train1[i % 12]); +			nv_wr32(pfb, 0x10f91c,              train1[i % 12]); +			nv_wr32(pfb, 0x10f920, 0x00000000 | train0[i % 12]); +			nv_wr32(pfb, 0x10f924, 0x00000000 | train0[i % 12]); +			nv_wr32(pfb, 0x10f918,              train1[i % 12]); +			nv_wr32(pfb, 0x10f91c,              train1[i % 12]); +		} +	}	break; +	default: +		break; +	} + +	return 0; +} + +static int +nvc0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 size, +	      struct nouveau_object **pobject) +{ +	struct nouveau_bios *bios = nouveau_bios(parent); +	struct nvc0_ram *ram; +	int ret; + +	ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; + +	ret = nvbios_pll_parse(bios, 0x0c, &ram->refpll); +	if (ret) { +		nv_error(ram, "mclk refpll data not found\n"); +		return ret; +	} + +	ret = nvbios_pll_parse(bios, 0x04, &ram->mempll); +	if (ret) { +		nv_error(ram, "mclk pll data not found\n"); +		return ret; +	} + +	switch (ram->base.type) { +	case NV_MEM_TYPE_GDDR5: +		ram->base.calc = nvc0_ram_calc; +		ram->base.prog = nvc0_ram_prog; +		ram->base.tidy = nvc0_ram_tidy; +		break; +	default: +		nv_warn(ram, "reclocking of this ram type unsupported\n"); +		return 0; +	} + +	ram->fuc.r_0x10fe20 = ramfuc_reg(0x10fe20); +	ram->fuc.r_0x10fe24 = ramfuc_reg(0x10fe24); +	ram->fuc.r_0x137320 = ramfuc_reg(0x137320); +	ram->fuc.r_0x137330 = ramfuc_reg(0x137330); + +	ram->fuc.r_0x132000 = ramfuc_reg(0x132000); +	ram->fuc.r_0x132004 = ramfuc_reg(0x132004); +	ram->fuc.r_0x132100 = ramfuc_reg(0x132100); + +	ram->fuc.r_0x137390 = ramfuc_reg(0x137390); + +	ram->fuc.r_0x10f290 = ramfuc_reg(0x10f290); +	ram->fuc.r_0x10f294 = ramfuc_reg(0x10f294); +	ram->fuc.r_0x10f298 = ramfuc_reg(0x10f298); +	ram->fuc.r_0x10f29c = ramfuc_reg(0x10f29c); +	ram->fuc.r_0x10f2a0 = ramfuc_reg(0x10f2a0); + +	ram->fuc.r_0x10f300 = ramfuc_reg(0x10f300); +	ram->fuc.r_0x10f338 = ramfuc_reg(0x10f338); +	ram->fuc.r_0x10f340 = ramfuc_reg(0x10f340); +	ram->fuc.r_0x10f344 = ramfuc_reg(0x10f344); +	ram->fuc.r_0x10f348 = ramfuc_reg(0x10f348); + +	ram->fuc.r_0x10f910 = ramfuc_reg(0x10f910); +	ram->fuc.r_0x10f914 = ramfuc_reg(0x10f914); + +	ram->fuc.r_0x100b0c = ramfuc_reg(0x100b0c); +	ram->fuc.r_0x10f050 = ramfuc_reg(0x10f050); +	ram->fuc.r_0x10f090 = ramfuc_reg(0x10f090); +	ram->fuc.r_0x10f200 = ramfuc_reg(0x10f200); +	ram->fuc.r_0x10f210 = ramfuc_reg(0x10f210); +	ram->fuc.r_0x10f310 = ramfuc_reg(0x10f310); +	ram->fuc.r_0x10f314 = ramfuc_reg(0x10f314); +	ram->fuc.r_0x10f610 = ramfuc_reg(0x10f610); +	ram->fuc.r_0x10f614 = ramfuc_reg(0x10f614); +	ram->fuc.r_0x10f800 = ramfuc_reg(0x10f800); +	ram->fuc.r_0x10f808 = ramfuc_reg(0x10f808); +	ram->fuc.r_0x10f824 = ramfuc_reg(0x10f824); +	ram->fuc.r_0x10f830 = ramfuc_reg(0x10f830); +	ram->fuc.r_0x10f988 = ramfuc_reg(0x10f988); +	ram->fuc.r_0x10f98c = ramfuc_reg(0x10f98c); +	ram->fuc.r_0x10f990 = ramfuc_reg(0x10f990); +	ram->fuc.r_0x10f998 = ramfuc_reg(0x10f998); +	ram->fuc.r_0x10f9b0 = ramfuc_reg(0x10f9b0); +	ram->fuc.r_0x10f9b4 = ramfuc_reg(0x10f9b4); +	ram->fuc.r_0x10fb04 = ramfuc_reg(0x10fb04); +	ram->fuc.r_0x10fb08 = ramfuc_reg(0x10fb08); +	ram->fuc.r_0x137310 = ramfuc_reg(0x137300); +	ram->fuc.r_0x137310 = ramfuc_reg(0x137310); +	ram->fuc.r_0x137360 = ramfuc_reg(0x137360); +	ram->fuc.r_0x1373ec = ramfuc_reg(0x1373ec); +	ram->fuc.r_0x1373f0 = ramfuc_reg(0x1373f0); +	ram->fuc.r_0x1373f8 = ramfuc_reg(0x1373f8); + +	ram->fuc.r_0x61c140 = ramfuc_reg(0x61c140); +	ram->fuc.r_0x611200 = ramfuc_reg(0x611200); + +	ram->fuc.r_0x13d8f4 = ramfuc_reg(0x13d8f4); +	return 0; +} +  struct nouveau_oclass  nvc0_ram_oclass = {  	.handle = 0,  	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvc0_ram_create, +		.ctor = nvc0_ram_ctor,  		.dtor = _nouveau_ram_dtor, -		.init = _nouveau_ram_init, +		.init = nvc0_ram_init,  		.fini = _nouveau_ram_fini,  	}  }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c new file mode 100644 index 00000000000..c5b46e30231 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnve0.c @@ -0,0 +1,1392 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/gpio.h> + +#include <subdev/bios.h> +#include <subdev/bios/pll.h> +#include <subdev/bios/init.h> +#include <subdev/bios/rammap.h> +#include <subdev/bios/timing.h> + +#include <subdev/clock.h> +#include <subdev/clock/pll.h> + +#include <subdev/timer.h> + +#include <core/option.h> + +#include "nvc0.h" + +#include "ramfuc.h" + +/* binary driver only executes this path if the condition (a) is true + * for any configuration (combination of rammap+ramcfg+timing) that + * can be reached on a given card.  for now, we will execute the branch + * unconditionally in the hope that a "false everywhere" in the bios + * tables doesn't actually mean "don't touch this". + */ +#define NOTE00(a) 1 + +struct nve0_ramfuc { +	struct ramfuc base; + +	struct nvbios_pll refpll; +	struct nvbios_pll mempll; + +	struct ramfuc_reg r_gpioMV; +	u32 r_funcMV[2]; +	struct ramfuc_reg r_gpio2E; +	u32 r_func2E[2]; +	struct ramfuc_reg r_gpiotrig; + +	struct ramfuc_reg r_0x132020; +	struct ramfuc_reg r_0x132028; +	struct ramfuc_reg r_0x132024; +	struct ramfuc_reg r_0x132030; +	struct ramfuc_reg r_0x132034; +	struct ramfuc_reg r_0x132000; +	struct ramfuc_reg r_0x132004; +	struct ramfuc_reg r_0x132040; + +	struct ramfuc_reg r_0x10f248; +	struct ramfuc_reg r_0x10f290; +	struct ramfuc_reg r_0x10f294; +	struct ramfuc_reg r_0x10f298; +	struct ramfuc_reg r_0x10f29c; +	struct ramfuc_reg r_0x10f2a0; +	struct ramfuc_reg r_0x10f2a4; +	struct ramfuc_reg r_0x10f2a8; +	struct ramfuc_reg r_0x10f2ac; +	struct ramfuc_reg r_0x10f2cc; +	struct ramfuc_reg r_0x10f2e8; +	struct ramfuc_reg r_0x10f250; +	struct ramfuc_reg r_0x10f24c; +	struct ramfuc_reg r_0x10fec4; +	struct ramfuc_reg r_0x10fec8; +	struct ramfuc_reg r_0x10f604; +	struct ramfuc_reg r_0x10f614; +	struct ramfuc_reg r_0x10f610; +	struct ramfuc_reg r_0x100770; +	struct ramfuc_reg r_0x100778; +	struct ramfuc_reg r_0x10f224; + +	struct ramfuc_reg r_0x10f870; +	struct ramfuc_reg r_0x10f698; +	struct ramfuc_reg r_0x10f694; +	struct ramfuc_reg r_0x10f6b8; +	struct ramfuc_reg r_0x10f808; +	struct ramfuc_reg r_0x10f670; +	struct ramfuc_reg r_0x10f60c; +	struct ramfuc_reg r_0x10f830; +	struct ramfuc_reg r_0x1373ec; +	struct ramfuc_reg r_0x10f800; +	struct ramfuc_reg r_0x10f82c; + +	struct ramfuc_reg r_0x10f978; +	struct ramfuc_reg r_0x10f910; +	struct ramfuc_reg r_0x10f914; + +	struct ramfuc_reg r_mr[16]; /* MR0 - MR8, MR15 */ + +	struct ramfuc_reg r_0x62c000; + +	struct ramfuc_reg r_0x10f200; + +	struct ramfuc_reg r_0x10f210; +	struct ramfuc_reg r_0x10f310; +	struct ramfuc_reg r_0x10f314; +	struct ramfuc_reg r_0x10f318; +	struct ramfuc_reg r_0x10f090; +	struct ramfuc_reg r_0x10f69c; +	struct ramfuc_reg r_0x10f824; +	struct ramfuc_reg r_0x1373f0; +	struct ramfuc_reg r_0x1373f4; +	struct ramfuc_reg r_0x137320; +	struct ramfuc_reg r_0x10f65c; +	struct ramfuc_reg r_0x10f6bc; +	struct ramfuc_reg r_0x100710; +	struct ramfuc_reg r_0x100750; +}; + +struct nve0_ram { +	struct nouveau_ram base; +	struct nve0_ramfuc fuc; + +	u32 parts; +	u32 pmask; +	u32 pnuts; + +	int from; +	int mode; +	int N1, fN1, M1, P1; +	int N2, M2, P2; +}; + +/******************************************************************************* + * GDDR5 + ******************************************************************************/ +static void +nve0_ram_train(struct nve0_ramfuc *fuc, u32 mask, u32 data) +{ +	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc); +	u32 addr = 0x110974, i; + +	ram_mask(fuc, 0x10f910, mask, data); +	ram_mask(fuc, 0x10f914, mask, data); + +	for (i = 0; (data & 0x80000000) && i < ram->parts; addr += 0x1000, i++) { +		if (ram->pmask & (1 << i)) +			continue; +		ram_wait(fuc, addr, 0x0000000f, 0x00000000, 500000); +	} +} + +static void +r1373f4_init(struct nve0_ramfuc *fuc) +{ +	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc); +	const u32 mcoef = ((--ram->P2 << 28) | (ram->N2 << 8) | ram->M2); +	const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1); +	const u32 runk0 = ram->fN1 << 16; +	const u32 runk1 = ram->fN1; + +	if (ram->from == 2) { +		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00001100); +		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00000010); +	} else { +		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010); +	} + +	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000); +	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000); + +	/* (re)program refpll, if required */ +	if ((ram_rd32(fuc, 0x132024) & 0xffffffff) != rcoef || +	    (ram_rd32(fuc, 0x132034) & 0x0000ffff) != runk1) { +		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000); +		ram_mask(fuc, 0x132020, 0x00000001, 0x00000000); +		ram_wr32(fuc, 0x137320, 0x00000000); +		ram_mask(fuc, 0x132030, 0xffff0000, runk0); +		ram_mask(fuc, 0x132034, 0x0000ffff, runk1); +		ram_wr32(fuc, 0x132024, rcoef); +		ram_mask(fuc, 0x132028, 0x00080000, 0x00080000); +		ram_mask(fuc, 0x132020, 0x00000001, 0x00000001); +		ram_wait(fuc, 0x137390, 0x00020000, 0x00020000, 64000); +		ram_mask(fuc, 0x132028, 0x00080000, 0x00000000); +	} + +	/* (re)program mempll, if required */ +	if (ram->mode == 2) { +		ram_mask(fuc, 0x1373f4, 0x00010000, 0x00000000); +		ram_mask(fuc, 0x132000, 0x80000000, 0x80000000); +		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000); +		ram_mask(fuc, 0x132004, 0x103fffff, mcoef); +		ram_mask(fuc, 0x132000, 0x00000001, 0x00000001); +		ram_wait(fuc, 0x137390, 0x00000002, 0x00000002, 64000); +		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00001100); +	} else { +		ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010100); +	} + +	ram_mask(fuc, 0x1373f4, 0x00000000, 0x00000010); +} + +static void +r1373f4_fini(struct nve0_ramfuc *fuc) +{ +	struct nve0_ram *ram = container_of(fuc, typeof(*ram), fuc); +	struct nouveau_ram_data *next = ram->base.next; +	u8 v0 = next->bios.ramcfg_11_03_c0; +	u8 v1 = next->bios.ramcfg_11_03_30; +	u32 tmp; + +	tmp = ram_rd32(fuc, 0x1373ec) & ~0x00030000; +	ram_wr32(fuc, 0x1373ec, tmp | (v1 << 16)); +	ram_mask(fuc, 0x1373f0, (~ram->mode & 3), 0x00000000); +	if (ram->mode == 2) { +		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000002); +		ram_mask(fuc, 0x1373f4, 0x00001100, 0x000000000); +	} else { +		ram_mask(fuc, 0x1373f4, 0x00000003, 0x000000001); +		ram_mask(fuc, 0x1373f4, 0x00010000, 0x000000000); +	} +	ram_mask(fuc, 0x10f800, 0x00000030, (v0 ^ v1) << 4); +} + +static void +nve0_ram_nuts(struct nve0_ram *ram, struct ramfuc_reg *reg, +	      u32 _mask, u32 _data, u32 _copy) +{ +	struct nve0_fb_priv *priv = (void *)nouveau_fb(ram); +	struct ramfuc *fuc = &ram->fuc.base; +	u32 addr = 0x110000 + (reg->addr[0] & 0xfff); +	u32 mask = _mask | _copy; +	u32 data = (_data & _mask) | (reg->data & _copy); +	u32 i; + +	for (i = 0; i < 16; i++, addr += 0x1000) { +		if (ram->pnuts & (1 << i)) { +			u32 prev = nv_rd32(priv, addr); +			u32 next = (prev & ~mask) | data; +			nouveau_memx_wr32(fuc->memx, addr, next); +		} +	} +} +#define ram_nuts(s,r,m,d,c)                                                    \ +	nve0_ram_nuts((s), &(s)->fuc.r_##r, (m), (d), (c)) + +static int +nve0_ram_calc_gddr5(struct nouveau_fb *pfb, u32 freq) +{ +	struct nve0_ram *ram = (void *)pfb->ram; +	struct nve0_ramfuc *fuc = &ram->fuc; +	struct nouveau_ram_data *next = ram->base.next; +	int vc = !next->bios.ramcfg_11_02_08; +	int mv = !next->bios.ramcfg_11_02_04; +	u32 mask, data; + +	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000); +	ram_wr32(fuc, 0x62c000, 0x0f0f0000); + +	/* MR1: turn termination on early, for some reason.. */ +	if ((ram->base.mr[1] & 0x03c) != 0x030) { +		ram_mask(fuc, mr[1], 0x03c, ram->base.mr[1] & 0x03c); +		ram_nuts(ram, mr[1], 0x03c, ram->base.mr1_nuts & 0x03c, 0x000); +	} + +	if (vc == 1 && ram_have(fuc, gpio2E)) { +		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]); +		if (temp != ram_rd32(fuc, gpio2E)) { +			ram_wr32(fuc, gpiotrig, 1); +			ram_nsec(fuc, 20000); +		} +	} + +	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000); + +	nve0_ram_train(fuc, 0x01020000, 0x000c0000); + +	ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */ +	ram_nsec(fuc, 1000); +	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ +	ram_nsec(fuc, 1000); + +	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); +	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ +	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000); +	ram_wr32(fuc, 0x10f090, 0x00000061); +	ram_wr32(fuc, 0x10f090, 0xc000007f); +	ram_nsec(fuc, 1000); + +	ram_wr32(fuc, 0x10f698, 0x00000000); +	ram_wr32(fuc, 0x10f69c, 0x00000000); + +	/*XXX: there does appear to be some kind of condition here, simply +	 *     modifying these bits in the vbios from the default pl0 +	 *     entries shows no change.  however, the data does appear to +	 *     be correct and may be required for the transition back +	 */ +	mask = 0x800f07e0; +	data = 0x00030000; +	if (ram_rd32(fuc, 0x10f978) & 0x00800000) +		data |= 0x00040000; + +	if (1) { +		data |= 0x800807e0; +		switch (next->bios.ramcfg_11_03_c0) { +		case 3: data &= ~0x00000040; break; +		case 2: data &= ~0x00000100; break; +		case 1: data &= ~0x80000000; break; +		case 0: data &= ~0x00000400; break; +		} + +		switch (next->bios.ramcfg_11_03_30) { +		case 3: data &= ~0x00000020; break; +		case 2: data &= ~0x00000080; break; +		case 1: data &= ~0x00080000; break; +		case 0: data &= ~0x00000200; break; +		} +	} + +	if (next->bios.ramcfg_11_02_80) +		mask |= 0x03000000; +	if (next->bios.ramcfg_11_02_40) +		mask |= 0x00002000; +	if (next->bios.ramcfg_11_07_10) +		mask |= 0x00004000; +	if (next->bios.ramcfg_11_07_08) +		mask |= 0x00000003; +	else { +		mask |= 0x34000000; +		if (ram_rd32(fuc, 0x10f978) & 0x00800000) +			mask |= 0x40000000; +	} +	ram_mask(fuc, 0x10f824, mask, data); + +	ram_mask(fuc, 0x132040, 0x00010000, 0x00000000); + +	if (ram->from == 2 && ram->mode != 2) { +		ram_mask(fuc, 0x10f808, 0x00080000, 0x00000000); +		ram_mask(fuc, 0x10f200, 0x18008000, 0x00008000); +		ram_mask(fuc, 0x10f800, 0x00000000, 0x00000004); +		ram_mask(fuc, 0x10f830, 0x00008000, 0x01040010); +		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000); +		r1373f4_init(fuc); +		ram_mask(fuc, 0x1373f0, 0x00000002, 0x00000001); +		r1373f4_fini(fuc); +		ram_mask(fuc, 0x10f830, 0x00c00000, 0x00240001); +	} else +	if (ram->from != 2 && ram->mode != 2) { +		r1373f4_init(fuc); +		r1373f4_fini(fuc); +	} + +	if (ram_have(fuc, gpioMV)) { +		u32 temp  = ram_mask(fuc, gpioMV, 0x3000, fuc->r_funcMV[mv]); +		if (temp != ram_rd32(fuc, gpioMV)) { +			ram_wr32(fuc, gpiotrig, 1); +			ram_nsec(fuc, 64000); +		} +	} + +	if (next->bios.ramcfg_11_02_40 || +	    next->bios.ramcfg_11_07_10) { +		ram_mask(fuc, 0x132040, 0x00010000, 0x00010000); +		ram_nsec(fuc, 20000); +	} + +	if (ram->from != 2 && ram->mode == 2) { +		if (0 /*XXX: Titan */) +			ram_mask(fuc, 0x10f200, 0x18000000, 0x18000000); +		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000); +		ram_mask(fuc, 0x1373f0, 0x00000000, 0x00000002); +		ram_mask(fuc, 0x10f830, 0x00800001, 0x00408010); +		r1373f4_init(fuc); +		r1373f4_fini(fuc); +		ram_mask(fuc, 0x10f808, 0x00000000, 0x00080000); +		ram_mask(fuc, 0x10f200, 0x00808000, 0x00800000); +	} else +	if (ram->from == 2 && ram->mode == 2) { +		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000000); +		r1373f4_init(fuc); +		r1373f4_fini(fuc); +	} + +	if (ram->mode != 2) /*XXX*/ { +		if (next->bios.ramcfg_11_07_40) +			ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000); +	} + +	ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c); +	ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09); +	ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09); + +	if (!next->bios.ramcfg_11_07_08 && !next->bios.ramcfg_11_07_04) { +		ram_wr32(fuc, 0x10f698, 0x01010101 * next->bios.ramcfg_11_04); +		ram_wr32(fuc, 0x10f69c, 0x01010101 * next->bios.ramcfg_11_04); +	} else +	if (!next->bios.ramcfg_11_07_08) { +		ram_wr32(fuc, 0x10f698, 0x00000000); +		ram_wr32(fuc, 0x10f69c, 0x00000000); +	} + +	if (ram->mode != 2) { +		u32 data = 0x01000100 * next->bios.ramcfg_11_04; +		ram_nuke(fuc, 0x10f694); +		ram_mask(fuc, 0x10f694, 0xff00ff00, data); +	} + +	if (ram->mode == 2 && next->bios.ramcfg_11_08_10) +		data = 0x00000080; +	else +		data = 0x00000000; +	ram_mask(fuc, 0x10f60c, 0x00000080, data); + +	mask = 0x00070000; +	data = 0x00000000; +	if (!next->bios.ramcfg_11_02_80) +		data |= 0x03000000; +	if (!next->bios.ramcfg_11_02_40) +		data |= 0x00002000; +	if (!next->bios.ramcfg_11_07_10) +		data |= 0x00004000; +	if (!next->bios.ramcfg_11_07_08) +		data |= 0x00000003; +	else +		data |= 0x74000000; +	ram_mask(fuc, 0x10f824, mask, data); + +	if (next->bios.ramcfg_11_01_08) +		data = 0x00000000; +	else +		data = 0x00001000; +	ram_mask(fuc, 0x10f200, 0x00001000, data); + +	if (ram_rd32(fuc, 0x10f670) & 0x80000000) { +		ram_nsec(fuc, 10000); +		ram_mask(fuc, 0x10f670, 0x80000000, 0x00000000); +	} + +	if (next->bios.ramcfg_11_08_01) +		data = 0x00100000; +	else +		data = 0x00000000; +	ram_mask(fuc, 0x10f82c, 0x00100000, data); + +	data = 0x00000000; +	if (next->bios.ramcfg_11_08_08) +		data |= 0x00002000; +	if (next->bios.ramcfg_11_08_04) +		data |= 0x00001000; +	if (next->bios.ramcfg_11_08_02) +		data |= 0x00004000; +	ram_mask(fuc, 0x10f830, 0x00007000, data); + +	/* PFB timing */ +	ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]); +	ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]); +	ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]); +	ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]); +	ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]); +	ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]); +	ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]); +	ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]); +	ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]); +	ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]); +	ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]); + +	data = mask = 0x00000000; +	if (NOTE00(ramcfg_08_20)) { +		if (next->bios.ramcfg_11_08_20) +			data |= 0x01000000; +		mask |= 0x01000000; +	} +	ram_mask(fuc, 0x10f200, mask, data); + +	data = mask = 0x00000000; +	if (NOTE00(ramcfg_02_03 != 0)) { +		data |= next->bios.ramcfg_11_02_03 << 8; +		mask |= 0x00000300; +	} +	if (NOTE00(ramcfg_01_10)) { +		if (next->bios.ramcfg_11_01_10) +			data |= 0x70000000; +		mask |= 0x70000000; +	} +	ram_mask(fuc, 0x10f604, mask, data); + +	data = mask = 0x00000000; +	if (NOTE00(timing_30_07 != 0)) { +		data |= next->bios.timing_20_30_07 << 28; +		mask |= 0x70000000; +	} +	if (NOTE00(ramcfg_01_01)) { +		if (next->bios.ramcfg_11_01_01) +			data |= 0x00000100; +		mask |= 0x00000100; +	} +	ram_mask(fuc, 0x10f614, mask, data); + +	data = mask = 0x00000000; +	if (NOTE00(timing_30_07 != 0)) { +		data |= next->bios.timing_20_30_07 << 28; +		mask |= 0x70000000; +	} +	if (NOTE00(ramcfg_01_02)) { +		if (next->bios.ramcfg_11_01_02) +			data |= 0x00000100; +		mask |= 0x00000100; +	} +	ram_mask(fuc, 0x10f610, mask, data); + +	mask = 0x33f00000; +	data = 0x00000000; +	if (!next->bios.ramcfg_11_01_04) +		data |= 0x20200000; +	if (!next->bios.ramcfg_11_07_80) +		data |= 0x12800000; +	/*XXX: see note above about there probably being some condition +	 *     for the 10f824 stuff that uses ramcfg 3... +	 */ +	if (next->bios.ramcfg_11_03_f0) { +		if (next->bios.rammap_11_08_0c) { +			if (!next->bios.ramcfg_11_07_80) +				mask |= 0x00000020; +			else +				data |= 0x00000020; +			mask |= 0x00000004; +		} +	} else { +		mask |= 0x40000020; +		data |= 0x00000004; +	} + +	ram_mask(fuc, 0x10f808, mask, data); + +	ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f); + +	data = mask = 0x00000000; +	if (NOTE00(ramcfg_02_03 != 0)) { +		data |= next->bios.ramcfg_11_02_03; +		mask |= 0x00000003; +	} +	if (NOTE00(ramcfg_01_10)) { +		if (next->bios.ramcfg_11_01_10) +			data |= 0x00000004; +		mask |= 0x00000004; +	} + +	if ((ram_mask(fuc, 0x100770, mask, data) & mask & 4) != (data & 4)) { +		ram_mask(fuc, 0x100750, 0x00000008, 0x00000008); +		ram_wr32(fuc, 0x100710, 0x00000000); +		ram_wait(fuc, 0x100710, 0x80000000, 0x80000000, 200000); +	} + +	data = next->bios.timing_20_30_07 << 8; +	if (next->bios.ramcfg_11_01_01) +		data |= 0x80000000; +	ram_mask(fuc, 0x100778, 0x00000700, data); + +	ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4); +	data = (next->bios.timing[10] & 0x7f000000) >> 24; +	if (data < next->bios.timing_20_2c_1fc0) +		data = next->bios.timing_20_2c_1fc0; +	ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24); +	ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16); + +	ram_mask(fuc, 0x10fec4, 0x041e0f07, next->bios.timing_20_31_0800 << 26 | +					    next->bios.timing_20_31_0780 << 17 | +					    next->bios.timing_20_31_0078 << 8 | +					    next->bios.timing_20_31_0007); +	ram_mask(fuc, 0x10fec8, 0x00000027, next->bios.timing_20_31_8000 << 5 | +					    next->bios.timing_20_31_7000); + +	ram_wr32(fuc, 0x10f090, 0x4000007e); +	ram_nsec(fuc, 2000); +	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ +	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ +	ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */ + +	if (next->bios.ramcfg_11_08_10 && (ram->mode == 2) /*XXX*/) { +		u32 temp = ram_mask(fuc, 0x10f294, 0xff000000, 0x24000000); +		nve0_ram_train(fuc, 0xbc0e0000, 0xa4010000); /*XXX*/ +		ram_nsec(fuc, 1000); +		ram_wr32(fuc, 0x10f294, temp); +	} + +	ram_mask(fuc, mr[3], 0xfff, ram->base.mr[3]); +	ram_wr32(fuc, mr[0], ram->base.mr[0]); +	ram_mask(fuc, mr[8], 0xfff, ram->base.mr[8]); +	ram_nsec(fuc, 1000); +	ram_mask(fuc, mr[1], 0xfff, ram->base.mr[1]); +	ram_mask(fuc, mr[5], 0xfff, ram->base.mr[5] & ~0x004); /* LP3 later */ +	ram_mask(fuc, mr[6], 0xfff, ram->base.mr[6]); +	ram_mask(fuc, mr[7], 0xfff, ram->base.mr[7]); + +	if (vc == 0 && ram_have(fuc, gpio2E)) { +		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]); +		if (temp != ram_rd32(fuc, gpio2E)) { +			ram_wr32(fuc, gpiotrig, 1); +			ram_nsec(fuc, 20000); +		} +	} + +	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); +	ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */ +	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000); +	ram_nsec(fuc, 1000); +	ram_nuts(ram, 0x10f200, 0x18808800, 0x00000000, 0x18808800); + +	data  = ram_rd32(fuc, 0x10f978); +	data &= ~0x00046144; +	data |=  0x0000000b; +	if (!next->bios.ramcfg_11_07_08) { +		if (!next->bios.ramcfg_11_07_04) +			data |= 0x0000200c; +		else +			data |= 0x00000000; +	} else { +		data |= 0x00040044; +	} +	ram_wr32(fuc, 0x10f978, data); + +	if (ram->mode == 1) { +		data = ram_rd32(fuc, 0x10f830) | 0x00000001; +		ram_wr32(fuc, 0x10f830, data); +	} + +	if (!next->bios.ramcfg_11_07_08) { +		data = 0x88020000; +		if ( next->bios.ramcfg_11_07_04) +			data |= 0x10000000; +		if (!next->bios.rammap_11_08_10) +			data |= 0x00080000; +	} else { +		data = 0xa40e0000; +	} +	nve0_ram_train(fuc, 0xbc0f0000, data); +	if (1) /* XXX: not always? */ +		ram_nsec(fuc, 1000); + +	if (ram->mode == 2) { /*XXX*/ +		ram_mask(fuc, 0x10f800, 0x00000004, 0x00000004); +	} + +	/* LP3 */ +	if (ram_mask(fuc, mr[5], 0x004, ram->base.mr[5]) != ram->base.mr[5]) +		ram_nsec(fuc, 1000); + +	if (ram->mode != 2) { +		ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000); +		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000); +	} + +	if (next->bios.ramcfg_11_07_02) +		nve0_ram_train(fuc, 0x80020000, 0x01000000); + +	ram_wr32(fuc, 0x62c000, 0x0f0f0f00); + +	if (next->bios.rammap_11_08_01) +		data = 0x00000800; +	else +		data = 0x00000000; +	ram_mask(fuc, 0x10f200, 0x00000800, data); +	ram_nuts(ram, 0x10f200, 0x18808800, data, 0x18808800); +	return 0; +} + +/******************************************************************************* + * DDR3 + ******************************************************************************/ + +static int +nve0_ram_calc_sddr3(struct nouveau_fb *pfb, u32 freq) +{ +	struct nve0_ram *ram = (void *)pfb->ram; +	struct nve0_ramfuc *fuc = &ram->fuc; +	const u32 rcoef = ((  ram->P1 << 16) | (ram->N1 << 8) | ram->M1); +	const u32 runk0 = ram->fN1 << 16; +	const u32 runk1 = ram->fN1; +	struct nouveau_ram_data *next = ram->base.next; +	int vc = !next->bios.ramcfg_11_02_08; +	int mv = !next->bios.ramcfg_11_02_04; +	u32 mask, data; + +	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000); +	ram_wr32(fuc, 0x62c000, 0x0f0f0000); + +	if (vc == 1 && ram_have(fuc, gpio2E)) { +		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]); +		if (temp != ram_rd32(fuc, gpio2E)) { +			ram_wr32(fuc, gpiotrig, 1); +			ram_nsec(fuc, 20000); +		} +	} + +	ram_mask(fuc, 0x10f200, 0x00000800, 0x00000000); +	if (next->bios.ramcfg_11_03_f0) +		ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000); + +	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ +	ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */ +	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ +	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); +	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ +	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000); +	ram_nsec(fuc, 1000); + +	ram_wr32(fuc, 0x10f090, 0x00000060); +	ram_wr32(fuc, 0x10f090, 0xc000007e); + +	/*XXX: there does appear to be some kind of condition here, simply +	 *     modifying these bits in the vbios from the default pl0 +	 *     entries shows no change.  however, the data does appear to +	 *     be correct and may be required for the transition back +	 */ +	mask = 0x00010000; +	data = 0x00010000; + +	if (1) { +		mask |= 0x800807e0; +		data |= 0x800807e0; +		switch (next->bios.ramcfg_11_03_c0) { +		case 3: data &= ~0x00000040; break; +		case 2: data &= ~0x00000100; break; +		case 1: data &= ~0x80000000; break; +		case 0: data &= ~0x00000400; break; +		} + +		switch (next->bios.ramcfg_11_03_30) { +		case 3: data &= ~0x00000020; break; +		case 2: data &= ~0x00000080; break; +		case 1: data &= ~0x00080000; break; +		case 0: data &= ~0x00000200; break; +		} +	} + +	if (next->bios.ramcfg_11_02_80) +		mask |= 0x03000000; +	if (next->bios.ramcfg_11_02_40) +		mask |= 0x00002000; +	if (next->bios.ramcfg_11_07_10) +		mask |= 0x00004000; +	if (next->bios.ramcfg_11_07_08) +		mask |= 0x00000003; +	else +		mask |= 0x14000000; +	ram_mask(fuc, 0x10f824, mask, data); + +	ram_mask(fuc, 0x132040, 0x00010000, 0x00000000); + +	ram_mask(fuc, 0x1373f4, 0x00000000, 0x00010010); +	data  = ram_rd32(fuc, 0x1373ec) & ~0x00030000; +	data |= next->bios.ramcfg_11_03_30 << 16; +	ram_wr32(fuc, 0x1373ec, data); +	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000000); +	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000000); + +	/* (re)program refpll, if required */ +	if ((ram_rd32(fuc, 0x132024) & 0xffffffff) != rcoef || +	    (ram_rd32(fuc, 0x132034) & 0x0000ffff) != runk1) { +		ram_mask(fuc, 0x132000, 0x00000001, 0x00000000); +		ram_mask(fuc, 0x132020, 0x00000001, 0x00000000); +		ram_wr32(fuc, 0x137320, 0x00000000); +		ram_mask(fuc, 0x132030, 0xffff0000, runk0); +		ram_mask(fuc, 0x132034, 0x0000ffff, runk1); +		ram_wr32(fuc, 0x132024, rcoef); +		ram_mask(fuc, 0x132028, 0x00080000, 0x00080000); +		ram_mask(fuc, 0x132020, 0x00000001, 0x00000001); +		ram_wait(fuc, 0x137390, 0x00020000, 0x00020000, 64000); +		ram_mask(fuc, 0x132028, 0x00080000, 0x00000000); +	} + +	ram_mask(fuc, 0x1373f4, 0x00000010, 0x00000010); +	ram_mask(fuc, 0x1373f4, 0x00000003, 0x00000001); +	ram_mask(fuc, 0x1373f4, 0x00010000, 0x00000000); + +	if (ram_have(fuc, gpioMV)) { +		u32 temp  = ram_mask(fuc, gpioMV, 0x3000, fuc->r_funcMV[mv]); +		if (temp != ram_rd32(fuc, gpioMV)) { +			ram_wr32(fuc, gpiotrig, 1); +			ram_nsec(fuc, 64000); +		} +	} + +	if (next->bios.ramcfg_11_02_40 || +	    next->bios.ramcfg_11_07_10) { +		ram_mask(fuc, 0x132040, 0x00010000, 0x00010000); +		ram_nsec(fuc, 20000); +	} + +	if (ram->mode != 2) /*XXX*/ { +		if (next->bios.ramcfg_11_07_40) +			ram_mask(fuc, 0x10f670, 0x80000000, 0x80000000); +	} + +	ram_wr32(fuc, 0x10f65c, 0x00000011 * next->bios.rammap_11_11_0c); +	ram_wr32(fuc, 0x10f6b8, 0x01010101 * next->bios.ramcfg_11_09); +	ram_wr32(fuc, 0x10f6bc, 0x01010101 * next->bios.ramcfg_11_09); + +	mask = 0x00010000; +	data = 0x00000000; +	if (!next->bios.ramcfg_11_02_80) +		data |= 0x03000000; +	if (!next->bios.ramcfg_11_02_40) +		data |= 0x00002000; +	if (!next->bios.ramcfg_11_07_10) +		data |= 0x00004000; +	if (!next->bios.ramcfg_11_07_08) +		data |= 0x00000003; +	else +		data |= 0x14000000; +	ram_mask(fuc, 0x10f824, mask, data); +	ram_nsec(fuc, 1000); + +	if (next->bios.ramcfg_11_08_01) +		data = 0x00100000; +	else +		data = 0x00000000; +	ram_mask(fuc, 0x10f82c, 0x00100000, data); + +	/* PFB timing */ +	ram_mask(fuc, 0x10f248, 0xffffffff, next->bios.timing[10]); +	ram_mask(fuc, 0x10f290, 0xffffffff, next->bios.timing[0]); +	ram_mask(fuc, 0x10f294, 0xffffffff, next->bios.timing[1]); +	ram_mask(fuc, 0x10f298, 0xffffffff, next->bios.timing[2]); +	ram_mask(fuc, 0x10f29c, 0xffffffff, next->bios.timing[3]); +	ram_mask(fuc, 0x10f2a0, 0xffffffff, next->bios.timing[4]); +	ram_mask(fuc, 0x10f2a4, 0xffffffff, next->bios.timing[5]); +	ram_mask(fuc, 0x10f2a8, 0xffffffff, next->bios.timing[6]); +	ram_mask(fuc, 0x10f2ac, 0xffffffff, next->bios.timing[7]); +	ram_mask(fuc, 0x10f2cc, 0xffffffff, next->bios.timing[8]); +	ram_mask(fuc, 0x10f2e8, 0xffffffff, next->bios.timing[9]); + +	mask = 0x33f00000; +	data = 0x00000000; +	if (!next->bios.ramcfg_11_01_04) +		data |= 0x20200000; +	if (!next->bios.ramcfg_11_07_80) +		data |= 0x12800000; +	/*XXX: see note above about there probably being some condition +	 *     for the 10f824 stuff that uses ramcfg 3... +	 */ +	if (next->bios.ramcfg_11_03_f0) { +		if (next->bios.rammap_11_08_0c) { +			if (!next->bios.ramcfg_11_07_80) +				mask |= 0x00000020; +			else +				data |= 0x00000020; +			mask |= 0x08000004; +		} +		data |= 0x04000000; +	} else { +		mask |= 0x44000020; +		data |= 0x08000004; +	} + +	ram_mask(fuc, 0x10f808, mask, data); + +	ram_wr32(fuc, 0x10f870, 0x11111111 * next->bios.ramcfg_11_03_0f); + +	ram_mask(fuc, 0x10f250, 0x000003f0, next->bios.timing_20_2c_003f << 4); + +	data = (next->bios.timing[10] & 0x7f000000) >> 24; +	if (data < next->bios.timing_20_2c_1fc0) +		data = next->bios.timing_20_2c_1fc0; +	ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24); + +	ram_mask(fuc, 0x10f224, 0x001f0000, next->bios.timing_20_30_f8 << 16); + +	ram_wr32(fuc, 0x10f090, 0x4000007f); +	ram_nsec(fuc, 1000); + +	ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ +	ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ +	ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */ +	ram_nsec(fuc, 1000); + +	ram_nuke(fuc, mr[0]); +	ram_mask(fuc, mr[0], 0x100, 0x100); +	ram_mask(fuc, mr[0], 0x100, 0x000); + +	ram_mask(fuc, mr[2], 0xfff, ram->base.mr[2]); +	ram_wr32(fuc, mr[0], ram->base.mr[0]); +	ram_nsec(fuc, 1000); + +	ram_nuke(fuc, mr[0]); +	ram_mask(fuc, mr[0], 0x100, 0x100); +	ram_mask(fuc, mr[0], 0x100, 0x000); + +	if (vc == 0 && ram_have(fuc, gpio2E)) { +		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]); +		if (temp != ram_rd32(fuc, gpio2E)) { +			ram_wr32(fuc, gpiotrig, 1); +			ram_nsec(fuc, 20000); +		} +	} + +	if (ram->mode != 2) { +		ram_mask(fuc, 0x10f830, 0x01000000, 0x01000000); +		ram_mask(fuc, 0x10f830, 0x01000000, 0x00000000); +	} + +	ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); +	ram_wr32(fuc, 0x10f318, 0x00000001); /* NOP? */ +	ram_mask(fuc, 0x10f200, 0x80000000, 0x00000000); +	ram_nsec(fuc, 1000); + +	ram_wr32(fuc, 0x62c000, 0x0f0f0f00); + +	if (next->bios.rammap_11_08_01) +		data = 0x00000800; +	else +		data = 0x00000000; +	ram_mask(fuc, 0x10f200, 0x00000800, data); +	return 0; +} + +/******************************************************************************* + * main hooks + ******************************************************************************/ + +static int +nve0_ram_calc_data(struct nouveau_fb *pfb, u32 freq, +		   struct nouveau_ram_data *data) +{ +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nve0_ram *ram = (void *)pfb->ram; +	u8 strap, cnt, len; + +	/* lookup memory config data relevant to the target frequency */ +	ram->base.rammap.data = nvbios_rammapEp(bios, freq / 1000, +					       &ram->base.rammap.version, +					       &ram->base.rammap.size, +					       &cnt, &len, &data->bios); +	if (!ram->base.rammap.data || ram->base.rammap.version != 0x11 || +	     ram->base.rammap.size < 0x09) { +		nv_error(pfb, "invalid/missing rammap entry\n"); +		return -EINVAL; +	} + +	/* locate specific data set for the attached memory */ +	strap = nvbios_ramcfg_index(nv_subdev(pfb)); +	ram->base.ramcfg.data = nvbios_rammapSp(bios, ram->base.rammap.data, +						ram->base.rammap.version, +						ram->base.rammap.size, +						cnt, len, strap, +						&ram->base.ramcfg.version, +						&ram->base.ramcfg.size, +						&data->bios); +	if (!ram->base.ramcfg.data || ram->base.ramcfg.version != 0x11 || +	     ram->base.ramcfg.size < 0x08) { +		nv_error(pfb, "invalid/missing ramcfg entry\n"); +		return -EINVAL; +	} + +	/* lookup memory timings, if bios says they're present */ +	strap = nv_ro08(bios, ram->base.ramcfg.data + 0x00); +	if (strap != 0xff) { +		ram->base.timing.data = +			nvbios_timingEp(bios, strap, &ram->base.timing.version, +				       &ram->base.timing.size, &cnt, &len, +				       &data->bios); +		if (!ram->base.timing.data || +		     ram->base.timing.version != 0x20 || +		     ram->base.timing.size < 0x33) { +			nv_error(pfb, "invalid/missing timing entry\n"); +			return -EINVAL; +		} +	} else { +		ram->base.timing.data = 0; +	} + +	data->freq = freq; +	return 0; +} + +static int +nve0_ram_calc_xits(struct nouveau_fb *pfb, struct nouveau_ram_data *next) +{ +	struct nve0_ram *ram = (void *)pfb->ram; +	struct nve0_ramfuc *fuc = &ram->fuc; +	int refclk, i; +	int ret; + +	ret = ram_init(fuc, pfb); +	if (ret) +		return ret; + +	ram->mode = (next->freq > fuc->refpll.vco1.max_freq) ? 2 : 1; +	ram->from = ram_rd32(fuc, 0x1373f4) & 0x0000000f; + +	/* XXX: this is *not* what nvidia do.  on fermi nvidia generally +	 * select, based on some unknown condition, one of the two possible +	 * reference frequencies listed in the vbios table for mempll and +	 * program refpll to that frequency. +	 * +	 * so far, i've seen very weird values being chosen by nvidia on +	 * kepler boards, no idea how/why they're chosen. +	 */ +	refclk = next->freq; +	if (ram->mode == 2) +		refclk = fuc->mempll.refclk; + +	/* calculate refpll coefficients */ +	ret = nva3_pll_calc(nv_subdev(pfb), &fuc->refpll, refclk, &ram->N1, +			   &ram->fN1, &ram->M1, &ram->P1); +	fuc->mempll.refclk = ret; +	if (ret <= 0) { +		nv_error(pfb, "unable to calc refpll\n"); +		return -EINVAL; +	} + +	/* calculate mempll coefficients, if we're using it */ +	if (ram->mode == 2) { +		/* post-divider doesn't work... the reg takes the values but +		 * appears to completely ignore it.  there *is* a bit at +		 * bit 28 that appears to divide the clock by 2 if set. +		 */ +		fuc->mempll.min_p = 1; +		fuc->mempll.max_p = 2; + +		ret = nva3_pll_calc(nv_subdev(pfb), &fuc->mempll, next->freq, +				   &ram->N2, NULL, &ram->M2, &ram->P2); +		if (ret <= 0) { +			nv_error(pfb, "unable to calc mempll\n"); +			return -EINVAL; +		} +	} + +	for (i = 0; i < ARRAY_SIZE(fuc->r_mr); i++) { +		if (ram_have(fuc, mr[i])) +			ram->base.mr[i] = ram_rd32(fuc, mr[i]); +	} +	ram->base.freq = next->freq; + +	switch (ram->base.type) { +	case NV_MEM_TYPE_DDR3: +		ret = nouveau_sddr3_calc(&ram->base); +		if (ret == 0) +			ret = nve0_ram_calc_sddr3(pfb, next->freq); +		break; +	case NV_MEM_TYPE_GDDR5: +		ret = nouveau_gddr5_calc(&ram->base, ram->pnuts != 0); +		if (ret == 0) +			ret = nve0_ram_calc_gddr5(pfb, next->freq); +		break; +	default: +		ret = -ENOSYS; +		break; +	} + +	return ret; +} + +static int +nve0_ram_calc(struct nouveau_fb *pfb, u32 freq) +{ +	struct nouveau_clock *clk = nouveau_clock(pfb); +	struct nve0_ram *ram = (void *)pfb->ram; +	struct nouveau_ram_data *xits = &ram->base.xition; +	struct nouveau_ram_data *copy; +	int ret; + +	if (ram->base.next == NULL) { +		ret = nve0_ram_calc_data(pfb, clk->read(clk, nv_clk_src_mem), +					&ram->base.former); +		if (ret) +			return ret; + +		ret = nve0_ram_calc_data(pfb, freq, &ram->base.target); +		if (ret) +			return ret; + +		if (ram->base.target.freq < ram->base.former.freq) { +			*xits = ram->base.target; +			copy = &ram->base.former; +		} else { +			*xits = ram->base.former; +			copy = &ram->base.target; +		} + +		xits->bios.ramcfg_11_02_04 = copy->bios.ramcfg_11_02_04; +		xits->bios.ramcfg_11_02_03 = copy->bios.ramcfg_11_02_03; +		xits->bios.timing_20_30_07 = copy->bios.timing_20_30_07; + +		ram->base.next = &ram->base.target; +		if (memcmp(xits, &ram->base.former, sizeof(xits->bios))) +			ram->base.next = &ram->base.xition; +	} else { +		BUG_ON(ram->base.next != &ram->base.xition); +		ram->base.next = &ram->base.target; +	} + +	return nve0_ram_calc_xits(pfb, ram->base.next); +} + +static int +nve0_ram_prog(struct nouveau_fb *pfb) +{ +	struct nouveau_device *device = nv_device(pfb); +	struct nve0_ram *ram = (void *)pfb->ram; +	struct nve0_ramfuc *fuc = &ram->fuc; +	ram_exec(fuc, nouveau_boolopt(device->cfgopt, "NvMemExec", true)); +	return (ram->base.next == &ram->base.xition); +} + +static void +nve0_ram_tidy(struct nouveau_fb *pfb) +{ +	struct nve0_ram *ram = (void *)pfb->ram; +	struct nve0_ramfuc *fuc = &ram->fuc; +	ram->base.next = NULL; +	ram_exec(fuc, false); +} + +int +nve0_ram_init(struct nouveau_object *object) +{ +	struct nouveau_fb *pfb = (void *)object->parent; +	struct nve0_ram *ram   = (void *)object; +	struct nouveau_bios *bios = nouveau_bios(pfb); +	static const u8  train0[] = { +		0x00, 0xff, 0xff, 0x00, 0xff, 0x00, +		0x00, 0xff, 0xff, 0x00, 0xff, 0x00, +	}; +	static const u32 train1[] = { +		0x00000000, 0xffffffff, +		0x55555555, 0xaaaaaaaa, +		0x33333333, 0xcccccccc, +		0xf0f0f0f0, 0x0f0f0f0f, +		0x00ff00ff, 0xff00ff00, +		0x0000ffff, 0xffff0000, +	}; +	u8  ver, hdr, cnt, len, snr, ssz; +	u32 data, save; +	int ret, i; + +	ret = nouveau_ram_init(&ram->base); +	if (ret) +		return ret; + +	/* run a bunch of tables from rammap table.  there's actually +	 * individual pointers for each rammap entry too, but, nvidia +	 * seem to just run the last two entries' scripts early on in +	 * their init, and never again.. we'll just run 'em all once +	 * for now. +	 * +	 * i strongly suspect that each script is for a separate mode +	 * (likely selected by 0x10f65c's lower bits?), and the +	 * binary driver skips the one that's already been setup by +	 * the init tables. +	 */ +	data = nvbios_rammapTe(bios, &ver, &hdr, &cnt, &len, &snr, &ssz); +	if (!data || hdr < 0x15) +		return -EINVAL; + +	cnt  = nv_ro08(bios, data + 0x14); /* guess at count */ +	data = nv_ro32(bios, data + 0x10); /* guess u32... */ +	save = nv_rd32(pfb, 0x10f65c); +	for (i = 0; i < cnt; i++) { +		nv_mask(pfb, 0x10f65c, 0x000000f0, i << 4); +		nvbios_exec(&(struct nvbios_init) { +				.subdev = nv_subdev(pfb), +				.bios = bios, +				.offset = nv_ro32(bios, data), /* guess u32 */ +				.execute = 1, +			    }); +		data += 4; +	} +	nv_wr32(pfb, 0x10f65c, save); +	nv_mask(pfb, 0x10f584, 0x11000000, 0x00000000); + +	switch (ram->base.type) { +	case NV_MEM_TYPE_GDDR5: +		for (i = 0; i < 0x30; i++) { +			nv_wr32(pfb, 0x10f968, 0x00000000 | (i << 8)); +			nv_wr32(pfb, 0x10f920, 0x00000000 | train0[i % 12]); +			nv_wr32(pfb, 0x10f918,              train1[i % 12]); +			nv_wr32(pfb, 0x10f920, 0x00000100 | train0[i % 12]); +			nv_wr32(pfb, 0x10f918,              train1[i % 12]); + +			nv_wr32(pfb, 0x10f96c, 0x00000000 | (i << 8)); +			nv_wr32(pfb, 0x10f924, 0x00000000 | train0[i % 12]); +			nv_wr32(pfb, 0x10f91c,              train1[i % 12]); +			nv_wr32(pfb, 0x10f924, 0x00000100 | train0[i % 12]); +			nv_wr32(pfb, 0x10f91c,              train1[i % 12]); +		} + +		for (i = 0; i < 0x100; i++) { +			nv_wr32(pfb, 0x10f968, i); +			nv_wr32(pfb, 0x10f900, train1[2 + (i & 1)]); +		} + +		for (i = 0; i < 0x100; i++) { +			nv_wr32(pfb, 0x10f96c, i); +			nv_wr32(pfb, 0x10f900, train1[2 + (i & 1)]); +		} +		break; +	default: +		break; +	} + +	return 0; +} + +static int +nve0_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 size, +	      struct nouveau_object **pobject) +{ +	struct nouveau_fb *pfb = nouveau_fb(parent); +	struct nouveau_bios *bios = nouveau_bios(pfb); +	struct nouveau_gpio *gpio = nouveau_gpio(pfb); +	struct dcb_gpio_func func; +	struct nve0_ram *ram; +	int ret, i; +	u32 tmp; + +	ret = nvc0_ram_create(parent, engine, oclass, 0x022554, &ram); +	*pobject = nv_object(ram); +	if (ret) +		return ret; + +	switch (ram->base.type) { +	case NV_MEM_TYPE_DDR3: +	case NV_MEM_TYPE_GDDR5: +		ram->base.calc = nve0_ram_calc; +		ram->base.prog = nve0_ram_prog; +		ram->base.tidy = nve0_ram_tidy; +		break; +	default: +		nv_warn(pfb, "reclocking of this RAM type is unsupported\n"); +		break; +	} + +	/* calculate a mask of differently configured memory partitions, +	 * because, of course reclocking wasn't complicated enough +	 * already without having to treat some of them differently to +	 * the others.... +	 */ +	ram->parts = nv_rd32(pfb, 0x022438); +	ram->pmask = nv_rd32(pfb, 0x022554); +	ram->pnuts = 0; +	for (i = 0, tmp = 0; i < ram->parts; i++) { +		if (!(ram->pmask & (1 << i))) { +			u32 cfg1 = nv_rd32(pfb, 0x110204 + (i * 0x1000)); +			if (tmp && tmp != cfg1) { +				ram->pnuts |= (1 << i); +				continue; +			} +			tmp = cfg1; +		} +	} + +	// parse bios data for both pll's +	ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll); +	if (ret) { +		nv_error(pfb, "mclk refpll data not found\n"); +		return ret; +	} + +	ret = nvbios_pll_parse(bios, 0x04, &ram->fuc.mempll); +	if (ret) { +		nv_error(pfb, "mclk pll data not found\n"); +		return ret; +	} + +	ret = gpio->find(gpio, 0, 0x18, DCB_GPIO_UNUSED, &func); +	if (ret == 0) { +		ram->fuc.r_gpioMV = ramfuc_reg(0x00d610 + (func.line * 0x04)); +		ram->fuc.r_funcMV[0] = (func.log[0] ^ 2) << 12; +		ram->fuc.r_funcMV[1] = (func.log[1] ^ 2) << 12; +	} + +	ret = gpio->find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); +	if (ret == 0) { +		ram->fuc.r_gpio2E = ramfuc_reg(0x00d610 + (func.line * 0x04)); +		ram->fuc.r_func2E[0] = (func.log[0] ^ 2) << 12; +		ram->fuc.r_func2E[1] = (func.log[1] ^ 2) << 12; +	} + +	ram->fuc.r_gpiotrig = ramfuc_reg(0x00d604); + +	ram->fuc.r_0x132020 = ramfuc_reg(0x132020); +	ram->fuc.r_0x132028 = ramfuc_reg(0x132028); +	ram->fuc.r_0x132024 = ramfuc_reg(0x132024); +	ram->fuc.r_0x132030 = ramfuc_reg(0x132030); +	ram->fuc.r_0x132034 = ramfuc_reg(0x132034); +	ram->fuc.r_0x132000 = ramfuc_reg(0x132000); +	ram->fuc.r_0x132004 = ramfuc_reg(0x132004); +	ram->fuc.r_0x132040 = ramfuc_reg(0x132040); + +	ram->fuc.r_0x10f248 = ramfuc_reg(0x10f248); +	ram->fuc.r_0x10f290 = ramfuc_reg(0x10f290); +	ram->fuc.r_0x10f294 = ramfuc_reg(0x10f294); +	ram->fuc.r_0x10f298 = ramfuc_reg(0x10f298); +	ram->fuc.r_0x10f29c = ramfuc_reg(0x10f29c); +	ram->fuc.r_0x10f2a0 = ramfuc_reg(0x10f2a0); +	ram->fuc.r_0x10f2a4 = ramfuc_reg(0x10f2a4); +	ram->fuc.r_0x10f2a8 = ramfuc_reg(0x10f2a8); +	ram->fuc.r_0x10f2ac = ramfuc_reg(0x10f2ac); +	ram->fuc.r_0x10f2cc = ramfuc_reg(0x10f2cc); +	ram->fuc.r_0x10f2e8 = ramfuc_reg(0x10f2e8); +	ram->fuc.r_0x10f250 = ramfuc_reg(0x10f250); +	ram->fuc.r_0x10f24c = ramfuc_reg(0x10f24c); +	ram->fuc.r_0x10fec4 = ramfuc_reg(0x10fec4); +	ram->fuc.r_0x10fec8 = ramfuc_reg(0x10fec8); +	ram->fuc.r_0x10f604 = ramfuc_reg(0x10f604); +	ram->fuc.r_0x10f614 = ramfuc_reg(0x10f614); +	ram->fuc.r_0x10f610 = ramfuc_reg(0x10f610); +	ram->fuc.r_0x100770 = ramfuc_reg(0x100770); +	ram->fuc.r_0x100778 = ramfuc_reg(0x100778); +	ram->fuc.r_0x10f224 = ramfuc_reg(0x10f224); + +	ram->fuc.r_0x10f870 = ramfuc_reg(0x10f870); +	ram->fuc.r_0x10f698 = ramfuc_reg(0x10f698); +	ram->fuc.r_0x10f694 = ramfuc_reg(0x10f694); +	ram->fuc.r_0x10f6b8 = ramfuc_reg(0x10f6b8); +	ram->fuc.r_0x10f808 = ramfuc_reg(0x10f808); +	ram->fuc.r_0x10f670 = ramfuc_reg(0x10f670); +	ram->fuc.r_0x10f60c = ramfuc_reg(0x10f60c); +	ram->fuc.r_0x10f830 = ramfuc_reg(0x10f830); +	ram->fuc.r_0x1373ec = ramfuc_reg(0x1373ec); +	ram->fuc.r_0x10f800 = ramfuc_reg(0x10f800); +	ram->fuc.r_0x10f82c = ramfuc_reg(0x10f82c); + +	ram->fuc.r_0x10f978 = ramfuc_reg(0x10f978); +	ram->fuc.r_0x10f910 = ramfuc_reg(0x10f910); +	ram->fuc.r_0x10f914 = ramfuc_reg(0x10f914); + +	switch (ram->base.type) { +	case NV_MEM_TYPE_GDDR5: +		ram->fuc.r_mr[0] = ramfuc_reg(0x10f300); +		ram->fuc.r_mr[1] = ramfuc_reg(0x10f330); +		ram->fuc.r_mr[2] = ramfuc_reg(0x10f334); +		ram->fuc.r_mr[3] = ramfuc_reg(0x10f338); +		ram->fuc.r_mr[4] = ramfuc_reg(0x10f33c); +		ram->fuc.r_mr[5] = ramfuc_reg(0x10f340); +		ram->fuc.r_mr[6] = ramfuc_reg(0x10f344); +		ram->fuc.r_mr[7] = ramfuc_reg(0x10f348); +		ram->fuc.r_mr[8] = ramfuc_reg(0x10f354); +		ram->fuc.r_mr[15] = ramfuc_reg(0x10f34c); +		break; +	case NV_MEM_TYPE_DDR3: +		ram->fuc.r_mr[0] = ramfuc_reg(0x10f300); +		ram->fuc.r_mr[2] = ramfuc_reg(0x10f320); +		break; +	default: +		break; +	} + +	ram->fuc.r_0x62c000 = ramfuc_reg(0x62c000); +	ram->fuc.r_0x10f200 = ramfuc_reg(0x10f200); +	ram->fuc.r_0x10f210 = ramfuc_reg(0x10f210); +	ram->fuc.r_0x10f310 = ramfuc_reg(0x10f310); +	ram->fuc.r_0x10f314 = ramfuc_reg(0x10f314); +	ram->fuc.r_0x10f318 = ramfuc_reg(0x10f318); +	ram->fuc.r_0x10f090 = ramfuc_reg(0x10f090); +	ram->fuc.r_0x10f69c = ramfuc_reg(0x10f69c); +	ram->fuc.r_0x10f824 = ramfuc_reg(0x10f824); +	ram->fuc.r_0x1373f0 = ramfuc_reg(0x1373f0); +	ram->fuc.r_0x1373f4 = ramfuc_reg(0x1373f4); +	ram->fuc.r_0x137320 = ramfuc_reg(0x137320); +	ram->fuc.r_0x10f65c = ramfuc_reg(0x10f65c); +	ram->fuc.r_0x10f6bc = ramfuc_reg(0x10f6bc); +	ram->fuc.r_0x100710 = ramfuc_reg(0x100710); +	ram->fuc.r_0x100750 = ramfuc_reg(0x100750); +	return 0; +} + +struct nouveau_oclass +nve0_ram_oclass = { +	.handle = 0, +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nve0_ram_ctor, +		.dtor = _nouveau_ram_dtor, +		.init = nve0_ram_init, +		.fini = _nouveau_ram_fini, +	} +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramseq.h b/drivers/gpu/drm/nouveau/core/subdev/fb/ramseq.h new file mode 100644 index 00000000000..571077e3907 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramseq.h @@ -0,0 +1,18 @@ +#ifndef __NVKM_FBRAM_SEQ_H__ +#define __NVKM_FBRAM_SEQ_H__ + +#include <subdev/bus.h> +#include <subdev/bus/hwsq.h> + +#define ram_init(s,p)       hwsq_init(&(s)->base, (p)) +#define ram_exec(s,e)       hwsq_exec(&(s)->base, (e)) +#define ram_have(s,r)       ((s)->r_##r.addr != 0x000000) +#define ram_rd32(s,r)       hwsq_rd32(&(s)->base, &(s)->r_##r) +#define ram_wr32(s,r,d)     hwsq_wr32(&(s)->base, &(s)->r_##r, (d)) +#define ram_nuke(s,r)       hwsq_nuke(&(s)->base, &(s)->r_##r) +#define ram_mask(s,r,m,d)   hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d)) +#define ram_setf(s,f,d)     hwsq_setf(&(s)->base, (f), (d)) +#define ram_wait(s,f,d)     hwsq_wait(&(s)->base, (f), (d)) +#define ram_nsec(s,n)       hwsq_nsec(&(s)->base, (n)) + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/sddr3.c b/drivers/gpu/drm/nouveau/core/subdev/fb/sddr3.c new file mode 100644 index 00000000000..ebd4cd9c35d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/sddr3.c @@ -0,0 +1,99 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include <subdev/bios.h> +#include "priv.h" + +struct ramxlat { +	int id; +	u8 enc; +}; + +static inline int +ramxlat(const struct ramxlat *xlat, int id) +{ +	while (xlat->id >= 0) { +		if (xlat->id == id) +			return xlat->enc; +		xlat++; +	} +	return -EINVAL; +} + +static const struct ramxlat +ramddr3_cl[] = { +	{ 5, 2 }, { 6, 4 }, { 7, 6 }, { 8, 8 }, { 9, 10 }, { 10, 12 }, +	{ 11, 14 }, +	/* the below are mentioned in some, but not all, ddr3 docs */ +	{ 12, 1 }, { 13, 3 }, { 14, 5 }, +	{ -1 } +}; + +static const struct ramxlat +ramddr3_wr[] = { +	{ 5, 1 }, { 6, 2 }, { 7, 3 }, { 8, 4 }, { 10, 5 }, { 12, 6 }, +	/* the below are mentioned in some, but not all, ddr3 docs */ +	{ 14, 7 }, { 16, 0 }, +	{ -1 } +}; + +static const struct ramxlat +ramddr3_cwl[] = { +	{ 5, 0 }, { 6, 1 }, { 7, 2 }, { 8, 3 }, +	/* the below are mentioned in some, but not all, ddr3 docs */ +	{ 9, 4 }, +	{ -1 } +}; + +int +nouveau_sddr3_calc(struct nouveau_ram *ram) +{ +	struct nouveau_bios *bios = nouveau_bios(ram); +	int WL, CL, WR; + +	switch (!!ram->timing.data * ram->timing.version) { +	case 0x20: +		WL = (nv_ro16(bios, ram->timing.data + 0x04) & 0x0f80) >> 7; +		CL =  nv_ro08(bios, ram->timing.data + 0x04) & 0x1f; +		WR =  nv_ro08(bios, ram->timing.data + 0x0a) & 0x7f; +		break; +	default: +		return -ENOSYS; +	} + +	WL = ramxlat(ramddr3_cwl, WL); +	CL = ramxlat(ramddr3_cl, CL); +	WR = ramxlat(ramddr3_wr, WR); +	if (WL < 0 || CL < 0 || WR < 0) +		return -EINVAL; + +	ram->mr[0] &= ~0xe74; +	ram->mr[0] |= (WR & 0x07) << 9; +	ram->mr[0] |= (CL & 0x0e) << 3; +	ram->mr[0] |= (CL & 0x01) << 2; + +	ram->mr[2] &= ~0x038; +	ram->mr[2] |= (WL & 0x07) << 3; +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index d422acc9af1..45e0202f315 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -22,21 +22,24 @@   * Authors: Ben Skeggs   */ -#include <subdev/gpio.h>  #include <subdev/bios.h>  #include <subdev/bios/gpio.h> +#include "priv.h" +  static int  nouveau_gpio_drive(struct nouveau_gpio *gpio,  		   int idx, int line, int dir, int out)  { -	return gpio->drive ? gpio->drive(gpio, line, dir, out) : -ENODEV; +	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; +	return impl->drive ? impl->drive(gpio, line, dir, out) : -ENODEV;  }  static int  nouveau_gpio_sense(struct nouveau_gpio *gpio, int idx, int line)  { -	return gpio->sense ? gpio->sense(gpio, line) : -ENODEV; +	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; +	return impl->sense ? impl->sense(gpio, line) : -ENODEV;  }  static int @@ -67,7 +70,7 @@ nouveau_gpio_find(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line,  		}  	} -	return -EINVAL; +	return -ENOENT;  }  static int @@ -102,6 +105,80 @@ nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line)  	return ret;  } +static void +nouveau_gpio_intr_disable(struct nouveau_event *event, int type, int index) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(event->priv); +	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; +	impl->intr_mask(gpio, type, 1 << index, 0); +} + +static void +nouveau_gpio_intr_enable(struct nouveau_event *event, int type, int index) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(event->priv); +	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; +	impl->intr_mask(gpio, type, 1 << index, 1 << index); +} + +static void +nouveau_gpio_intr(struct nouveau_subdev *subdev) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(subdev); +	const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; +	u32 hi, lo, e, i; + +	impl->intr_stat(gpio, &hi, &lo); + +	for (i = 0; e = 0, (hi | lo) && i < impl->lines; i++) { +		if (hi & (1 << i)) +			e |= NVKM_GPIO_HI; +		if (lo & (1 << i)) +			e |= NVKM_GPIO_LO; +		nouveau_event_trigger(gpio->events, e, i); +	} +} + +int +_nouveau_gpio_fini(struct nouveau_object *object, bool suspend) +{ +	const struct nouveau_gpio_impl *impl = (void *)object->oclass; +	struct nouveau_gpio *gpio = nouveau_gpio(object); +	u32 mask = (1 << impl->lines) - 1; + +	impl->intr_mask(gpio, NVKM_GPIO_TOGGLED, mask, 0); +	impl->intr_stat(gpio, &mask, &mask); + +	return nouveau_subdev_fini(&gpio->base, suspend); +} + +static struct dmi_system_id gpio_reset_ids[] = { +	{ +		.ident = "Apple Macbook 10,1", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), +		} +	}, +	{ } +}; + +int +_nouveau_gpio_init(struct nouveau_object *object) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(object); +	int ret; + +	ret = nouveau_subdev_init(&gpio->base); +	if (ret) +		return ret; + +	if (gpio->reset && dmi_check_system(gpio_reset_ids)) +		gpio->reset(gpio, DCB_GPIO_UNUSED); + +	return ret; +} +  void  _nouveau_gpio_dtor(struct nouveau_object *object)  { @@ -113,9 +190,10 @@ _nouveau_gpio_dtor(struct nouveau_object *object)  int  nouveau_gpio_create_(struct nouveau_object *parent,  		     struct nouveau_object *engine, -		     struct nouveau_oclass *oclass, int lines, +		     struct nouveau_oclass *oclass,  		     int length, void **pobject)  { +	const struct nouveau_gpio_impl *impl = (void *)oclass;  	struct nouveau_gpio *gpio;  	int ret; @@ -125,34 +203,34 @@ nouveau_gpio_create_(struct nouveau_object *parent,  	if (ret)  		return ret; -	ret = nouveau_event_create(lines, &gpio->events); -	if (ret) -		return ret; -  	gpio->find = nouveau_gpio_find;  	gpio->set  = nouveau_gpio_set;  	gpio->get  = nouveau_gpio_get; +	gpio->reset = impl->reset; + +	ret = nouveau_event_create(2, impl->lines, &gpio->events); +	if (ret) +		return ret; + +	gpio->events->priv = gpio; +	gpio->events->enable = nouveau_gpio_intr_enable; +	gpio->events->disable = nouveau_gpio_intr_disable; +	nv_subdev(gpio)->intr = nouveau_gpio_intr;  	return 0;  } -static struct dmi_system_id gpio_reset_ids[] = { -	{ -		.ident = "Apple Macbook 10,1", -		.matches = { -			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"), -		} -	}, -	{ } -}; -  int -nouveau_gpio_init(struct nouveau_gpio *gpio) +_nouveau_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		   struct nouveau_oclass *oclass, void *data, u32 size, +		   struct nouveau_object **pobject)  { -	int ret = nouveau_subdev_init(&gpio->base); -	if (ret == 0 && gpio->reset) { -		if (dmi_check_system(gpio_reset_ids)) -			gpio->reset(gpio, DCB_GPIO_UNUSED); -	} -	return ret; +	struct nouveau_gpio *gpio; +	int ret; + +	ret = nouveau_gpio_create(parent, engine, oclass, &gpio); +	*pobject = nv_object(gpio); +	if (ret) +		return ret; + +	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c index 76d5d5465dd..27ad23eaf18 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c @@ -26,10 +26,6 @@  #include "priv.h" -struct nv10_gpio_priv { -	struct nouveau_gpio base; -}; -  static int  nv10_gpio_sense(struct nouveau_gpio *gpio, int line)  { @@ -83,95 +79,38 @@ nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)  }  static void -nv10_gpio_intr(struct nouveau_subdev *subdev) -{ -	struct nv10_gpio_priv *priv = (void *)subdev; -	u32 intr = nv_rd32(priv, 0x001104); -	u32 hi = (intr & 0x0000ffff) >> 0; -	u32 lo = (intr & 0xffff0000) >> 16; -	int i; - -	for (i = 0; (hi | lo) && i < 32; i++) { -		if ((hi | lo) & (1 << i)) -			nouveau_event_trigger(priv->base.events, i); -	} - -	nv_wr32(priv, 0x001104, intr); -} - -static void -nv10_gpio_intr_enable(struct nouveau_event *event, int line) -{ -	nv_wr32(event->priv, 0x001104, 0x00010001 << line); -	nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00010001 << line); -} - -static void -nv10_gpio_intr_disable(struct nouveau_event *event, int line) -{ -	nv_wr32(event->priv, 0x001104, 0x00010001 << line); -	nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00000000); -} - -static int -nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	       struct nouveau_oclass *oclass, void *data, u32 size, -	       struct nouveau_object **pobject) +nv10_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo)  { -	struct nv10_gpio_priv *priv; -	int ret; - -	ret = nouveau_gpio_create(parent, engine, oclass, 16, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.drive = nv10_gpio_drive; -	priv->base.sense = nv10_gpio_sense; -	priv->base.events->priv = priv; -	priv->base.events->enable = nv10_gpio_intr_enable; -	priv->base.events->disable = nv10_gpio_intr_disable; -	nv_subdev(priv)->intr = nv10_gpio_intr; -	return 0; +	u32 intr = nv_rd32(gpio, 0x001104); +	u32 stat = nv_rd32(gpio, 0x001144) & intr; +	*lo = (stat & 0xffff0000) >> 16; +	*hi = (stat & 0x0000ffff); +	nv_wr32(gpio, 0x001104, intr);  }  static void -nv10_gpio_dtor(struct nouveau_object *object) -{ -	struct nv10_gpio_priv *priv = (void *)object; -	nouveau_gpio_destroy(&priv->base); -} - -static int -nv10_gpio_init(struct nouveau_object *object) -{ -	struct nv10_gpio_priv *priv = (void *)object; -	int ret; - -	ret = nouveau_gpio_init(&priv->base); -	if (ret) -		return ret; - -	nv_wr32(priv, 0x001144, 0x00000000); -	nv_wr32(priv, 0x001104, 0xffffffff); -	return 0; -} - -static int -nv10_gpio_fini(struct nouveau_object *object, bool suspend) +nv10_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data)  { -	struct nv10_gpio_priv *priv = (void *)object; -	nv_wr32(priv, 0x001144, 0x00000000); -	return nouveau_gpio_fini(&priv->base, suspend); +	u32 inte = nv_rd32(gpio, 0x001144); +	if (type & NVKM_GPIO_LO) +		inte = (inte & ~(mask << 16)) | (data << 16); +	if (type & NVKM_GPIO_HI) +		inte = (inte & ~mask) | data; +	nv_wr32(gpio, 0x001144, inte);  } -struct nouveau_oclass -nv10_gpio_oclass = { -	.handle = NV_SUBDEV(GPIO, 0x10), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv10_gpio_ctor, -		.dtor = nv10_gpio_dtor, -		.init = nv10_gpio_init, -		.fini = nv10_gpio_fini, +struct nouveau_oclass * +nv10_gpio_oclass = &(struct nouveau_gpio_impl) { +	.base.handle = NV_SUBDEV(GPIO, 0x10), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_gpio_ctor, +		.dtor = _nouveau_gpio_dtor, +		.init = _nouveau_gpio_init, +		.fini = _nouveau_gpio_fini,  	}, -}; +	.lines = 16, +	.intr_stat = nv10_gpio_intr_stat, +	.intr_mask = nv10_gpio_intr_mask, +	.drive = nv10_gpio_drive, +	.sense = nv10_gpio_sense, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index c4c1d415e7f..1864fa98e6b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c @@ -24,15 +24,10 @@  #include "priv.h" -struct nv50_gpio_priv { -	struct nouveau_gpio base; -}; - -static void +void  nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)  {  	struct nouveau_bios *bios = nouveau_bios(gpio); -	struct nv50_gpio_priv *priv = (void *)gpio;  	u8 ver, len;  	u16 entry;  	int ent = -1; @@ -46,7 +41,8 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)  		u8  unk0 = !!(data & 0x02000000);  		u8  unk1 = !!(data & 0x04000000);  		u32 val = (unk1 << 16) | unk0; -		u32 reg = regs[line >> 4]; line &= 0x0f; +		u32 reg = regs[line >> 4]; +		u32 lsh = line & 0x0f;  		if ( func  == DCB_GPIO_UNUSED ||  		    (match != DCB_GPIO_UNUSED && match != func)) @@ -54,7 +50,7 @@ nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match)  		gpio->set(gpio, 0, func, line, defs); -		nv_mask(priv, reg, 0x00010001 << line, val << line); +		nv_mask(gpio, reg, 0x00010001 << lsh, val << lsh);  	}  } @@ -71,7 +67,7 @@ nv50_gpio_location(int line, u32 *reg, u32 *shift)  	return 0;  } -static int +int  nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)  {  	u32 reg, shift; @@ -79,11 +75,11 @@ nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)  	if (nv50_gpio_location(line, ®, &shift))  		return -EINVAL; -	nv_mask(gpio, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); +	nv_mask(gpio, reg, 3 << shift, (((dir ^ 1) << 1) | out) << shift);  	return 0;  } -static int +int  nv50_gpio_sense(struct nouveau_gpio *gpio, int line)  {  	u32 reg, shift; @@ -94,119 +90,40 @@ nv50_gpio_sense(struct nouveau_gpio *gpio, int line)  	return !!(nv_rd32(gpio, reg) & (4 << shift));  } -void -nv50_gpio_intr(struct nouveau_subdev *subdev) -{ -	struct nv50_gpio_priv *priv = (void *)subdev; -	u32 intr0, intr1 = 0; -	u32 hi, lo; -	int i; - -	intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); -	if (nv_device(priv)->chipset > 0x92) -		intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); - -	hi = (intr0 & 0x0000ffff) | (intr1 << 16); -	lo = (intr0 >> 16) | (intr1 & 0xffff0000); - -	for (i = 0; (hi | lo) && i < 32; i++) { -		if ((hi | lo) & (1 << i)) -			nouveau_event_trigger(priv->base.events, i); -	} - -	nv_wr32(priv, 0xe054, intr0); -	if (nv_device(priv)->chipset > 0x92) -		nv_wr32(priv, 0xe074, intr1); -} - -void -nv50_gpio_intr_enable(struct nouveau_event *event, int line) -{ -	const u32 addr = line < 16 ? 0xe050 : 0xe070; -	const u32 mask = 0x00010001 << (line & 0xf); -	nv_wr32(event->priv, addr + 0x04, mask); -	nv_mask(event->priv, addr + 0x00, mask, mask); -} - -void -nv50_gpio_intr_disable(struct nouveau_event *event, int line) -{ -	const u32 addr = line < 16 ? 0xe050 : 0xe070; -	const u32 mask = 0x00010001 << (line & 0xf); -	nv_wr32(event->priv, addr + 0x04, mask); -	nv_mask(event->priv, addr + 0x00, mask, 0x00000000); -} - -static int -nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	       struct nouveau_oclass *oclass, void *data, u32 size, -	       struct nouveau_object **pobject) -{ -	struct nv50_gpio_priv *priv; -	int ret; - -	ret = nouveau_gpio_create(parent, engine, oclass, -				  nv_device(parent)->chipset > 0x92 ? 32 : 16, -				  &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.reset = nv50_gpio_reset; -	priv->base.drive = nv50_gpio_drive; -	priv->base.sense = nv50_gpio_sense; -	priv->base.events->priv = priv; -	priv->base.events->enable = nv50_gpio_intr_enable; -	priv->base.events->disable = nv50_gpio_intr_disable; -	nv_subdev(priv)->intr = nv50_gpio_intr; -	return 0; -} - -void -nv50_gpio_dtor(struct nouveau_object *object) -{ -	struct nv50_gpio_priv *priv = (void *)object; -	nouveau_gpio_destroy(&priv->base); -} - -int -nv50_gpio_init(struct nouveau_object *object) +static void +nv50_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo)  { -	struct nv50_gpio_priv *priv = (void *)object; -	int ret; - -	ret = nouveau_gpio_init(&priv->base); -	if (ret) -		return ret; - -	/* disable, and ack any pending gpio interrupts */ -	nv_wr32(priv, 0xe050, 0x00000000); -	nv_wr32(priv, 0xe054, 0xffffffff); -	if (nv_device(priv)->chipset > 0x92) { -		nv_wr32(priv, 0xe070, 0x00000000); -		nv_wr32(priv, 0xe074, 0xffffffff); -	} - -	return 0; +	u32 intr = nv_rd32(gpio, 0x00e054); +	u32 stat = nv_rd32(gpio, 0x00e050) & intr; +	*lo = (stat & 0xffff0000) >> 16; +	*hi = (stat & 0x0000ffff); +	nv_wr32(gpio, 0x00e054, intr);  } -int -nv50_gpio_fini(struct nouveau_object *object, bool suspend) +static void +nv50_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data)  { -	struct nv50_gpio_priv *priv = (void *)object; -	nv_wr32(priv, 0xe050, 0x00000000); -	if (nv_device(priv)->chipset > 0x92) -		nv_wr32(priv, 0xe070, 0x00000000); -	return nouveau_gpio_fini(&priv->base, suspend); +	u32 inte = nv_rd32(gpio, 0x00e050); +	if (type & NVKM_GPIO_LO) +		inte = (inte & ~(mask << 16)) | (data << 16); +	if (type & NVKM_GPIO_HI) +		inte = (inte & ~mask) | data; +	nv_wr32(gpio, 0x00e050, inte);  } -struct nouveau_oclass -nv50_gpio_oclass = { -	.handle = NV_SUBDEV(GPIO, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv50_gpio_ctor, -		.dtor = nv50_gpio_dtor, -		.init = nv50_gpio_init, -		.fini = nv50_gpio_fini, +struct nouveau_oclass * +nv50_gpio_oclass = &(struct nouveau_gpio_impl) { +	.base.handle = NV_SUBDEV(GPIO, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_gpio_ctor, +		.dtor = _nouveau_gpio_dtor, +		.init = _nouveau_gpio_init, +		.fini = _nouveau_gpio_fini,  	}, -}; +	.lines = 16, +	.intr_stat = nv50_gpio_intr_stat, +	.intr_mask = nv50_gpio_intr_mask, +	.drive = nv50_gpio_drive, +	.sense = nv50_gpio_sense, +	.reset = nv50_gpio_reset, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv92.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv92.c new file mode 100644 index 00000000000..252083d376f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv92.c @@ -0,0 +1,74 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "priv.h" + +void +nv92_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo) +{ +	u32 intr0 = nv_rd32(gpio, 0x00e054); +	u32 intr1 = nv_rd32(gpio, 0x00e074); +	u32 stat0 = nv_rd32(gpio, 0x00e050) & intr0; +	u32 stat1 = nv_rd32(gpio, 0x00e070) & intr1; +	*lo = (stat1 & 0xffff0000) | (stat0 >> 16); +	*hi = (stat1 << 16) | (stat0 & 0x0000ffff); +	nv_wr32(gpio, 0x00e054, intr0); +	nv_wr32(gpio, 0x00e074, intr1); +} + +void +nv92_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data) +{ +	u32 inte0 = nv_rd32(gpio, 0x00e050); +	u32 inte1 = nv_rd32(gpio, 0x00e070); +	if (type & NVKM_GPIO_LO) +		inte0 = (inte0 & ~(mask << 16)) | (data << 16); +	if (type & NVKM_GPIO_HI) +		inte0 = (inte0 & ~(mask & 0xffff)) | (data & 0xffff); +	mask >>= 16; +	data >>= 16; +	if (type & NVKM_GPIO_LO) +		inte1 = (inte1 & ~(mask << 16)) | (data << 16); +	if (type & NVKM_GPIO_HI) +		inte1 = (inte1 & ~mask) | data; +	nv_wr32(gpio, 0x00e050, inte0); +	nv_wr32(gpio, 0x00e070, inte1); +} + +struct nouveau_oclass * +nv92_gpio_oclass = &(struct nouveau_gpio_impl) { +	.base.handle = NV_SUBDEV(GPIO, 0x92), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_gpio_ctor, +		.dtor = _nouveau_gpio_dtor, +		.init = _nouveau_gpio_init, +		.fini = _nouveau_gpio_fini, +	}, +	.lines = 32, +	.intr_stat = nv92_gpio_intr_stat, +	.intr_mask = nv92_gpio_intr_mask, +	.drive = nv50_gpio_drive, +	.sense = nv50_gpio_sense, +	.reset = nv50_gpio_reset, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index 010431e3ace..a4682b0956a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c @@ -24,15 +24,10 @@  #include "priv.h" -struct nvd0_gpio_priv { -	struct nouveau_gpio base; -}; -  void  nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)  {  	struct nouveau_bios *bios = nouveau_bios(gpio); -	struct nvd0_gpio_priv *priv = (void *)gpio;  	u8 ver, len;  	u16 entry;  	int ent = -1; @@ -51,9 +46,9 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match)  		gpio->set(gpio, 0, func, line, defs); -		nv_mask(priv, 0x00d610 + (line * 4), 0xff, unk0); +		nv_mask(gpio, 0x00d610 + (line * 4), 0xff, unk0);  		if (unk1--) -			nv_mask(priv, 0x00d740 + (unk1 * 4), 0xff, line); +			nv_mask(gpio, 0x00d740 + (unk1 * 4), 0xff, line);  	}  } @@ -72,36 +67,19 @@ nvd0_gpio_sense(struct nouveau_gpio *gpio, int line)  	return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000);  } -static int -nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	       struct nouveau_oclass *oclass, void *data, u32 size, -	       struct nouveau_object **pobject) -{ -	struct nvd0_gpio_priv *priv; -	int ret; - -	ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.reset = nvd0_gpio_reset; -	priv->base.drive = nvd0_gpio_drive; -	priv->base.sense = nvd0_gpio_sense; -	priv->base.events->priv = priv; -	priv->base.events->enable = nv50_gpio_intr_enable; -	priv->base.events->disable = nv50_gpio_intr_disable; -	nv_subdev(priv)->intr = nv50_gpio_intr; -	return 0; -} - -struct nouveau_oclass -nvd0_gpio_oclass = { -	.handle = NV_SUBDEV(GPIO, 0xd0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvd0_gpio_ctor, -		.dtor = nv50_gpio_dtor, -		.init = nv50_gpio_init, -		.fini = nv50_gpio_fini, +struct nouveau_oclass * +nvd0_gpio_oclass = &(struct nouveau_gpio_impl) { +	.base.handle = NV_SUBDEV(GPIO, 0xd0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_gpio_ctor, +		.dtor = _nouveau_gpio_dtor, +		.init = _nouveau_gpio_init, +		.fini = _nouveau_gpio_fini,  	}, -}; +	.lines = 32, +	.intr_stat = nv92_gpio_intr_stat, +	.intr_mask = nv92_gpio_intr_mask, +	.drive = nvd0_gpio_drive, +	.sense = nvd0_gpio_sense, +	.reset = nvd0_gpio_reset, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c index 16b8c5bf5ef..e1145b48c76 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c @@ -24,108 +24,51 @@  #include "priv.h" -struct nve0_gpio_priv { -	struct nouveau_gpio base; -}; - -void -nve0_gpio_intr(struct nouveau_subdev *subdev) +static void +nve0_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo)  { -	struct nve0_gpio_priv *priv = (void *)subdev; -	u32 intr0 = nv_rd32(priv, 0xdc00) & nv_rd32(priv, 0xdc08); -	u32 intr1 = nv_rd32(priv, 0xdc80) & nv_rd32(priv, 0xdc88); -	u32 hi = (intr0 & 0x0000ffff) | (intr1 << 16); -	u32 lo = (intr0 >> 16) | (intr1 & 0xffff0000); -	int i; - -	for (i = 0; (hi | lo) && i < 32; i++) { -		if ((hi | lo) & (1 << i)) -			nouveau_event_trigger(priv->base.events, i); -	} - -	nv_wr32(priv, 0xdc00, intr0); -	nv_wr32(priv, 0xdc88, intr1); +	u32 intr0 = nv_rd32(gpio, 0x00dc00); +	u32 intr1 = nv_rd32(gpio, 0x00dc80); +	u32 stat0 = nv_rd32(gpio, 0x00dc08) & intr0; +	u32 stat1 = nv_rd32(gpio, 0x00dc88) & intr1; +	*lo = (stat1 & 0xffff0000) | (stat0 >> 16); +	*hi = (stat1 << 16) | (stat0 & 0x0000ffff); +	nv_wr32(gpio, 0x00dc00, intr0); +	nv_wr32(gpio, 0x00dc80, intr1);  }  void -nve0_gpio_intr_enable(struct nouveau_event *event, int line) +nve0_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data)  { -	const u32 addr = line < 16 ? 0xdc00 : 0xdc80; -	const u32 mask = 0x00010001 << (line & 0xf); -	nv_wr32(event->priv, addr + 0x08, mask); -	nv_mask(event->priv, addr + 0x00, mask, mask); -} - -void -nve0_gpio_intr_disable(struct nouveau_event *event, int line) -{ -	const u32 addr = line < 16 ? 0xdc00 : 0xdc80; -	const u32 mask = 0x00010001 << (line & 0xf); -	nv_wr32(event->priv, addr + 0x08, mask); -	nv_mask(event->priv, addr + 0x00, mask, 0x00000000); -} - -int -nve0_gpio_fini(struct nouveau_object *object, bool suspend) -{ -	struct nve0_gpio_priv *priv = (void *)object; -	nv_wr32(priv, 0xdc08, 0x00000000); -	nv_wr32(priv, 0xdc88, 0x00000000); -	return nouveau_gpio_fini(&priv->base, suspend); -} - -int -nve0_gpio_init(struct nouveau_object *object) -{ -	struct nve0_gpio_priv *priv = (void *)object; -	int ret; - -	ret = nouveau_gpio_init(&priv->base); -	if (ret) -		return ret; - -	nv_wr32(priv, 0xdc00, 0xffffffff); -	nv_wr32(priv, 0xdc80, 0xffffffff); -	return 0; -} - -void -nve0_gpio_dtor(struct nouveau_object *object) -{ -	struct nve0_gpio_priv *priv = (void *)object; -	nouveau_gpio_destroy(&priv->base); -} - -static int -nve0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	       struct nouveau_oclass *oclass, void *data, u32 size, -	       struct nouveau_object **pobject) -{ -	struct nve0_gpio_priv *priv; -	int ret; - -	ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.reset = nvd0_gpio_reset; -	priv->base.drive = nvd0_gpio_drive; -	priv->base.sense = nvd0_gpio_sense; -	priv->base.events->priv = priv; -	priv->base.events->enable = nve0_gpio_intr_enable; -	priv->base.events->disable = nve0_gpio_intr_disable; -	nv_subdev(priv)->intr = nve0_gpio_intr; -	return 0; +	u32 inte0 = nv_rd32(gpio, 0x00dc08); +	u32 inte1 = nv_rd32(gpio, 0x00dc88); +	if (type & NVKM_GPIO_LO) +		inte0 = (inte0 & ~(mask << 16)) | (data << 16); +	if (type & NVKM_GPIO_HI) +		inte0 = (inte0 & ~(mask & 0xffff)) | (data & 0xffff); +	mask >>= 16; +	data >>= 16; +	if (type & NVKM_GPIO_LO) +		inte1 = (inte1 & ~(mask << 16)) | (data << 16); +	if (type & NVKM_GPIO_HI) +		inte1 = (inte1 & ~mask) | data; +	nv_wr32(gpio, 0x00dc08, inte0); +	nv_wr32(gpio, 0x00dc88, inte1);  } -struct nouveau_oclass -nve0_gpio_oclass = { -	.handle = NV_SUBDEV(GPIO, 0xe0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nve0_gpio_ctor, -		.dtor = nv50_gpio_dtor, -		.init = nve0_gpio_init, -		.fini = nve0_gpio_fini, +struct nouveau_oclass * +nve0_gpio_oclass = &(struct nouveau_gpio_impl) { +	.base.handle = NV_SUBDEV(GPIO, 0xe0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_gpio_ctor, +		.dtor = _nouveau_gpio_dtor, +		.init = _nouveau_gpio_init, +		.fini = _nouveau_gpio_fini,  	}, -}; +	.lines = 32, +	.intr_stat = nve0_gpio_intr_stat, +	.intr_mask = nve0_gpio_intr_mask, +	.drive = nvd0_gpio_drive, +	.sense = nvd0_gpio_sense, +	.reset = nvd0_gpio_reset, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h b/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h index 2ee1c895c78..e1724dfc86a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h @@ -3,15 +3,65 @@  #include <subdev/gpio.h> -void nv50_gpio_dtor(struct nouveau_object *); -int  nv50_gpio_init(struct nouveau_object *); -int  nv50_gpio_fini(struct nouveau_object *, bool); -void nv50_gpio_intr(struct nouveau_subdev *); -void nv50_gpio_intr_enable(struct nouveau_event *, int line); -void nv50_gpio_intr_disable(struct nouveau_event *, int line); +#define nouveau_gpio_create(p,e,o,d)                                           \ +	nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_gpio_destroy(p) ({                                             \ +	struct nouveau_gpio *gpio = (p);                                       \ +	_nouveau_gpio_dtor(nv_object(gpio));                                   \ +}) +#define nouveau_gpio_init(p) ({                                                \ +	struct nouveau_gpio *gpio = (p);                                       \ +	_nouveau_gpio_init(nv_object(gpio));                                   \ +}) +#define nouveau_gpio_fini(p,s) ({                                              \ +	struct nouveau_gpio *gpio = (p);                                       \ +	_nouveau_gpio_fini(nv_object(gpio), (s));                              \ +}) + +int  nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, +			  struct nouveau_oclass *, int, void **); +int  _nouveau_gpio_ctor(struct nouveau_object *, struct nouveau_object *, +			struct nouveau_oclass *, void *, u32, +			struct nouveau_object **); +void _nouveau_gpio_dtor(struct nouveau_object *); +int  _nouveau_gpio_init(struct nouveau_object *); +int  _nouveau_gpio_fini(struct nouveau_object *, bool); + +struct nouveau_gpio_impl { +	struct nouveau_oclass base; +	int lines; + +	/* read and ack pending interrupts, returning only data +	 * for lines that have not been masked off, while still +	 * performing the ack for anything that was pending. +	 */ +	void (*intr_stat)(struct nouveau_gpio *, u32 *, u32 *); + +	/* mask on/off interrupts for hi/lo transitions on a +	 * given set of gpio lines +	 */ +	void (*intr_mask)(struct nouveau_gpio *, u32, u32, u32); + +	/* configure gpio direction and output value */ +	int  (*drive)(struct nouveau_gpio *, int line, int dir, int out); + +	/* sense current state of given gpio line */ +	int  (*sense)(struct nouveau_gpio *, int line); + +	/*XXX*/ +	void (*reset)(struct nouveau_gpio *, u8); +}; + +void nv50_gpio_reset(struct nouveau_gpio *, u8); +int  nv50_gpio_drive(struct nouveau_gpio *, int, int, int); +int  nv50_gpio_sense(struct nouveau_gpio *, int); + +void nv92_gpio_intr_stat(struct nouveau_gpio *, u32 *, u32 *); +void nv92_gpio_intr_mask(struct nouveau_gpio *, u32, u32, u32);  void nvd0_gpio_reset(struct nouveau_gpio *, u8);  int  nvd0_gpio_drive(struct nouveau_gpio *, int, int, int);  int  nvd0_gpio_sense(struct nouveau_gpio *, int); +  #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c index 4b195ac4da6..2c2731a6cf9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c @@ -22,7 +22,7 @@   * Authors: Ben Skeggs <bskeggs@redhat.com>   */ -#include <subdev/i2c.h> +#include "port.h"  struct anx9805_i2c_port {  	struct nouveau_i2c_port base; @@ -37,6 +37,8 @@ anx9805_train(struct nouveau_i2c_port *port, int link_nr, int link_bw, bool enh)  	struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent;  	u8 tmp, i; +	DBG("ANX9805 train %d 0x%02x %d\n", link_nr, link_bw, enh); +  	nv_wri2cr(mast, chan->addr, 0xa0, link_bw);  	nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00));  	nv_wri2cr(mast, chan->addr, 0xa2, 0x01); @@ -60,21 +62,29 @@ anx9805_train(struct nouveau_i2c_port *port, int link_nr, int link_bw, bool enh)  }  static int -anx9805_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size) +anx9805_aux(struct nouveau_i2c_port *port, bool retry, +	    u8 type, u32 addr, u8 *data, u8 size)  {  	struct anx9805_i2c_port *chan = (void *)port;  	struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent;  	int i, ret = -ETIMEDOUT; +	u8 buf[16] = {};  	u8 tmp; +	DBG("%02x %05x %d\n", type, addr, size); +  	tmp = nv_rdi2cr(mast, chan->ctrl, 0x07) & ~0x04;  	nv_wri2cr(mast, chan->ctrl, 0x07, tmp | 0x04);  	nv_wri2cr(mast, chan->ctrl, 0x07, tmp);  	nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01);  	nv_wri2cr(mast, chan->addr, 0xe4, 0x80); -	for (i = 0; !(type & 1) && i < size; i++) -		nv_wri2cr(mast, chan->addr, 0xf0 + i, data[i]); +	if (!(type & 1)) { +		memcpy(buf, data, size); +		DBG("%16ph", buf); +		for (i = 0; i < size; i++) +			nv_wri2cr(mast, chan->addr, 0xf0 + i, buf[i]); +	}  	nv_wri2cr(mast, chan->addr, 0xe5, ((size - 1) << 4) | type);  	nv_wri2cr(mast, chan->addr, 0xe6, (addr & 0x000ff) >>  0);  	nv_wri2cr(mast, chan->addr, 0xe7, (addr & 0x0ff00) >>  8); @@ -93,8 +103,13 @@ anx9805_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size)  		goto done;  	} -	for (i = 0; (type & 1) && i < size; i++) -		data[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); +	if (type & 1) { +		for (i = 0; i < size; i++) +			buf[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); +		DBG("%16ph", buf); +		memcpy(data, buf, size); +	} +  	ret = 0;  done:  	nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c index 5de074ad170..02eb42be2e9 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c @@ -22,15 +22,19 @@   * Authors: Ben Skeggs   */ -#include <subdev/i2c.h> +#include "priv.h"  int  nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)  { +	struct nouveau_i2c *i2c = nouveau_i2c(port);  	if (port->func->aux) { -		if (port->func->acquire) -			port->func->acquire(port); -		return port->func->aux(port, 9, addr, data, size); +		int ret = i2c->acquire(port, 0); +		if (ret == 0) { +			ret = port->func->aux(port, true, 9, addr, data, size); +			i2c->release(port); +		} +		return ret;  	}  	return -ENODEV;  } @@ -38,10 +42,14 @@ nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)  int  nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size)  { +	struct nouveau_i2c *i2c = nouveau_i2c(port);  	if (port->func->aux) { -		if (port->func->acquire) -			port->func->acquire(port); -		return port->func->aux(port, 8, addr, data, size); +		int ret = i2c->acquire(port, 0); +		if (ret == 0) { +			ret = port->func->aux(port, true, 8, addr, data, size); +			i2c->release(port); +		} +		return ret;  	}  	return -ENODEV;  } @@ -50,13 +58,16 @@ static int  aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  {  	struct nouveau_i2c_port *port = adap->algo_data; +	struct nouveau_i2c *i2c = nouveau_i2c(port);  	struct i2c_msg *msg = msgs;  	int ret, mcnt = num;  	if (!port->func->aux)  		return -ENODEV; -	if ( port->func->acquire) -		port->func->acquire(port); + +	ret = i2c->acquire(port, 0); +	if (ret) +		return ret;  	while (mcnt--) {  		u8 remaining = msg->len; @@ -74,9 +85,11 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  			if (mcnt || remaining > 16)  				cmd |= 4; /* MOT */ -			ret = port->func->aux(port, cmd, msg->addr, ptr, cnt); -			if (ret < 0) +			ret = port->func->aux(port, true, cmd, msg->addr, ptr, cnt); +			if (ret < 0) { +				i2c->release(port);  				return ret; +			}  			ptr += cnt;  			remaining -= cnt; @@ -85,6 +98,7 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		msg++;  	} +	i2c->release(port);  	return num;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 2895c19bb15..09ba2cc851c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -23,13 +23,16 @@   */  #include <core/option.h> +#include <core/event.h>  #include <subdev/bios.h>  #include <subdev/bios/dcb.h>  #include <subdev/bios/i2c.h> -#include <subdev/i2c.h>  #include <subdev/vga.h> +#include "priv.h" +#include "pad.h" +  /******************************************************************************   * interface to linux i2c bit-banging algorithm   *****************************************************************************/ @@ -45,9 +48,15 @@ nouveau_i2c_pre_xfer(struct i2c_adapter *adap)  {  	struct i2c_algo_bit_data *bit = adap->algo_data;  	struct nouveau_i2c_port *port = bit->data; -	if (port->func->acquire) -		port->func->acquire(port); -	return 0; +	return nouveau_i2c(port)->acquire(port, bit->timeout); +} + +static void +nouveau_i2c_post_xfer(struct i2c_adapter *adap) +{ +	struct i2c_algo_bit_data *bit = adap->algo_data; +	struct nouveau_i2c_port *port = bit->data; +	return nouveau_i2c(port)->release(port);  }  static void @@ -82,6 +91,15 @@ nouveau_i2c_getsda(void *data)   * base i2c "port" class implementation   *****************************************************************************/ +int +_nouveau_i2c_port_fini(struct nouveau_object *object, bool suspend) +{ +	struct nouveau_i2c_port *port = (void *)object; +	struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); +	nv_ofuncs(pad)->fini(nv_object(pad), suspend); +	return nouveau_object_fini(&port->base, suspend); +} +  void  _nouveau_i2c_port_dtor(struct nouveau_object *object)  { @@ -98,7 +116,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,  			 const struct nouveau_i2c_func *func,  			 int size, void **pobject)  { -	struct nouveau_device *device = nv_device(parent); +	struct nouveau_device *device = nv_device(engine);  	struct nouveau_i2c *i2c = (void *)engine;  	struct nouveau_i2c_port *port;  	int ret; @@ -111,10 +129,11 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,  	snprintf(port->adapter.name, sizeof(port->adapter.name),  		 "nouveau-%s-%d", device->name, index);  	port->adapter.owner = THIS_MODULE; -	port->adapter.dev.parent = &device->pdev->dev; +	port->adapter.dev.parent = nv_device_base(device);  	port->index = index; +	port->aux = -1;  	port->func = func; -	i2c_set_adapdata(&port->adapter, i2c); +	mutex_init(&port->mutex);  	if ( algo == &nouveau_i2c_bit_algo &&  	    !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) { @@ -128,6 +147,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,  		bit->timeout = usecs_to_jiffies(2200);  		bit->data = port;  		bit->pre_xfer = nouveau_i2c_pre_xfer; +		bit->post_xfer = nouveau_i2c_post_xfer;  		bit->setsda = nouveau_i2c_setsda;  		bit->setscl = nouveau_i2c_setscl;  		bit->getsda = nouveau_i2c_getsda; @@ -141,7 +161,6 @@ nouveau_i2c_port_create_(struct nouveau_object *parent,  		ret = i2c_add_adapter(&port->adapter);  	} -	/* drop port's i2c subdev refcount, i2c handles this itself */  	if (ret == 0)  		list_add_tail(&port->head, &i2c->ports);  	return ret; @@ -193,11 +212,80 @@ nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type)  	return NULL;  } +static void +nouveau_i2c_release_pad(struct nouveau_i2c_port *port) +{ +	struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); +	struct nouveau_i2c *i2c = nouveau_i2c(port); + +	if (atomic_dec_and_test(&nv_object(pad)->usecount)) { +		nv_ofuncs(pad)->fini(nv_object(pad), false); +		wake_up_all(&i2c->wait); +	} +} + +static int +nouveau_i2c_try_acquire_pad(struct nouveau_i2c_port *port) +{ +	struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); + +	if (atomic_add_return(1, &nv_object(pad)->usecount) != 1) { +		struct nouveau_object *owner = (void *)pad->port; +		do { +			if (owner == (void *)port) +				return 0; +			owner = owner->parent; +		} while(owner); +		nouveau_i2c_release_pad(port); +		return -EBUSY; +	} + +	pad->next = port; +	nv_ofuncs(pad)->init(nv_object(pad)); +	return 0; +} + +static int +nouveau_i2c_acquire_pad(struct nouveau_i2c_port *port, unsigned long timeout) +{ +	struct nouveau_i2c *i2c = nouveau_i2c(port); + +	if (timeout) { +		if (wait_event_timeout(i2c->wait, +				       nouveau_i2c_try_acquire_pad(port) == 0, +				       timeout) == 0) +			return -EBUSY; +	} else { +		wait_event(i2c->wait, nouveau_i2c_try_acquire_pad(port) == 0); +	} + +	return 0; +} + +static void +nouveau_i2c_release(struct nouveau_i2c_port *port) +__releases(pad->mutex) +{ +	nouveau_i2c(port)->release_pad(port); +	mutex_unlock(&port->mutex); +} + +static int +nouveau_i2c_acquire(struct nouveau_i2c_port *port, unsigned long timeout) +__acquires(pad->mutex) +{ +	int ret; +	mutex_lock(&port->mutex); +	if ((ret = nouveau_i2c(port)->acquire_pad(port, timeout))) +		mutex_unlock(&port->mutex); +	return ret; +} +  static int  nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, -		     struct i2c_board_info *info, +		     struct nouveau_i2c_board_info *info,  		     bool (*match)(struct nouveau_i2c_port *, -				   struct i2c_board_info *)) +				   struct i2c_board_info *, void *), void *data)  {  	struct nouveau_i2c_port *port = nouveau_i2c_find(i2c, index);  	int i; @@ -208,23 +296,88 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what,  	}  	nv_debug(i2c, "probing %ss on bus: %d\n", what, port->index); -	for (i = 0; info[i].addr; i++) { -		if (nv_probe_i2c(port, info[i].addr) && -		    (!match || match(port, &info[i]))) { -			nv_info(i2c, "detected %s: %s\n", what, info[i].type); +	for (i = 0; info[i].dev.addr; i++) { +		u8 orig_udelay = 0; + +		if ((port->adapter.algo == &i2c_bit_algo) && +		    (info[i].udelay != 0)) { +			struct i2c_algo_bit_data *algo = port->adapter.algo_data; +			nv_debug(i2c, "using custom udelay %d instead of %d\n", +			         info[i].udelay, algo->udelay); +			orig_udelay = algo->udelay; +			algo->udelay = info[i].udelay; +		} + +		if (nv_probe_i2c(port, info[i].dev.addr) && +		    (!match || match(port, &info[i].dev, data))) { +			nv_info(i2c, "detected %s: %s\n", what, +				info[i].dev.type);  			return i;  		} + +		if (orig_udelay) { +			struct i2c_algo_bit_data *algo = port->adapter.algo_data; +			algo->udelay = orig_udelay; +		}  	}  	nv_debug(i2c, "no devices found.\n");  	return -ENODEV;  } +static void +nouveau_i2c_intr_disable(struct nouveau_event *event, int type, int index) +{ +	struct nouveau_i2c *i2c = nouveau_i2c(event->priv); +	struct nouveau_i2c_port *port = i2c->find(i2c, index); +	const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass; +	if (port && port->aux >= 0) +		impl->aux_mask(i2c, type, 1 << port->aux, 0); +} + +static void +nouveau_i2c_intr_enable(struct nouveau_event *event, int type, int index) +{ +	struct nouveau_i2c *i2c = nouveau_i2c(event->priv); +	struct nouveau_i2c_port *port = i2c->find(i2c, index); +	const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass; +	if (port && port->aux >= 0) +		impl->aux_mask(i2c, type, 1 << port->aux, 1 << port->aux); +} + +static void +nouveau_i2c_intr(struct nouveau_subdev *subdev) +{ +	struct nouveau_i2c_impl *impl = (void *)nv_oclass(subdev); +	struct nouveau_i2c *i2c = nouveau_i2c(subdev); +	struct nouveau_i2c_port *port; +	u32 hi, lo, rq, tx, e; + +	if (impl->aux_stat) { +		impl->aux_stat(i2c, &hi, &lo, &rq, &tx); +		if (hi || lo || rq || tx) { +			list_for_each_entry(port, &i2c->ports, head) { +				if (e = 0, port->aux < 0) +					continue; + +				if (hi & (1 << port->aux)) e |= NVKM_I2C_PLUG; +				if (lo & (1 << port->aux)) e |= NVKM_I2C_UNPLUG; +				if (rq & (1 << port->aux)) e |= NVKM_I2C_IRQ; +				if (tx & (1 << port->aux)) e |= NVKM_I2C_DONE; + +				nouveau_event_trigger(i2c->ntfy, e, port->index); +			} +		} +	} +} +  int  _nouveau_i2c_fini(struct nouveau_object *object, bool suspend)  { +	struct nouveau_i2c_impl *impl = (void *)nv_oclass(object);  	struct nouveau_i2c *i2c = (void *)object;  	struct nouveau_i2c_port *port; +	u32 mask;  	int ret;  	list_for_each_entry(port, &i2c->ports, head) { @@ -233,6 +386,11 @@ _nouveau_i2c_fini(struct nouveau_object *object, bool suspend)  			goto fail;  	} +	if ((mask = (1 << impl->aux) - 1), impl->aux_stat) { +		impl->aux_mask(i2c, NVKM_I2C_ANY, mask, 0); +		impl->aux_stat(i2c, &mask, &mask, &mask, &mask); +	} +  	return nouveau_subdev_fini(&i2c->base, suspend);  fail:  	list_for_each_entry_continue_reverse(port, &i2c->ports, head) { @@ -273,6 +431,8 @@ _nouveau_i2c_dtor(struct nouveau_object *object)  	struct nouveau_i2c *i2c = (void *)object;  	struct nouveau_i2c_port *port, *temp; +	nouveau_event_destroy(&i2c->ntfy); +  	list_for_each_entry_safe(port, temp, &i2c->ports, head) {  		nouveau_object_ref(NULL, (struct nouveau_object **)&port);  	} @@ -289,14 +449,14 @@ int  nouveau_i2c_create_(struct nouveau_object *parent,  		    struct nouveau_object *engine,  		    struct nouveau_oclass *oclass, -		    struct nouveau_oclass *sclass,  		    int length, void **pobject)  { +	const struct nouveau_i2c_impl *impl = (void *)oclass;  	struct nouveau_bios *bios = nouveau_bios(parent);  	struct nouveau_i2c *i2c;  	struct nouveau_object *object;  	struct dcb_i2c_entry info; -	int ret, i, j, index = -1; +	int ret, i, j, index = -1, pad;  	struct dcb_output outp;  	u8  ver, hdr;  	u32 data; @@ -307,24 +467,48 @@ nouveau_i2c_create_(struct nouveau_object *parent,  	if (ret)  		return ret; +	nv_subdev(i2c)->intr = nouveau_i2c_intr;  	i2c->find = nouveau_i2c_find;  	i2c->find_type = nouveau_i2c_find_type; +	i2c->acquire_pad = nouveau_i2c_acquire_pad; +	i2c->release_pad = nouveau_i2c_release_pad; +	i2c->acquire = nouveau_i2c_acquire; +	i2c->release = nouveau_i2c_release;  	i2c->identify = nouveau_i2c_identify; +	init_waitqueue_head(&i2c->wait);  	INIT_LIST_HEAD(&i2c->ports);  	while (!dcb_i2c_parse(bios, ++index, &info)) {  		if (info.type == DCB_I2C_UNUSED)  			continue; -		oclass = sclass; +		if (info.share != DCB_I2C_UNUSED) { +			if (info.type == DCB_I2C_NVIO_AUX) +				pad = info.drive; +			else +				pad = info.share; +			oclass = impl->pad_s; +		} else { +			pad = 0x100 + info.drive; +			oclass = impl->pad_x; +		} + +		ret = nouveau_object_ctor(NULL, *pobject, oclass, +					  NULL, pad, &parent); +		if (ret < 0) +			continue; + +		oclass = impl->sclass;  		do {  			ret = -EINVAL;  			if (oclass->handle == info.type) { -				ret = nouveau_object_ctor(*pobject, *pobject, +				ret = nouveau_object_ctor(parent, *pobject,  							  oclass, &info,  							  index, &object);  			}  		} while (ret && (++oclass)->handle); + +		nouveau_object_ref(NULL, &parent);  	}  	/* in addition to the busses specified in the i2c table, there @@ -363,5 +547,28 @@ nouveau_i2c_create_(struct nouveau_object *parent,  		}  	} +	ret = nouveau_event_create(4, index, &i2c->ntfy); +	if (ret) +		return ret; + +	i2c->ntfy->priv = i2c; +	i2c->ntfy->enable = nouveau_i2c_intr_enable; +	i2c->ntfy->disable = nouveau_i2c_intr_disable; +	return 0; +} + +int +_nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **pobject) +{ +	struct nouveau_i2c *i2c; +	int ret; + +	ret = nouveau_i2c_create(parent, engine, oclass, &i2c); +	*pobject = nv_object(i2c); +	if (ret) +		return ret; +  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c index a6e72d3b06b..813ffc96e86 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c @@ -22,7 +22,7 @@   * Authors: Ben Skeggs   */ -#include "subdev/i2c.h" +#include "priv.h"  #ifdef CONFIG_NOUVEAU_I2C_INTERNAL  #define T_TIMEOUT  2200000 @@ -187,8 +187,9 @@ i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	struct i2c_msg *msg = msgs;  	int ret = 0, mcnt = num; -	if (port->func->acquire) -		port->func->acquire(port); +	ret = nouveau_i2c(port)->acquire(port, nsecs_to_jiffies(T_TIMEOUT)); +	if (ret) +		return ret;  	while (!ret && mcnt--) {  		u8 remaining = msg->len; @@ -210,6 +211,7 @@ i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  	}  	i2c_stop(port); +	nouveau_i2c(port)->release(port);  	return (ret < 0) ? ret : num;  }  #else diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/gf117.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/gf117.c new file mode 100644 index 00000000000..fa891c39866 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/gf117.c @@ -0,0 +1,39 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +struct nouveau_oclass * +gf117_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0xd7), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor, +		.dtor = _nouveau_i2c_dtor, +		.init = _nouveau_i2c_init, +		.fini = _nouveau_i2c_fini, +	}, +	.sclass = nvd0_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +	.pad_s = &nv04_i2c_pad_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c index 860d5d2365d..b1725bdea96 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c @@ -22,9 +22,10 @@   * Authors: Ben Skeggs   */ -#include <subdev/i2c.h>  #include <subdev/vga.h> +#include "priv.h" +  struct nv04_i2c_priv {  	struct nouveau_i2c base;  }; @@ -115,29 +116,15 @@ nv04_i2c_sclass[] = {  	{}  }; -static int -nv04_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv04_i2c_priv *priv; -	int ret; - -	ret = nouveau_i2c_create(parent, engine, oclass, nv04_i2c_sclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -struct nouveau_oclass -nv04_i2c_oclass = { -	.handle = NV_SUBDEV(I2C, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv04_i2c_ctor, +struct nouveau_oclass * +nv04_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0x04), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor,  		.dtor = _nouveau_i2c_dtor,  		.init = _nouveau_i2c_init,  		.fini = _nouveau_i2c_fini,  	}, -}; +	.sclass = nv04_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c index 0c2655a03bb..f16c87ce5ba 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c @@ -22,9 +22,10 @@   * Authors: Ben Skeggs   */ -#include <subdev/i2c.h>  #include <subdev/vga.h> +#include "priv.h" +  struct nv4e_i2c_priv {  	struct nouveau_i2c base;  }; @@ -107,29 +108,15 @@ nv4e_i2c_sclass[] = {  	{}  }; -static int -nv4e_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv4e_i2c_priv *priv; -	int ret; - -	ret = nouveau_i2c_create(parent, engine, oclass, nv4e_i2c_sclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -struct nouveau_oclass -nv4e_i2c_oclass = { -	.handle = NV_SUBDEV(I2C, 0x4e), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv4e_i2c_ctor, +struct nouveau_oclass * +nv4e_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0x4e), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor,  		.dtor = _nouveau_i2c_dtor,  		.init = _nouveau_i2c_init,  		.fini = _nouveau_i2c_fini,  	}, -}; +	.sclass = nv4e_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c index a8d67a28770..7b8756d4df0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c @@ -121,29 +121,15 @@ nv50_i2c_sclass[] = {  	{}  }; -static int -nv50_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv50_i2c_priv *priv; -	int ret; - -	ret = nouveau_i2c_create(parent, engine, oclass, nv50_i2c_sclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -struct nouveau_oclass -nv50_i2c_oclass = { -	.handle = NV_SUBDEV(I2C, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv50_i2c_ctor, +struct nouveau_oclass * +nv50_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor,  		.dtor = _nouveau_i2c_dtor,  		.init = _nouveau_i2c_init,  		.fini = _nouveau_i2c_fini,  	}, -}; +	.sclass = nv50_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h index 4e5ba48ebf5..5d2a77421c7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h @@ -1,7 +1,7 @@  #ifndef __NV50_I2C_H__  #define __NV50_I2C_H__ -#include <subdev/i2c.h> +#include "priv.h"  struct nv50_i2c_priv {  	struct nouveau_i2c base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c index df6d3e4b68b..f59c3a25546 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c @@ -24,6 +24,36 @@  #include "nv50.h" +void +nv94_aux_stat(struct nouveau_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) +{ +	u32 intr = nv_rd32(i2c, 0x00e06c); +	u32 stat = nv_rd32(i2c, 0x00e068) & intr, i; +	for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { +		if ((stat & (1 << (i * 4)))) *hi |= 1 << i; +		if ((stat & (2 << (i * 4)))) *lo |= 1 << i; +		if ((stat & (4 << (i * 4)))) *rq |= 1 << i; +		if ((stat & (8 << (i * 4)))) *tx |= 1 << i; +	} +	nv_wr32(i2c, 0x00e06c, intr); +} + +void +nv94_aux_mask(struct nouveau_i2c *i2c, u32 type, u32 mask, u32 data) +{ +	u32 temp = nv_rd32(i2c, 0x00e068), i; +	for (i = 0; i < 8; i++) { +		if (mask & (1 << i)) { +			if (!(data & (1 << i))) { +				temp &= ~(type << (i * 4)); +				continue; +			} +			temp |= type << (i * 4); +		} +	} +	nv_wr32(i2c, 0x00e068, temp); +} +  #define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args)  #define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) @@ -69,7 +99,8 @@ auxch_init(struct nouveau_i2c *aux, int ch)  }  int -nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size) +nv94_aux(struct nouveau_i2c_port *base, bool retry, +	 u8 type, u32 addr, u8 *data, u8 size)  {  	struct nouveau_i2c *aux = nouveau_i2c(base);  	struct nv50_i2c_port *port = (void *)base; @@ -105,9 +136,8 @@ nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size)  	ctrl |= size - 1;  	nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); -	/* retry transaction a number of times on failure... */ -	ret = -EREMOTEIO; -	for (retries = 0; retries < 32; retries++) { +	/* (maybe) retry transaction a number of times on failure... */ +	for (retries = 0; !ret && retries < 32; retries++) {  		/* reset, and delay a while if this is a retry */  		nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl);  		nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); @@ -123,16 +153,21 @@ nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size)  			udelay(1);  			if (!timeout--) {  				AUX_ERR("tx req timeout 0x%08x\n", ctrl); +				ret = -EIO;  				goto out;  			}  		} while (ctrl & 0x00010000); +		ret = 1;  		/* read status, and check if transaction completed ok */  		stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); -		if (!(stat & 0x000f0f00)) { -			ret = 0; -			break; -		} +		if ((stat & 0x000f0000) == 0x00080000 || +		    (stat & 0x000f0000) == 0x00020000) +			ret = retry ? 0 : 1; +		if ((stat & 0x00000100)) +			ret = -ETIMEDOUT; +		if ((stat & 0x00000e00)) +			ret = -EIO;  		AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat);  	} @@ -147,29 +182,11 @@ nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size)  out:  	auxch_fini(aux, ch); -	return ret; -} - -void -nv94_i2c_acquire(struct nouveau_i2c_port *base) -{ -	struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; -	struct nv50_i2c_port *port = (void *)base; -	if (port->ctrl) { -		nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000); -		nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data); -	} -} - -void -nv94_i2c_release(struct nouveau_i2c_port *base) -{ +	return ret < 0 ? ret : (stat & 0x000f0000) >> 16;  }  static const struct nouveau_i2c_func  nv94_i2c_func = { -	.acquire   = nv94_i2c_acquire, -	.release   = nv94_i2c_release,  	.drive_scl = nv50_i2c_drive_scl,  	.drive_sda = nv50_i2c_drive_sda,  	.sense_scl = nv50_i2c_sense_scl, @@ -206,8 +223,6 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  static const struct nouveau_i2c_func  nv94_aux_func = { -	.acquire   = nv94_i2c_acquire, -	.release   = nv94_i2c_release,  	.aux       = nv94_aux,  }; @@ -227,6 +242,7 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	if (ret)  		return ret; +	port->base.aux = info->drive;  	port->addr = info->drive;  	if (info->share != DCB_I2C_UNUSED) {  		port->ctrl = 0x00e500 + (info->drive * 0x50); @@ -257,29 +273,19 @@ nv94_i2c_sclass[] = {  	{}  }; -static int -nv94_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv50_i2c_priv *priv; -	int ret; - -	ret = nouveau_i2c_create(parent, engine, oclass, nv94_i2c_sclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -struct nouveau_oclass -nv94_i2c_oclass = { -	.handle = NV_SUBDEV(I2C, 0x94), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv94_i2c_ctor, +struct nouveau_oclass * +nv94_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0x94), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor,  		.dtor = _nouveau_i2c_dtor,  		.init = _nouveau_i2c_init,  		.fini = _nouveau_i2c_fini,  	}, -}; +	.sclass = nv94_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +	.pad_s = &nv94_i2c_pad_oclass, +	.aux = 4, +	.aux_stat = nv94_aux_stat, +	.aux_mask = nv94_aux_mask, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c index 29967d30f97..364ddb1c5f0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c @@ -42,8 +42,6 @@ nvd0_i2c_sense_sda(struct nouveau_i2c_port *base)  static const struct nouveau_i2c_func  nvd0_i2c_func = { -	.acquire   = nv94_i2c_acquire, -	.release   = nv94_i2c_release,  	.drive_scl = nv50_i2c_drive_scl,  	.drive_sda = nv50_i2c_drive_sda,  	.sense_scl = nvd0_i2c_sense_scl, @@ -75,7 +73,7 @@ nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -static struct nouveau_oclass +struct nouveau_oclass  nvd0_i2c_sclass[] = {  	{ .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT),  	  .ofuncs = &(struct nouveau_ofuncs) { @@ -96,29 +94,19 @@ nvd0_i2c_sclass[] = {  	{}  }; -static int -nvd0_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	      struct nouveau_oclass *oclass, void *data, u32 size, -	      struct nouveau_object **pobject) -{ -	struct nv50_i2c_priv *priv; -	int ret; - -	ret = nouveau_i2c_create(parent, engine, oclass, nvd0_i2c_sclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -struct nouveau_oclass -nvd0_i2c_oclass = { -	.handle = NV_SUBDEV(I2C, 0xd0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvd0_i2c_ctor, +struct nouveau_oclass * +nvd0_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0xd0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor,  		.dtor = _nouveau_i2c_dtor,  		.init = _nouveau_i2c_init,  		.fini = _nouveau_i2c_fini,  	}, -}; +	.sclass = nvd0_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +	.pad_s = &nv94_i2c_pad_oclass, +	.aux = 4, +	.aux_stat = nv94_aux_stat, +	.aux_mask = nv94_aux_mask, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nve0.c new file mode 100644 index 00000000000..cae77e1ad8d --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nve0.c @@ -0,0 +1,72 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv50.h" + +static void +nve0_aux_stat(struct nouveau_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) +{ +	u32 intr = nv_rd32(i2c, 0x00dc60); +	u32 stat = nv_rd32(i2c, 0x00dc68) & intr, i; +	for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { +		if ((stat & (1 << (i * 4)))) *hi |= 1 << i; +		if ((stat & (2 << (i * 4)))) *lo |= 1 << i; +		if ((stat & (4 << (i * 4)))) *rq |= 1 << i; +		if ((stat & (8 << (i * 4)))) *tx |= 1 << i; +	} +	nv_wr32(i2c, 0x00dc60, intr); +} + +static void +nve0_aux_mask(struct nouveau_i2c *i2c, u32 type, u32 mask, u32 data) +{ +	u32 temp = nv_rd32(i2c, 0x00dc68), i; +	for (i = 0; i < 8; i++) { +		if (mask & (1 << i)) { +			if (!(data & (1 << i))) { +				temp &= ~(type << (i * 4)); +				continue; +			} +			temp |= type << (i * 4); +		} +	} +	nv_wr32(i2c, 0x00dc68, temp); +} + +struct nouveau_oclass * +nve0_i2c_oclass = &(struct nouveau_i2c_impl) { +	.base.handle = NV_SUBDEV(I2C, 0xe0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nouveau_i2c_ctor, +		.dtor = _nouveau_i2c_dtor, +		.init = _nouveau_i2c_init, +		.fini = _nouveau_i2c_fini, +	}, +	.sclass = nvd0_i2c_sclass, +	.pad_x = &nv04_i2c_pad_oclass, +	.pad_s = &nv94_i2c_pad_oclass, +	.aux = 4, +	.aux_stat = nve0_aux_stat, +	.aux_mask = nve0_aux_mask, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/pad.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/pad.c new file mode 100644 index 00000000000..e9e412477c1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/pad.c @@ -0,0 +1,84 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "pad.h" + +int +_nvkm_i2c_pad_fini(struct nouveau_object *object, bool suspend) +{ +	struct nvkm_i2c_pad *pad = (void *)object; +	DBG("-> NULL\n"); +	pad->port = NULL; +	return nouveau_object_fini(&pad->base, suspend); +} + +int +_nvkm_i2c_pad_init(struct nouveau_object *object) +{ +	struct nvkm_i2c_pad *pad = (void *)object; +	DBG("-> PORT:%02x\n", pad->next->index); +	pad->port = pad->next; +	return nouveau_object_init(&pad->base); +} + +int +nvkm_i2c_pad_create_(struct nouveau_object *parent, +		     struct nouveau_object *engine, +		     struct nouveau_oclass *oclass, int index, +		     int size, void **pobject) +{ +	struct nouveau_i2c *i2c = (void *)engine; +	struct nouveau_i2c_port *port; +	struct nvkm_i2c_pad *pad; +	int ret; + +	list_for_each_entry(port, &i2c->ports, head) { +		pad = nvkm_i2c_pad(port); +		if (pad->index == index) { +			atomic_inc(&nv_object(pad)->refcount); +			*pobject = pad; +			return 1; +		} +	} + +	ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject); +	pad = *pobject; +	if (ret) +		return ret; + +	pad->index = index; +	return 0; +} + +int +_nvkm_i2c_pad_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		   struct nouveau_oclass *oclass, void *data, u32 index, +		   struct nouveau_object **pobject) +{ +	struct nvkm_i2c_pad *pad; +	int ret; +	ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); +	*pobject = nv_object(pad); +	return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/pad.h b/drivers/gpu/drm/nouveau/core/subdev/i2c/pad.h new file mode 100644 index 00000000000..452ac10c300 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/pad.h @@ -0,0 +1,58 @@ +#ifndef __NVKM_I2C_PAD_H__ +#define __NVKM_I2C_PAD_H__ + +#include "priv.h" + +struct nvkm_i2c_pad { +	struct nouveau_object base; +	int index; +	struct nouveau_i2c_port *port; +	struct nouveau_i2c_port *next; +}; + +static inline struct nvkm_i2c_pad * +nvkm_i2c_pad(struct nouveau_i2c_port *port) +{ +	struct nouveau_object *pad = nv_object(port); +	while (pad->parent) +		pad = pad->parent; +	return (void *)pad; +} + +#define nvkm_i2c_pad_create(p,e,o,i,d)                                         \ +	nvkm_i2c_pad_create_((p), (e), (o), (i), sizeof(**d), (void **)d) +#define nvkm_i2c_pad_destroy(p) ({                                             \ +	struct nvkm_i2c_pad *_p = (p);                                         \ +	_nvkm_i2c_pad_dtor(nv_object(_p));                                     \ +}) +#define nvkm_i2c_pad_init(p) ({                                                \ +	struct nvkm_i2c_pad *_p = (p);                                         \ +	_nvkm_i2c_pad_init(nv_object(_p));                                     \ +}) +#define nvkm_i2c_pad_fini(p,s) ({                                              \ +	struct nvkm_i2c_pad *_p = (p);                                         \ +	_nvkm_i2c_pad_fini(nv_object(_p), (s));                                \ +}) + +int nvkm_i2c_pad_create_(struct nouveau_object *, struct nouveau_object *, +			 struct nouveau_oclass *, int index, int, void **); + +int _nvkm_i2c_pad_ctor(struct nouveau_object *, struct nouveau_object *, +		       struct nouveau_oclass *, void *, u32, +		       struct nouveau_object **); +#define _nvkm_i2c_pad_dtor nouveau_object_destroy +int _nvkm_i2c_pad_init(struct nouveau_object *); +int _nvkm_i2c_pad_fini(struct nouveau_object *, bool); + +#ifndef MSG +#define MSG(l,f,a...) do {                                                     \ +	struct nvkm_i2c_pad *_pad = (void *)pad;                               \ +	nv_##l(nv_object(_pad)->engine, "PAD:%c:%02x: "f,                      \ +	       _pad->index >= 0x100 ? 'X' : 'S',                               \ +	       _pad->index >= 0x100 ? _pad->index - 0x100 : _pad->index, ##a); \ +} while(0) +#define DBG(f,a...) MSG(debug, f, ##a) +#define ERR(f,a...) MSG(error, f, ##a) +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/padnv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/padnv04.c new file mode 100644 index 00000000000..2c4b61296dd --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/padnv04.c @@ -0,0 +1,35 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "pad.h" + +struct nouveau_oclass +nv04_i2c_pad_oclass = { +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = _nvkm_i2c_pad_ctor, +		.dtor = _nvkm_i2c_pad_dtor, +		.init = _nvkm_i2c_pad_init, +		.fini = _nvkm_i2c_pad_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/padnv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/padnv94.c new file mode 100644 index 00000000000..0dc6753014f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/padnv94.c @@ -0,0 +1,86 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "pad.h" + +struct nv94_i2c_pad { +	struct nvkm_i2c_pad base; +	int addr; +}; + +static int +nv94_i2c_pad_fini(struct nouveau_object *object, bool suspend) +{ +	struct nouveau_i2c *i2c = (void *)object->engine; +	struct nv94_i2c_pad *pad = (void *)object; +	nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000001); +	return nvkm_i2c_pad_fini(&pad->base, suspend); +} + +static int +nv94_i2c_pad_init(struct nouveau_object *object) +{ +	struct nouveau_i2c *i2c = (void *)object->engine; +	struct nv94_i2c_pad *pad = (void *)object; + +	switch (nv_oclass(pad->base.next)->handle) { +	case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX): +		nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x00000002); +		break; +	case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT): +	default: +		nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x0000c001); +		break; +	} + +	nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000000); +	return nvkm_i2c_pad_init(&pad->base); +} + +static int +nv94_i2c_pad_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 index, +		  struct nouveau_object **pobject) +{ +	struct nv94_i2c_pad *pad; +	int ret; + +	ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); +	*pobject = nv_object(pad); +	if (ret) +		return ret; + +	pad->addr = index * 0x50;; +	return 0; +} + +struct nouveau_oclass +nv94_i2c_pad_oclass = { +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv94_i2c_pad_ctor, +		.dtor = _nvkm_i2c_pad_dtor, +		.init = nv94_i2c_pad_init, +		.fini = nv94_i2c_pad_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/port.h b/drivers/gpu/drm/nouveau/core/subdev/i2c/port.h new file mode 100644 index 00000000000..a8ff6e077af --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/port.h @@ -0,0 +1,15 @@ +#ifndef __NVKM_I2C_PORT_H__ +#define __NVKM_I2C_PORT_H__ + +#include "priv.h" + +#ifndef MSG +#define MSG(l,f,a...) do {                                                     \ +	struct nouveau_i2c_port *_port = (void *)port;                         \ +	nv_##l(nv_object(_port)->engine, "PORT:%02x: "f, _port->index, ##a);   \ +} while(0) +#define DBG(f,a...) MSG(debug, f, ##a) +#define ERR(f,a...) MSG(error, f, ##a) +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/priv.h b/drivers/gpu/drm/nouveau/core/subdev/i2c/priv.h new file mode 100644 index 00000000000..780090b6425 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/priv.h @@ -0,0 +1,85 @@ +#ifndef __NVKM_I2C_H__ +#define __NVKM_I2C_H__ + +#include <subdev/i2c.h> + +extern struct nouveau_oclass nv04_i2c_pad_oclass; +extern struct nouveau_oclass nv94_i2c_pad_oclass; + +#define nouveau_i2c_port_create(p,e,o,i,a,f,d)                                 \ +	nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f),                 \ +				 sizeof(**d), (void **)d) +#define nouveau_i2c_port_destroy(p) ({                                         \ +	struct nouveau_i2c_port *port = (p);                                   \ +	_nouveau_i2c_port_dtor(nv_object(i2c));                                \ +}) +#define nouveau_i2c_port_init(p)                                               \ +	nouveau_object_init(&(p)->base) +#define nouveau_i2c_port_fini(p,s)                                             \ +	nouveau_object_fini(&(p)->base, (s)) + +int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, +			     struct nouveau_oclass *, u8, +			     const struct i2c_algorithm *, +			     const struct nouveau_i2c_func *, +			     int, void **); +void _nouveau_i2c_port_dtor(struct nouveau_object *); +#define _nouveau_i2c_port_init nouveau_object_init +int  _nouveau_i2c_port_fini(struct nouveau_object *, bool); + +#define nouveau_i2c_create(p,e,o,d)                                            \ +	nouveau_i2c_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_i2c_destroy(p) ({                                              \ +	struct nouveau_i2c *i2c = (p);                                         \ +	_nouveau_i2c_dtor(nv_object(i2c));                                     \ +}) +#define nouveau_i2c_init(p) ({                                                 \ +	struct nouveau_i2c *i2c = (p);                                         \ +	_nouveau_i2c_init(nv_object(i2c));                                     \ +}) +#define nouveau_i2c_fini(p,s) ({                                               \ +	struct nouveau_i2c *i2c = (p);                                         \ +	_nouveau_i2c_fini(nv_object(i2c), (s));                                \ +}) + +int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, +			struct nouveau_oclass *, int, void **); +int  _nouveau_i2c_ctor(struct nouveau_object *, struct nouveau_object *, +		       struct nouveau_oclass *, void *, u32, +		       struct nouveau_object **); +void _nouveau_i2c_dtor(struct nouveau_object *); +int  _nouveau_i2c_init(struct nouveau_object *); +int  _nouveau_i2c_fini(struct nouveau_object *, bool); + +extern struct nouveau_oclass nouveau_anx9805_sclass[]; +extern struct nouveau_oclass nvd0_i2c_sclass[]; + +extern const struct i2c_algorithm nouveau_i2c_bit_algo; +extern const struct i2c_algorithm nouveau_i2c_aux_algo; + +struct nouveau_i2c_impl { +	struct nouveau_oclass base; + +	/* supported i2c port classes */ +	struct nouveau_oclass *sclass; +	struct nouveau_oclass *pad_x; +	struct nouveau_oclass *pad_s; + +	/* number of native dp aux channels present */ +	int aux; + +	/* read and ack pending interrupts, returning only data +	 * for ports that have not been masked off, while still +	 * performing the ack for anything that was pending. +	 */ +	void (*aux_stat)(struct nouveau_i2c *, u32 *, u32 *, u32 *, u32 *); + +	/* mask on/off interrupt types for a given set of auxch +	 */ +	void (*aux_mask)(struct nouveau_i2c *, u32, u32, u32); +}; + +void nv94_aux_stat(struct nouveau_i2c *, u32 *, u32 *, u32 *, u32 *); +void nv94_aux_mask(struct nouveau_i2c *, u32, u32, u32); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/gk20a.c new file mode 100644 index 00000000000..245f0ebaa6a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ibus/gk20a.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <subdev/ibus.h> +#include <subdev/timer.h> + +struct gk20a_ibus_priv { +	struct nouveau_ibus base; +}; + +static void +gk20a_ibus_init_priv_ring(struct gk20a_ibus_priv *priv) +{ +	nv_mask(priv, 0x137250, 0x3f, 0); + +	nv_mask(priv, 0x000200, 0x20, 0); +	usleep_range(20, 30); +	nv_mask(priv, 0x000200, 0x20, 0x20); + +	nv_wr32(priv, 0x12004c, 0x4); +	nv_wr32(priv, 0x122204, 0x2); +	nv_rd32(priv, 0x122204); +} + +static void +gk20a_ibus_intr(struct nouveau_subdev *subdev) +{ +	struct gk20a_ibus_priv *priv = (void *)subdev; +	u32 status0 = nv_rd32(priv, 0x120058); + +	if (status0 & 0x7) { +		nv_debug(priv, "resetting priv ring\n"); +		gk20a_ibus_init_priv_ring(priv); +	} + +	/* Acknowledge interrupt */ +	nv_mask(priv, 0x12004c, 0x2, 0x2); + +	if (!nv_wait(subdev, 0x12004c, 0x3f, 0x00)) +		nv_warn(priv, "timeout waiting for ringmaster ack\n"); +} + +static int +gk20a_ibus_init(struct nouveau_object *object) +{ +	struct gk20a_ibus_priv *priv = (void *)object; +	int ret; + +	ret = _nouveau_ibus_init(object); +	if (ret) +		return ret; + +	gk20a_ibus_init_priv_ring(priv); + +	return 0; +} + +static int +gk20a_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct gk20a_ibus_priv *priv; +	int ret; + +	ret = nouveau_ibus_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	nv_subdev(priv)->intr = gk20a_ibus_intr; +	return 0; +} + +struct nouveau_oclass +gk20a_ibus_oclass = { +	.handle = NV_SUBDEV(IBUS, 0xea), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = gk20a_ibus_ctor, +		.dtor = _nouveau_ibus_dtor, +		.init = gk20a_ibus_init, +		.fini = _nouveau_ibus_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c b/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c index 7120124dcea..ebef970a064 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ibus/nve0.c @@ -95,6 +95,23 @@ nve0_ibus_intr(struct nouveau_subdev *subdev)  }  static int +nve0_ibus_init(struct nouveau_object *object) +{ +	struct nve0_ibus_priv *priv = (void *)object; +	int ret = nouveau_ibus_init(&priv->base); +	if (ret == 0) { +		nv_mask(priv, 0x122318, 0x0003ffff, 0x00001000); +		nv_mask(priv, 0x12231c, 0x0003ffff, 0x00000200); +		nv_mask(priv, 0x122310, 0x0003ffff, 0x00000800); +		nv_mask(priv, 0x122348, 0x0003ffff, 0x00000100); +		nv_mask(priv, 0x1223b0, 0x0003ffff, 0x00000fff); +		nv_mask(priv, 0x122348, 0x0003ffff, 0x00000200); +		nv_mask(priv, 0x122358, 0x0003ffff, 0x00002880); +	} +	return ret; +} + +static int  nve0_ibus_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size,  	       struct nouveau_object **pobject) @@ -117,7 +134,7 @@ nve0_ibus_oclass = {  	.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nve0_ibus_ctor,  		.dtor = _nouveau_ibus_dtor, -		.init = _nouveau_ibus_init, +		.init = nve0_ibus_init,  		.fini = _nouveau_ibus_fini,  	},  }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c index 6565f3dbbe0..14706d9842c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c @@ -22,7 +22,24 @@   * Authors: Ben Skeggs   */ -#include <subdev/instmem.h> +#include "priv.h" + +/****************************************************************************** + * instmem object base implementation + *****************************************************************************/ + +void +_nouveau_instobj_dtor(struct nouveau_object *object) +{ +	struct nouveau_instmem *imem = (void *)object->engine; +	struct nouveau_instobj *iobj = (void *)object; + +	mutex_lock(&nv_subdev(imem)->mutex); +	list_del(&iobj->head); +	mutex_unlock(&nv_subdev(imem)->mutex); + +	return nouveau_object_destroy(&iobj->base); +}  int  nouveau_instobj_create_(struct nouveau_object *parent, @@ -46,73 +63,26 @@ nouveau_instobj_create_(struct nouveau_object *parent,  	return 0;  } -void -nouveau_instobj_destroy(struct nouveau_instobj *iobj) -{ -	struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); +/****************************************************************************** + * instmem subdev base implementation + *****************************************************************************/ -	mutex_lock(&subdev->mutex); -	list_del(&iobj->head); -	mutex_unlock(&subdev->mutex); - -	return nouveau_object_destroy(&iobj->base); -} - -void -_nouveau_instobj_dtor(struct nouveau_object *object) +static int +nouveau_instmem_alloc(struct nouveau_instmem *imem, +		      struct nouveau_object *parent, u32 size, u32 align, +		      struct nouveau_object **pobject)  { -	struct nouveau_instobj *iobj = (void *)object; -	return nouveau_instobj_destroy(iobj); +	struct nouveau_object *engine = nv_object(imem); +	struct nouveau_instmem_impl *impl = (void *)engine->oclass; +	struct nouveau_instobj_args args = { .size = size, .align = align }; +	return nouveau_object_ctor(parent, engine, impl->instobj, &args, +				   sizeof(args), pobject);  }  int -nouveau_instmem_create_(struct nouveau_object *parent, -			struct nouveau_object *engine, -			struct nouveau_oclass *oclass, -			int length, void **pobject) -{ -	struct nouveau_instmem *imem; -	int ret; - -	ret = nouveau_subdev_create_(parent, engine, oclass, 0, -				     "INSTMEM", "instmem", length, pobject); -	imem = *pobject; -	if (ret) -		return ret; - -	INIT_LIST_HEAD(&imem->list); -	return 0; -} - -int -nouveau_instmem_init(struct nouveau_instmem *imem) -{ -	struct nouveau_instobj *iobj; -	int ret, i; - -	ret = nouveau_subdev_init(&imem->base); -	if (ret) -		return ret; - -	mutex_lock(&imem->base.mutex); - -	list_for_each_entry(iobj, &imem->list, head) { -		if (iobj->suspend) { -			for (i = 0; i < iobj->size; i += 4) -				nv_wo32(iobj, i, iobj->suspend[i / 4]); -			vfree(iobj->suspend); -			iobj->suspend = NULL; -		} -	} - -	mutex_unlock(&imem->base.mutex); - -	return 0; -} - -int -nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) +_nouveau_instmem_fini(struct nouveau_object *object, bool suspend)  { +	struct nouveau_instmem *imem = (void *)object;  	struct nouveau_instobj *iobj;  	int i, ret = 0; @@ -143,12 +113,45 @@ int  _nouveau_instmem_init(struct nouveau_object *object)  {  	struct nouveau_instmem *imem = (void *)object; -	return nouveau_instmem_init(imem); +	struct nouveau_instobj *iobj; +	int ret, i; + +	ret = nouveau_subdev_init(&imem->base); +	if (ret) +		return ret; + +	mutex_lock(&imem->base.mutex); + +	list_for_each_entry(iobj, &imem->list, head) { +		if (iobj->suspend) { +			for (i = 0; i < iobj->size; i += 4) +				nv_wo32(iobj, i, iobj->suspend[i / 4]); +			vfree(iobj->suspend); +			iobj->suspend = NULL; +		} +	} + +	mutex_unlock(&imem->base.mutex); + +	return 0;  }  int -_nouveau_instmem_fini(struct nouveau_object *object, bool suspend) +nouveau_instmem_create_(struct nouveau_object *parent, +			struct nouveau_object *engine, +			struct nouveau_oclass *oclass, +			int length, void **pobject)  { -	struct nouveau_instmem *imem = (void *)object; -	return nouveau_instmem_fini(imem, suspend); +	struct nouveau_instmem *imem; +	int ret; + +	ret = nouveau_subdev_create_(parent, engine, oclass, 0, +				     "INSTMEM", "instmem", length, pobject); +	imem = *pobject; +	if (ret) +		return ret; + +	INIT_LIST_HEAD(&imem->list); +	imem->alloc = nouveau_instmem_alloc; +	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c index 795393d7b2f..7b64befee48 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c @@ -22,10 +22,35 @@   * Authors: Ben Skeggs   */ -#include <subdev/fb.h> -  #include "nv04.h" +/****************************************************************************** + * instmem object implementation + *****************************************************************************/ + +static u32 +nv04_instobj_rd32(struct nouveau_object *object, u64 addr) +{ +	struct nv04_instobj_priv *node = (void *)object; +	return nv_ro32(object->engine, node->mem->offset + addr); +} + +static void +nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data) +{ +	struct nv04_instobj_priv *node = (void *)object; +	nv_wo32(object->engine, node->mem->offset + addr, data); +} + +static void +nv04_instobj_dtor(struct nouveau_object *object) +{ +	struct nv04_instmem_priv *priv = (void *)object->engine; +	struct nv04_instobj_priv *node = (void *)object; +	nouveau_mm_free(&priv->heap, &node->mem); +	nouveau_instobj_destroy(&node->base); +} +  static int  nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		  struct nouveau_oclass *oclass, void *data, u32 size, @@ -33,18 +58,19 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  {  	struct nv04_instmem_priv *priv = (void *)engine;  	struct nv04_instobj_priv *node; -	int ret, align; +	struct nouveau_instobj_args *args = data; +	int ret; -	align = (unsigned long)data; -	if (!align) -		align = 1; +	if (!args->align) +		args->align = 1;  	ret = nouveau_instobj_create(parent, engine, oclass, &node);  	*pobject = nv_object(node);  	if (ret)  		return ret; -	ret = nouveau_mm_head(&priv->heap, 1, size, size, align, &node->mem); +	ret = nouveau_mm_head(&priv->heap, 1, args->size, args->size, +			      args->align, &node->mem);  	if (ret)  		return ret; @@ -53,32 +79,9 @@ nv04_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -static void -nv04_instobj_dtor(struct nouveau_object *object) -{ -	struct nv04_instmem_priv *priv = (void *)object->engine; -	struct nv04_instobj_priv *node = (void *)object; -	nouveau_mm_free(&priv->heap, &node->mem); -	nouveau_instobj_destroy(&node->base); -} - -static u32 -nv04_instobj_rd32(struct nouveau_object *object, u64 addr) -{ -	struct nv04_instobj_priv *node = (void *)object; -	return nv_ro32(object->engine, node->mem->offset + addr); -} - -static void -nv04_instobj_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ -	struct nv04_instobj_priv *node = (void *)object; -	nv_wo32(object->engine, node->mem->offset + addr, data); -} - -static struct nouveau_oclass +struct nouveau_instobj_impl  nv04_instobj_oclass = { -	.ofuncs = &(struct nouveau_ofuncs) { +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_instobj_ctor,  		.dtor = nv04_instobj_dtor,  		.init = _nouveau_instobj_init, @@ -88,19 +91,34 @@ nv04_instobj_oclass = {  	},  }; -int -nv04_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, -		   u32 size, u32 align, struct nouveau_object **pobject) +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ + +static u32 +nv04_instmem_rd32(struct nouveau_object *object, u64 addr)  { -	struct nouveau_object *engine = nv_object(imem); -	int ret; +	return nv_rd32(object, 0x700000 + addr); +} -	ret = nouveau_object_ctor(parent, engine, &nv04_instobj_oclass, -				  (void *)(unsigned long)align, size, pobject); -	if (ret) -		return ret; +static void +nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) +{ +	return nv_wr32(object, 0x700000 + addr, data); +} -	return 0; +void +nv04_instmem_dtor(struct nouveau_object *object) +{ +	struct nv04_instmem_priv *priv = (void *)object; +	nouveau_gpuobj_ref(NULL, &priv->ramfc); +	nouveau_gpuobj_ref(NULL, &priv->ramro); +	nouveau_ramht_ref(NULL, &priv->ramht); +	nouveau_gpuobj_ref(NULL, &priv->vbios); +	nouveau_mm_fini(&priv->heap); +	if (priv->iomem) +		iounmap(priv->iomem); +	nouveau_instmem_destroy(&priv->base);  }  static int @@ -118,7 +136,6 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	/* PRAMIN aperture maps over the end of VRAM, reserve it */  	priv->base.reserved = 512 * 1024; -	priv->base.alloc    = nv04_instmem_alloc;  	ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);  	if (ret) @@ -150,36 +167,10 @@ nv04_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -void -nv04_instmem_dtor(struct nouveau_object *object) -{ -	struct nv04_instmem_priv *priv = (void *)object; -	nouveau_gpuobj_ref(NULL, &priv->ramfc); -	nouveau_gpuobj_ref(NULL, &priv->ramro); -	nouveau_ramht_ref(NULL, &priv->ramht); -	nouveau_gpuobj_ref(NULL, &priv->vbios); -	nouveau_mm_fini(&priv->heap); -	if (priv->iomem) -		iounmap(priv->iomem); -	nouveau_instmem_destroy(&priv->base); -} - -static u32 -nv04_instmem_rd32(struct nouveau_object *object, u64 addr) -{ -	return nv_rd32(object, 0x700000 + addr); -} - -static void -nv04_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ -	return nv_wr32(object, 0x700000 + addr, data); -} - -struct nouveau_oclass -nv04_instmem_oclass = { -	.handle = NV_SUBDEV(INSTMEM, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_instmem_oclass = &(struct nouveau_instmem_impl) { +	.base.handle = NV_SUBDEV(INSTMEM, 0x04), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_instmem_ctor,  		.dtor = nv04_instmem_dtor,  		.init = _nouveau_instmem_init, @@ -187,4 +178,5 @@ nv04_instmem_oclass = {  		.rd32 = nv04_instmem_rd32,  		.wr32 = nv04_instmem_wr32,  	}, -}; +	.instobj = &nv04_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h index b15b6131023..095fbc6fc09 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h @@ -5,7 +5,9 @@  #include <core/ramht.h>  #include <core/mm.h> -#include <subdev/instmem.h> +#include "priv.h" + +extern struct nouveau_instobj_impl nv04_instobj_oclass;  struct nv04_instmem_priv {  	struct nouveau_instmem base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index b10a143787a..8803809f9fc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c @@ -26,13 +26,30 @@  #include "nv04.h" +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ + +static u32 +nv40_instmem_rd32(struct nouveau_object *object, u64 addr) +{ +	struct nv04_instmem_priv *priv = (void *)object; +	return ioread32_native(priv->iomem + addr); +} + +static void +nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) +{ +	struct nv04_instmem_priv *priv = (void *)object; +	iowrite32_native(data, priv->iomem + addr); +} +  static int  nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		  struct nouveau_oclass *oclass, void *data, u32 size,  		  struct nouveau_object **pobject)  {  	struct nouveau_device *device = nv_device(parent); -	struct pci_dev *pdev = device->pdev;  	struct nv04_instmem_priv *priv;  	int ret, bar, vs; @@ -42,13 +59,13 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		return ret;  	/* map bar */ -	if (pci_resource_len(pdev, 2)) +	if (nv_device_resource_len(device, 2))  		bar = 2;  	else  		bar = 3; -	priv->iomem = ioremap(pci_resource_start(pdev, bar), -			      pci_resource_len(pdev, bar)); +	priv->iomem = ioremap(nv_device_resource_start(device, bar), +			      nv_device_resource_len(device, bar));  	if (!priv->iomem) {  		nv_error(priv, "unable to map PRAMIN BAR\n");  		return -EFAULT; @@ -69,7 +86,6 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	priv->base.reserved += 512 * 1024;	/* object storage */  	priv->base.reserved = round_up(priv->base.reserved, 4096); -	priv->base.alloc    = nv04_instmem_alloc;  	ret = nouveau_mm_init(&priv->heap, 0, priv->base.reserved, 1);  	if (ret) @@ -106,24 +122,10 @@ nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -static u32 -nv40_instmem_rd32(struct nouveau_object *object, u64 addr) -{ -	struct nv04_instmem_priv *priv = (void *)object; -	return ioread32_native(priv->iomem + addr); -} - -static void -nv40_instmem_wr32(struct nouveau_object *object, u64 addr, u32 data) -{ -	struct nv04_instmem_priv *priv = (void *)object; -	iowrite32_native(data, priv->iomem + addr); -} - -struct nouveau_oclass -nv40_instmem_oclass = { -	.handle = NV_SUBDEV(INSTMEM, 0x40), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv40_instmem_oclass = &(struct nouveau_instmem_impl) { +	.base.handle = NV_SUBDEV(INSTMEM, 0x40), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv40_instmem_ctor,  		.dtor = nv04_instmem_dtor,  		.init = _nouveau_instmem_init, @@ -131,4 +133,5 @@ nv40_instmem_oclass = {  		.rd32 = nv40_instmem_rd32,  		.wr32 = nv40_instmem_wr32,  	}, -}; +	.instobj = &nv04_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c index 97bc5dff93e..7cb3b098a08 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv50.c @@ -22,11 +22,11 @@   * Authors: Ben Skeggs   */ -#include <subdev/instmem.h>  #include <subdev/fb.h> -  #include <core/mm.h> +#include "priv.h" +  struct nv50_instmem_priv {  	struct nouveau_instmem base;  	spinlock_t lock; @@ -38,42 +38,9 @@ struct nv50_instobj_priv {  	struct nouveau_mem *mem;  }; -static int -nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		  struct nouveau_oclass *oclass, void *data, u32 size, -		  struct nouveau_object **pobject) -{ -	struct nouveau_fb *pfb = nouveau_fb(parent); -	struct nv50_instobj_priv *node; -	u32 align = (unsigned long)data; -	int ret; - -	size  = max((size  + 4095) & ~4095, (u32)4096); -	align = max((align + 4095) & ~4095, (u32)4096); - -	ret = nouveau_instobj_create(parent, engine, oclass, &node); -	*pobject = nv_object(node); -	if (ret) -		return ret; - -	ret = pfb->ram->get(pfb, size, align, 0, 0x800, &node->mem); -	if (ret) -		return ret; - -	node->base.addr = node->mem->offset; -	node->base.size = node->mem->size << 12; -	node->mem->page_shift = 12; -	return 0; -} - -static void -nv50_instobj_dtor(struct nouveau_object *object) -{ -	struct nv50_instobj_priv *node = (void *)object; -	struct nouveau_fb *pfb = nouveau_fb(object); -	pfb->ram->put(pfb, &node->mem); -	nouveau_instobj_destroy(&node->base); -} +/****************************************************************************** + * instmem object implementation + *****************************************************************************/  static u32  nv50_instobj_rd32(struct nouveau_object *object, u64 offset) @@ -113,9 +80,46 @@ nv50_instobj_wr32(struct nouveau_object *object, u64 offset, u32 data)  	spin_unlock_irqrestore(&priv->lock, flags);  } -static struct nouveau_oclass +static void +nv50_instobj_dtor(struct nouveau_object *object) +{ +	struct nv50_instobj_priv *node = (void *)object; +	struct nouveau_fb *pfb = nouveau_fb(object); +	pfb->ram->put(pfb, &node->mem); +	nouveau_instobj_destroy(&node->base); +} + +static int +nv50_instobj_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		  struct nouveau_oclass *oclass, void *data, u32 size, +		  struct nouveau_object **pobject) +{ +	struct nouveau_fb *pfb = nouveau_fb(parent); +	struct nouveau_instobj_args *args = data; +	struct nv50_instobj_priv *node; +	int ret; + +	args->size  = max((args->size  + 4095) & ~4095, (u32)4096); +	args->align = max((args->align + 4095) & ~4095, (u32)4096); + +	ret = nouveau_instobj_create(parent, engine, oclass, &node); +	*pobject = nv_object(node); +	if (ret) +		return ret; + +	ret = pfb->ram->get(pfb, args->size, args->align, 0, 0x800, &node->mem); +	if (ret) +		return ret; + +	node->base.addr = node->mem->offset; +	node->base.size = node->mem->size << 12; +	node->mem->page_shift = 12; +	return 0; +} + +static struct nouveau_instobj_impl  nv50_instobj_oclass = { -	.ofuncs = &(struct nouveau_ofuncs) { +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_instobj_ctor,  		.dtor = nv50_instobj_dtor,  		.init = _nouveau_instobj_init, @@ -125,13 +129,16 @@ nv50_instobj_oclass = {  	},  }; +/****************************************************************************** + * instmem subdev implementation + *****************************************************************************/ +  static int -nv50_instmem_alloc(struct nouveau_instmem *imem, struct nouveau_object *parent, -		   u32 size, u32 align, struct nouveau_object **pobject) +nv50_instmem_fini(struct nouveau_object *object, bool suspend)  { -	struct nouveau_object *engine = nv_object(imem); -	return nouveau_object_ctor(parent, engine, &nv50_instobj_oclass, -				   (void *)(unsigned long)align, size, pobject); +	struct nv50_instmem_priv *priv = (void *)object; +	priv->addr = ~0ULL; +	return nouveau_instmem_fini(&priv->base, suspend);  }  static int @@ -148,25 +155,17 @@ nv50_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		return ret;  	spin_lock_init(&priv->lock); -	priv->base.alloc = nv50_instmem_alloc;  	return 0;  } -static int -nv50_instmem_fini(struct nouveau_object *object, bool suspend) -{ -	struct nv50_instmem_priv *priv = (void *)object; -	priv->addr = ~0ULL; -	return nouveau_instmem_fini(&priv->base, suspend); -} - -struct nouveau_oclass -nv50_instmem_oclass = { -	.handle = NV_SUBDEV(INSTMEM, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv50_instmem_oclass = &(struct nouveau_instmem_impl) { +	.base.handle = NV_SUBDEV(INSTMEM, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv50_instmem_ctor,  		.dtor = _nouveau_instmem_dtor,  		.init = _nouveau_instmem_init,  		.fini = nv50_instmem_fini,  	}, -}; +	.instobj = &nv50_instobj_oclass.base, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h new file mode 100644 index 00000000000..8d67dedc5bb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/priv.h @@ -0,0 +1,56 @@ +#ifndef __NVKM_INSTMEM_PRIV_H__ +#define __NVKM_INSTMEM_PRIV_H__ + +#include <subdev/instmem.h> + +struct nouveau_instobj_impl { +	struct nouveau_oclass base; +}; + +struct nouveau_instobj_args { +	u32 size; +	u32 align; +}; + +#define nouveau_instobj_create(p,e,o,d)                                        \ +	nouveau_instobj_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instobj_destroy(p) ({                                          \ +	struct nouveau_instobj *iobj = (p);                                    \ +	_nouveau_instobj_dtor(nv_object(iobj));                                \ +}) +#define nouveau_instobj_init(p)                                                \ +	nouveau_object_init(&(p)->base) +#define nouveau_instobj_fini(p,s)                                              \ +	nouveau_object_fini(&(p)->base, (s)) + +int  nouveau_instobj_create_(struct nouveau_object *, struct nouveau_object *, +			     struct nouveau_oclass *, int, void **); +void _nouveau_instobj_dtor(struct nouveau_object *); +#define _nouveau_instobj_init nouveau_object_init +#define _nouveau_instobj_fini nouveau_object_fini + +struct nouveau_instmem_impl { +	struct nouveau_oclass base; +	struct nouveau_oclass *instobj; +}; + +#define nouveau_instmem_create(p,e,o,d)                                        \ +	nouveau_instmem_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_instmem_destroy(p)                                             \ +	nouveau_subdev_destroy(&(p)->base) +#define nouveau_instmem_init(p) ({                                             \ +	struct nouveau_instmem *imem = (p);                                    \ +	_nouveau_instmem_init(nv_object(imem));                                \ +}) +#define nouveau_instmem_fini(p,s) ({                                           \ +	struct nouveau_instmem *imem = (p);                                    \ +	_nouveau_instmem_fini(nv_object(imem), (s));                           \ +}) + +int nouveau_instmem_create_(struct nouveau_object *, struct nouveau_object *, +			    struct nouveau_oclass *, int, void **); +#define _nouveau_instmem_dtor _nouveau_subdev_dtor +int _nouveau_instmem_init(struct nouveau_object *); +int _nouveau_instmem_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c index cce65cc5651..f2f3338a967 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.c @@ -22,44 +22,35 @@   * Authors: Ben Skeggs   */ -#include <subdev/ltcg.h>  #include <subdev/fb.h>  #include <subdev/timer.h> -struct nvc0_ltcg_priv { -	struct nouveau_ltcg base; -	u32 part_nr; -	u32 subp_nr; -	u32 num_tags; -	u32 tag_base; -	struct nouveau_mm tags; -	struct nouveau_mm_node *tag_ram; -}; +#include "gf100.h"  static void -nvc0_ltcg_subp_isr(struct nvc0_ltcg_priv *priv, int unit, int subp) +gf100_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts)  { -	u32 subp_base = 0x141000 + (unit * 0x2000) + (subp * 0x400); -	u32 stat = nv_rd32(priv, subp_base + 0x020); +	u32 base = 0x141000 + (ltc * 0x2000) + (lts * 0x400); +	u32 stat = nv_rd32(priv, base + 0x020);  	if (stat) { -		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", unit, subp, stat); -		nv_wr32(priv, subp_base + 0x020, stat); +		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat); +		nv_wr32(priv, base + 0x020, stat);  	}  }  static void -nvc0_ltcg_intr(struct nouveau_subdev *subdev) +gf100_ltcg_intr(struct nouveau_subdev *subdev)  { -	struct nvc0_ltcg_priv *priv = (void *)subdev; -	u32 units; - -	units = nv_rd32(priv, 0x00017c); -	while (units) { -		u32 subp, unit = ffs(units) - 1; -		for (subp = 0; subp < priv->subp_nr; subp++) -			nvc0_ltcg_subp_isr(priv, unit, subp); -		units &= ~(1 << unit); +	struct gf100_ltcg_priv *priv = (void *)subdev; +	u32 mask; + +	mask = nv_rd32(priv, 0x00017c); +	while (mask) { +		u32 lts, ltc = __ffs(mask); +		for (lts = 0; lts < priv->lts_nr; lts++) +			gf100_ltcg_lts_isr(priv, ltc, lts); +		mask &= ~(1 << ltc);  	}  	/* we do something horribly wrong and upset PMFB a lot, so mask off @@ -68,11 +59,11 @@ nvc0_ltcg_intr(struct nouveau_subdev *subdev)  	nv_mask(priv, 0x000640, 0x02000000, 0x00000000);  } -static int -nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n, +int +gf100_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,  		     struct nouveau_mm_node **pnode)  { -	struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;  	int ret;  	ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode); @@ -82,18 +73,18 @@ nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n,  	return ret;  } -static void -nvc0_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode) +void +gf100_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode)  { -	struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;  	nouveau_mm_free(&priv->tags, pnode);  }  static void -nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count) +gf100_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)  { -	struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;  	u32 last = first + count - 1;  	int p, i; @@ -104,16 +95,16 @@ nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count)  	nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */  	/* wait until it's finished with clearing */ -	for (p = 0; p < priv->part_nr; ++p) { -		for (i = 0; i < priv->subp_nr; ++i) +	for (p = 0; p < priv->ltc_nr; ++p) { +		for (i = 0; i < priv->lts_nr; ++i)  			nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0);  	}  }  /* TODO: Figure out tag memory details and drop the over-cautious allocation.   */ -static int -nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) +int +gf100_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct gf100_ltcg_priv *priv)  {  	u32 tag_size, tag_margin, tag_align;  	int ret; @@ -124,7 +115,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)  		priv->num_tags = 1 << 17; /* we have 17 bits in PTE */  	priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */ -	tag_align = priv->part_nr * 0x800; +	tag_align = priv->ltc_nr * 0x800;  	tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align;  	/* 4 part 4 sub: 0x2000 bytes for 56 tags */ @@ -157,11 +148,11 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)  }  static int -nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +gf100_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	       struct nouveau_oclass *oclass, void *data, u32 size,  	       struct nouveau_object **pobject)  { -	struct nvc0_ltcg_priv *priv; +	struct gf100_ltcg_priv *priv;  	struct nouveau_fb *pfb = nouveau_fb(parent);  	u32 parts, mask;  	int ret, i; @@ -175,27 +166,27 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	mask = nv_rd32(priv, 0x022554);  	for (i = 0; i < parts; i++) {  		if (!(mask & (1 << i))) -			priv->part_nr++; +			priv->ltc_nr++;  	} -	priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; +	priv->lts_nr = nv_rd32(priv, 0x17e8dc) >> 28; -	ret = nvc0_ltcg_init_tag_ram(pfb, priv); +	ret = gf100_ltcg_init_tag_ram(pfb, priv);  	if (ret)  		return ret; -	priv->base.tags_alloc = nvc0_ltcg_tags_alloc; -	priv->base.tags_free  = nvc0_ltcg_tags_free; -	priv->base.tags_clear = nvc0_ltcg_tags_clear; +	priv->base.tags_alloc = gf100_ltcg_tags_alloc; +	priv->base.tags_free  = gf100_ltcg_tags_free; +	priv->base.tags_clear = gf100_ltcg_tags_clear; -	nv_subdev(priv)->intr = nvc0_ltcg_intr; +	nv_subdev(priv)->intr = gf100_ltcg_intr;  	return 0;  } -static void -nvc0_ltcg_dtor(struct nouveau_object *object) +void +gf100_ltcg_dtor(struct nouveau_object *object)  {  	struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; -	struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;  	struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent);  	nouveau_mm_fini(&priv->tags); @@ -205,10 +196,10 @@ nvc0_ltcg_dtor(struct nouveau_object *object)  }  static int -nvc0_ltcg_init(struct nouveau_object *object) +gf100_ltcg_init(struct nouveau_object *object)  {  	struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; -	struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg;  	int ret;  	ret = nouveau_ltcg_init(ltcg); @@ -216,20 +207,20 @@ nvc0_ltcg_init(struct nouveau_object *object)  		return ret;  	nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ -	nv_wr32(priv, 0x17e8d8, priv->part_nr); +	nv_wr32(priv, 0x17e8d8, priv->ltc_nr);  	if (nv_device(ltcg)->card_type >= NV_E0) -		nv_wr32(priv, 0x17e000, priv->part_nr); +		nv_wr32(priv, 0x17e000, priv->ltc_nr);  	nv_wr32(priv, 0x17e8d4, priv->tag_base);  	return 0;  } -struct nouveau_oclass -nvc0_ltcg_oclass = { +struct nouveau_oclass * +gf100_ltcg_oclass = &(struct nouveau_oclass) {  	.handle = NV_SUBDEV(LTCG, 0xc0),  	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvc0_ltcg_ctor, -		.dtor = nvc0_ltcg_dtor, -		.init = nvc0_ltcg_init, +		.ctor = gf100_ltcg_ctor, +		.dtor = gf100_ltcg_dtor, +		.init = gf100_ltcg_init,  		.fini = _nouveau_ltcg_fini,  	},  }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h new file mode 100644 index 00000000000..87b10b8412e --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gf100.h @@ -0,0 +1,21 @@ +#ifndef __NVKM_LTCG_PRIV_GF100_H__ +#define __NVKM_LTCG_PRIV_GF100_H__ + +#include <subdev/ltcg.h> + +struct gf100_ltcg_priv { +	struct nouveau_ltcg base; +	u32 ltc_nr; +	u32 lts_nr; +	u32 num_tags; +	u32 tag_base; +	struct nouveau_mm tags; +	struct nouveau_mm_node *tag_ram; +}; + +void gf100_ltcg_dtor(struct nouveau_object *); +int  gf100_ltcg_init_tag_ram(struct nouveau_fb *, struct gf100_ltcg_priv *); +int  gf100_ltcg_tags_alloc(struct nouveau_ltcg *, u32, struct nouveau_mm_node **); +void gf100_ltcg_tags_free(struct nouveau_ltcg *, struct nouveau_mm_node **); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c new file mode 100644 index 00000000000..e79d0e81de4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/gm107.c @@ -0,0 +1,142 @@ +/* + * Copyright 2014 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/fb.h> +#include <subdev/timer.h> + +#include "gf100.h" + +static void +gm107_ltcg_lts_isr(struct gf100_ltcg_priv *priv, int ltc, int lts) +{ +	u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400); +	u32 stat = nv_rd32(priv, base + 0x00c); + +	if (stat) { +		nv_info(priv, "LTC%d_LTS%d: 0x%08x\n", ltc, lts, stat); +		nv_wr32(priv, base + 0x00c, stat); +	} +} + +static void +gm107_ltcg_intr(struct nouveau_subdev *subdev) +{ +	struct gf100_ltcg_priv *priv = (void *)subdev; +	u32 mask; + +	mask = nv_rd32(priv, 0x00017c); +	while (mask) { +		u32 lts, ltc = __ffs(mask); +		for (lts = 0; lts < priv->lts_nr; lts++) +			gm107_ltcg_lts_isr(priv, ltc, lts); +		mask &= ~(1 << ltc); +	} + +	/* we do something horribly wrong and upset PMFB a lot, so mask off +	 * interrupts from it after the first one until it's fixed +	 */ +	nv_mask(priv, 0x000640, 0x02000000, 0x00000000); +} + +static void +gm107_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count) +{ +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg; +	u32 last = first + count - 1; +	int p, i; + +	BUG_ON((first > last) || (last >= priv->num_tags)); + +	nv_wr32(priv, 0x17e270, first); +	nv_wr32(priv, 0x17e274, last); +	nv_wr32(priv, 0x17e26c, 0x4); /* trigger clear */ + +	/* wait until it's finished with clearing */ +	for (p = 0; p < priv->ltc_nr; ++p) { +		for (i = 0; i < priv->lts_nr; ++i) +			nv_wait(priv, 0x14046c + p * 0x2000 + i * 0x200, ~0, 0); +	} +} + +static int +gm107_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct gf100_ltcg_priv *priv; +	struct nouveau_fb *pfb = nouveau_fb(parent); +	u32 parts, mask; +	int ret, i; + +	ret = nouveau_ltcg_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	parts = nv_rd32(priv, 0x022438); +	mask = nv_rd32(priv, 0x021c14); +	for (i = 0; i < parts; i++) { +		if (!(mask & (1 << i))) +			priv->ltc_nr++; +	} +	priv->lts_nr = nv_rd32(priv, 0x17e280) >> 28; + +	ret = gf100_ltcg_init_tag_ram(pfb, priv); +	if (ret) +		return ret; + +	priv->base.tags_alloc = gf100_ltcg_tags_alloc; +	priv->base.tags_free  = gf100_ltcg_tags_free; +	priv->base.tags_clear = gm107_ltcg_tags_clear; + +	nv_subdev(priv)->intr = gm107_ltcg_intr; +	return 0; +} + +static int +gm107_ltcg_init(struct nouveau_object *object) +{ +	struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; +	struct gf100_ltcg_priv *priv = (struct gf100_ltcg_priv *)ltcg; +	int ret; + +	ret = nouveau_ltcg_init(ltcg); +	if (ret) +		return ret; + +	nv_wr32(priv, 0x17e27c, priv->ltc_nr); +	nv_wr32(priv, 0x17e278, priv->tag_base); +	return 0; +} + +struct nouveau_oclass * +gm107_ltcg_oclass = &(struct nouveau_oclass) { +	.handle = NV_SUBDEV(LTCG, 0xff), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = gm107_ltcg_ctor, +		.dtor = gf100_ltcg_dtor, +		.init = gm107_ltcg_init, +		.fini = _nouveau_ltcg_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 37712a6df92..8a5555192fa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c @@ -25,38 +25,48 @@  #include <subdev/mc.h>  #include <core/option.h> +static inline u32 +nouveau_mc_intr_mask(struct nouveau_mc *pmc) +{ +	u32 intr = nv_rd32(pmc, 0x000100); +	if (intr == 0xffffffff) /* likely fallen off the bus */ +		intr = 0x00000000; +	return intr; +} +  static irqreturn_t  nouveau_mc_intr(int irq, void *arg)  {  	struct nouveau_mc *pmc = arg; -	const struct nouveau_mc_intr *map = pmc->intr_map; -	struct nouveau_device *device = nv_device(pmc); +	const struct nouveau_mc_oclass *oclass = (void *)nv_object(pmc)->oclass; +	const struct nouveau_mc_intr *map = oclass->intr;  	struct nouveau_subdev *unit; -	u32 stat, intr; - -	intr = stat = nv_rd32(pmc, 0x000100); -	if (intr == 0xffffffff) -		return IRQ_NONE; -	while (stat && map->stat) { -		if (stat & map->stat) { -			unit = nouveau_subdev(pmc, map->unit); -			if (unit && unit->intr) -				unit->intr(unit); -			intr &= ~map->stat; -		} -		map++; -	} +	u32 intr; +	nv_wr32(pmc, 0x000140, 0x00000000); +	nv_rd32(pmc, 0x000140); +	intr = nouveau_mc_intr_mask(pmc);  	if (pmc->use_msi) -		nv_wr08(pmc->base.base.parent, 0x00088068, 0xff); +		oclass->msi_rearm(pmc);  	if (intr) { -		nv_error(pmc, "unknown intr 0x%08x\n", stat); +		u32 stat = intr = nouveau_mc_intr_mask(pmc); +		while (map->stat) { +			if (intr & map->stat) { +				unit = nouveau_subdev(pmc, map->unit); +				if (unit && unit->intr) +					unit->intr(unit); +				stat &= ~map->stat; +			} +			map++; +		} + +		if (stat) +			nv_error(pmc, "unknown intr 0x%08x\n", stat);  	} -	if (stat == IRQ_HANDLED) -		pm_runtime_mark_last_busy(&device->pdev->dev); -	return stat ? IRQ_HANDLED : IRQ_NONE; +	nv_wr32(pmc, 0x000140, 0x00000001); +	return intr ? IRQ_HANDLED : IRQ_NONE;  }  int @@ -83,7 +93,7 @@ _nouveau_mc_dtor(struct nouveau_object *object)  {  	struct nouveau_device *device = nv_device(object);  	struct nouveau_mc *pmc = (void *)object; -	free_irq(device->pdev->irq, pmc); +	free_irq(pmc->irq, pmc);  	if (pmc->use_msi)  		pci_disable_msi(device->pdev);  	nouveau_subdev_destroy(&pmc->base); @@ -91,41 +101,57 @@ _nouveau_mc_dtor(struct nouveau_object *object)  int  nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, -		   struct nouveau_oclass *oclass, -		   const struct nouveau_mc_intr *intr_map, -		   int length, void **pobject) +		   struct nouveau_oclass *bclass, int length, void **pobject)  { +	const struct nouveau_mc_oclass *oclass = (void *)bclass;  	struct nouveau_device *device = nv_device(parent);  	struct nouveau_mc *pmc;  	int ret; -	ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PMC", +	ret = nouveau_subdev_create_(parent, engine, bclass, 0, "PMC",  				     "master", length, pobject);  	pmc = *pobject;  	if (ret)  		return ret; -	pmc->intr_map = intr_map; +	if (nv_device_is_pci(device)) +		switch (device->pdev->device & 0x0ff0) { +		case 0x00f0: +		case 0x02e0: +			/* BR02? NFI how these would be handled yet exactly */ +			break; +		default: +			switch (device->chipset) { +			case 0xaa: +				/* reported broken, nv also disable it */ +				break; +			default: +				pmc->use_msi = true; +				break; +		} + +		pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", +					       pmc->use_msi); -	switch (device->pdev->device & 0x0ff0) { -	case 0x00f0: /* BR02? */ -	case 0x02e0: /* BR02? */ -		pmc->use_msi = false; -		break; -	default: -		pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", true); -		if (pmc->use_msi) { +		if (pmc->use_msi && oclass->msi_rearm) {  			pmc->use_msi = pci_enable_msi(device->pdev) == 0;  			if (pmc->use_msi) {  				nv_info(pmc, "MSI interrupts enabled\n"); -				nv_wr08(device, 0x00088068, 0xff); +				oclass->msi_rearm(pmc);  			} +		} else { +			pmc->use_msi = false;  		} -		break;  	} -	ret = request_irq(device->pdev->irq, nouveau_mc_intr, -			  IRQF_SHARED, "nouveau", pmc); +	ret = nv_device_get_irq(device, true); +	if (ret < 0) +		return ret; +	pmc->irq = ret; + +	ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau", +			  pmc); +  	if (ret < 0)  		return ret; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c index 64aa4edb0d9..2d787e4dfef 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c @@ -22,17 +22,14 @@   * Authors: Ben Skeggs   */ -#include <subdev/mc.h> - -struct nv04_mc_priv { -	struct nouveau_mc base; -}; +#include "nv04.h"  const struct nouveau_mc_intr  nv04_mc_intr[] = {  	{ 0x00000001, NVDEV_ENGINE_MPEG },	/* NV17- MPEG/ME */  	{ 0x00000100, NVDEV_ENGINE_FIFO },  	{ 0x00001000, NVDEV_ENGINE_GR }, +	{ 0x00010000, NVDEV_ENGINE_DISP },  	{ 0x00020000, NVDEV_ENGINE_VP },	/* NV40- */  	{ 0x00100000, NVDEV_SUBDEV_TIMER },  	{ 0x01000000, NVDEV_ENGINE_DISP },	/* NV04- PCRTC0 */ @@ -42,7 +39,18 @@ nv04_mc_intr[] = {  	{}  }; -static int +int +nv04_mc_init(struct nouveau_object *object) +{ +	struct nv04_mc_priv *priv = (void *)object; + +	nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ +	nv_wr32(priv, 0x001850, 0x00000001); /* disable rom access */ + +	return nouveau_mc_init(&priv->base); +} + +int  nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	     struct nouveau_oclass *oclass, void *data, u32 size,  	     struct nouveau_object **pobject) @@ -50,7 +58,7 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nv04_mc_priv *priv;  	int ret; -	ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv); +	ret = nouveau_mc_create(parent, engine, oclass, &priv);  	*pobject = nv_object(priv);  	if (ret)  		return ret; @@ -58,24 +66,14 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	return 0;  } -int -nv04_mc_init(struct nouveau_object *object) -{ -	struct nv04_mc_priv *priv = (void *)object; - -	nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ -	nv_wr32(priv, 0x001850, 0x00000001); /* disable rom access */ - -	return nouveau_mc_init(&priv->base); -} - -struct nouveau_oclass -nv04_mc_oclass = { -	.handle = NV_SUBDEV(MC, 0x04), -	.ofuncs = &(struct nouveau_ofuncs) { +struct nouveau_oclass * +nv04_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x04), +	.base.ofuncs = &(struct nouveau_ofuncs) {  		.ctor = nv04_mc_ctor,  		.dtor = _nouveau_mc_dtor,  		.init = nv04_mc_init,  		.fini = _nouveau_mc_fini,  	}, -}; +	.intr = nv04_mc_intr, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h new file mode 100644 index 00000000000..81a408e7d03 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.h @@ -0,0 +1,22 @@ +#ifndef __NVKM_MC_NV04_H__ +#define __NVKM_MC_NV04_H__ + +#include <subdev/mc.h> + +struct nv04_mc_priv { +	struct nouveau_mc base; +}; + +int  nv04_mc_ctor(struct nouveau_object *, struct nouveau_object *, +		  struct nouveau_oclass *, void *, u32, +		  struct nouveau_object **); + +extern const struct nouveau_mc_intr nv04_mc_intr[]; +int  nv04_mc_init(struct nouveau_object *); +void nv40_mc_msi_rearm(struct nouveau_mc *); +int  nv44_mc_init(struct nouveau_object *object); +int  nv50_mc_init(struct nouveau_object *); +extern const struct nouveau_mc_intr nv50_mc_intr[]; +extern const struct nouveau_mc_intr nvc0_mc_intr[]; + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c new file mode 100644 index 00000000000..5b1faecfed2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv40.c @@ -0,0 +1,45 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv04.h" + +void +nv40_mc_msi_rearm(struct nouveau_mc *pmc) +{ +	struct nv04_mc_priv *priv = (void *)pmc; +	nv_wr08(priv, 0x088068, 0xff); +} + +struct nouveau_oclass * +nv40_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x40), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor, +		.dtor = _nouveau_mc_dtor, +		.init = nv04_mc_init, +		.fini = _nouveau_mc_fini, +	}, +	.intr = nv04_mc_intr, +	.msi_rearm = nv40_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index d9891782bf2..cc4d0d2d886 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c @@ -22,32 +22,12 @@   * Authors: Ben Skeggs   */ -#include <subdev/mc.h> +#include "nv04.h" -struct nv44_mc_priv { -	struct nouveau_mc base; -}; - -static int -nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv44_mc_priv *priv; -	int ret; - -	ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -static int +int  nv44_mc_init(struct nouveau_object *object)  { -	struct nv44_mc_priv *priv = (void *)object; +	struct nv04_mc_priv *priv = (void *)object;  	u32 tmp = nv_rd32(priv, 0x10020c);  	nv_wr32(priv, 0x000200, 0xffffffff); /* everything enabled */ @@ -60,13 +40,15 @@ nv44_mc_init(struct nouveau_object *object)  	return nouveau_mc_init(&priv->base);  } -struct nouveau_oclass -nv44_mc_oclass = { -	.handle = NV_SUBDEV(MC, 0x44), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv44_mc_ctor, +struct nouveau_oclass * +nv44_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x44), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor,  		.dtor = _nouveau_mc_dtor,  		.init = nv44_mc_init,  		.fini = _nouveau_mc_fini,  	}, -}; +	.intr = nv04_mc_intr, +	.msi_rearm = nv40_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c new file mode 100644 index 00000000000..a75c35ccf25 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c @@ -0,0 +1,45 @@ +/* + * Copyright 2014 Ilia Mirkin + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ilia Mirkin + */ + +#include "nv04.h" + +static void +nv4c_mc_msi_rearm(struct nouveau_mc *pmc) +{ +	struct nv04_mc_priv *priv = (void *)pmc; +	nv_wr08(priv, 0x088050, 0xff); +} + +struct nouveau_oclass * +nv4c_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x4c), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor, +		.dtor = _nouveau_mc_dtor, +		.init = nv44_mc_init, +		.fini = _nouveau_mc_fini, +	}, +	.intr = nv04_mc_intr, +	.msi_rearm = nv4c_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index 2b1afe225db..9ca93e2718f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c @@ -22,14 +22,11 @@   * Authors: Ben Skeggs   */ -#include <subdev/mc.h> +#include "nv04.h" -struct nv50_mc_priv { -	struct nouveau_mc base; -}; - -static const struct nouveau_mc_intr +const struct nouveau_mc_intr  nv50_mc_intr[] = { +	{ 0x04000000, NVDEV_ENGINE_DISP },  /* DISP before FIFO, so pageflip-timestamping works! */  	{ 0x00000001, NVDEV_ENGINE_MPEG },  	{ 0x00000100, NVDEV_ENGINE_FIFO },  	{ 0x00001000, NVDEV_ENGINE_GR }, @@ -37,45 +34,38 @@ nv50_mc_intr[] = {  	{ 0x00008000, NVDEV_ENGINE_BSP },	/* NV84- */  	{ 0x00020000, NVDEV_ENGINE_VP },	/* NV84- */  	{ 0x00100000, NVDEV_SUBDEV_TIMER }, -	{ 0x00200000, NVDEV_SUBDEV_GPIO }, -	{ 0x04000000, NVDEV_ENGINE_DISP }, +	{ 0x00200000, NVDEV_SUBDEV_GPIO },	/* PMGR->GPIO */ +	{ 0x00200000, NVDEV_SUBDEV_I2C }, 	/* PMGR->I2C/AUX */  	{ 0x10000000, NVDEV_SUBDEV_BUS },  	{ 0x80000000, NVDEV_ENGINE_SW },  	{ 0x0002d101, NVDEV_SUBDEV_FB },  	{},  }; -static int -nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) +static void +nv50_mc_msi_rearm(struct nouveau_mc *pmc)  { -	struct nv50_mc_priv *priv; -	int ret; - -	ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; +	struct nouveau_device *device = nv_device(pmc); +	pci_write_config_byte(device->pdev, 0x68, 0xff);  }  int  nv50_mc_init(struct nouveau_object *object)  { -	struct nv50_mc_priv *priv = (void *)object; +	struct nv04_mc_priv *priv = (void *)object;  	nv_wr32(priv, 0x000200, 0xffffffff); /* everything on */  	return nouveau_mc_init(&priv->base);  } -struct nouveau_oclass -nv50_mc_oclass = { -	.handle = NV_SUBDEV(MC, 0x50), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv50_mc_ctor, +struct nouveau_oclass * +nv50_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x50), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor,  		.dtor = _nouveau_mc_dtor,  		.init = nv50_mc_init,  		.fini = _nouveau_mc_fini,  	}, -}; +	.intr = nv50_mc_intr, +	.msi_rearm = nv50_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv94.c new file mode 100644 index 00000000000..5f4541105e7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv94.c @@ -0,0 +1,38 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv04.h" + +struct nouveau_oclass * +nv94_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x94), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor, +		.dtor = _nouveau_mc_dtor, +		.init = nv50_mc_init, +		.fini = _nouveau_mc_fini, +	}, +	.intr = nv50_mc_intr, +	.msi_rearm = nv40_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index 06710419a59..3c76d9038f3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c @@ -22,54 +22,38 @@   * Authors: Ben Skeggs   */ -#include <subdev/mc.h> - -struct nv98_mc_priv { -	struct nouveau_mc base; -}; +#include "nv04.h"  static const struct nouveau_mc_intr  nv98_mc_intr[] = { +	{ 0x04000000, NVDEV_ENGINE_DISP },  /* DISP first, so pageflip timestamps work */  	{ 0x00000001, NVDEV_ENGINE_PPP },  	{ 0x00000100, NVDEV_ENGINE_FIFO },  	{ 0x00001000, NVDEV_ENGINE_GR },  	{ 0x00004000, NVDEV_ENGINE_CRYPT },	/* NV84:NVA3 */  	{ 0x00008000, NVDEV_ENGINE_BSP },  	{ 0x00020000, NVDEV_ENGINE_VP }, +	{ 0x00040000, NVDEV_SUBDEV_PWR },	/* NVA3:NVC0 */  	{ 0x00080000, NVDEV_SUBDEV_THERM },	/* NVA3:NVC0 */  	{ 0x00100000, NVDEV_SUBDEV_TIMER }, -	{ 0x00200000, NVDEV_SUBDEV_GPIO }, +	{ 0x00200000, NVDEV_SUBDEV_GPIO },	/* PMGR->GPIO */ +	{ 0x00200000, NVDEV_SUBDEV_I2C }, 	/* PMGR->I2C/AUX */  	{ 0x00400000, NVDEV_ENGINE_COPY0 },	/* NVA3-     */ -	{ 0x04000000, NVDEV_ENGINE_DISP },  	{ 0x10000000, NVDEV_SUBDEV_BUS },  	{ 0x80000000, NVDEV_ENGINE_SW },  	{ 0x0042d101, NVDEV_SUBDEV_FB },  	{},  }; -static int -nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) -{ -	struct nv98_mc_priv *priv; -	int ret; - -	ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; -} - -struct nouveau_oclass -nv98_mc_oclass = { -	.handle = NV_SUBDEV(MC, 0x98), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nv98_mc_ctor, +struct nouveau_oclass * +nv98_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0x98), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor,  		.dtor = _nouveau_mc_dtor,  		.init = nv50_mc_init,  		.fini = _nouveau_mc_fini,  	}, -}; +	.intr = nv98_mc_intr, +	.msi_rearm = nv40_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 104175c5a2d..f9c6a678b47 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -22,56 +22,49 @@   * Authors: Ben Skeggs   */ -#include <subdev/mc.h> +#include "nv04.h" -struct nvc0_mc_priv { -	struct nouveau_mc base; -}; - -static const struct nouveau_mc_intr +const struct nouveau_mc_intr  nvc0_mc_intr[] = { +	{ 0x04000000, NVDEV_ENGINE_DISP },  /* DISP first, so pageflip timestamps work. */  	{ 0x00000001, NVDEV_ENGINE_PPP },  	{ 0x00000020, NVDEV_ENGINE_COPY0 },  	{ 0x00000040, NVDEV_ENGINE_COPY1 },  	{ 0x00000080, NVDEV_ENGINE_COPY2 },  	{ 0x00000100, NVDEV_ENGINE_FIFO },  	{ 0x00001000, NVDEV_ENGINE_GR }, +	{ 0x00002000, NVDEV_SUBDEV_FB },  	{ 0x00008000, NVDEV_ENGINE_BSP },  	{ 0x00040000, NVDEV_SUBDEV_THERM },  	{ 0x00020000, NVDEV_ENGINE_VP },  	{ 0x00100000, NVDEV_SUBDEV_TIMER }, -	{ 0x00200000, NVDEV_SUBDEV_GPIO }, +	{ 0x00200000, NVDEV_SUBDEV_GPIO },	/* PMGR->GPIO */ +	{ 0x00200000, NVDEV_SUBDEV_I2C },	/* PMGR->I2C/AUX */ +	{ 0x01000000, NVDEV_SUBDEV_PWR },  	{ 0x02000000, NVDEV_SUBDEV_LTCG }, -	{ 0x04000000, NVDEV_ENGINE_DISP }, +	{ 0x08000000, NVDEV_SUBDEV_FB },  	{ 0x10000000, NVDEV_SUBDEV_BUS },  	{ 0x40000000, NVDEV_SUBDEV_IBUS },  	{ 0x80000000, NVDEV_ENGINE_SW },  	{},  }; -static int -nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -	     struct nouveau_oclass *oclass, void *data, u32 size, -	     struct nouveau_object **pobject) +static void +nvc0_mc_msi_rearm(struct nouveau_mc *pmc)  { -	struct nvc0_mc_priv *priv; -	int ret; - -	ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	return 0; +	struct nv04_mc_priv *priv = (void *)pmc; +	nv_wr32(priv, 0x088704, 0x00000000);  } -struct nouveau_oclass -nvc0_mc_oclass = { -	.handle = NV_SUBDEV(MC, 0xc0), -	.ofuncs = &(struct nouveau_ofuncs) { -		.ctor = nvc0_mc_ctor, +struct nouveau_oclass * +nvc0_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0xc0), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor,  		.dtor = _nouveau_mc_dtor,  		.init = nv50_mc_init,  		.fini = _nouveau_mc_fini,  	}, -}; +	.intr = nvc0_mc_intr, +	.msi_rearm = nvc0_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c new file mode 100644 index 00000000000..837e545aeb9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc3.c @@ -0,0 +1,38 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv04.h" + +struct nouveau_oclass * +nvc3_mc_oclass = &(struct nouveau_mc_oclass) { +	.base.handle = NV_SUBDEV(MC, 0xc3), +	.base.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_mc_ctor, +		.dtor = _nouveau_mc_dtor, +		.init = nv50_mc_init, +		.fini = _nouveau_mc_fini, +	}, +	.intr = nvc0_mc_intr, +	.msi_rearm = nv40_mc_msi_rearm, +}.base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c index e286e132c7e..51fcf796041 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/base.c @@ -87,55 +87,39 @@ mxm_shadow_dsm(struct nouveau_mxm *mxm, u8 version)  		0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65  	};  	u32 mxms_args[] = { 0x00000000 }; -	union acpi_object args[4] = { -		/* _DSM MUID */ -		{ .buffer.type = 3, -		  .buffer.length = sizeof(muid), -		  .buffer.pointer = muid, -		}, -		/* spec says this can be zero to mean "highest revision", but -		 * of course there's at least one bios out there which fails -		 * unless you pass in exactly the version it supports.. -		 */ -		{ .integer.type = ACPI_TYPE_INTEGER, -		  .integer.value = (version & 0xf0) << 4 | (version & 0x0f), -		}, -		/* MXMS function */ -		{ .integer.type = ACPI_TYPE_INTEGER, -		  .integer.value = 0x00000010, -		}, -		/* Pointer to MXMS arguments */ -		{ .buffer.type = ACPI_TYPE_BUFFER, -		  .buffer.length = sizeof(mxms_args), -		  .buffer.pointer = (char *)mxms_args, -		}, +	union acpi_object argv4 = { +		.buffer.type = ACPI_TYPE_BUFFER, +		.buffer.length = sizeof(mxms_args), +		.buffer.pointer = (char *)mxms_args,  	}; -	struct acpi_object_list list = { ARRAY_SIZE(args), args }; -	struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL };  	union acpi_object *obj;  	acpi_handle handle; -	int ret; +	int rev; -	handle = DEVICE_ACPI_HANDLE(&device->pdev->dev); +	handle = ACPI_HANDLE(nv_device_base(device));  	if (!handle)  		return false; -	ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); -	if (ret) { -		nv_debug(mxm, "DSM MXMS failed: %d\n", ret); +	/* +	 * spec says this can be zero to mean "highest revision", but +	 * of course there's at least one bios out there which fails +	 * unless you pass in exactly the version it supports.. +	 */ +	rev = (version & 0xf0) << 4 | (version & 0x0f); +	obj = acpi_evaluate_dsm(handle, muid, rev, 0x00000010, &argv4); +	if (!obj) { +		nv_debug(mxm, "DSM MXMS failed\n");  		return false;  	} -	obj = retn.pointer;  	if (obj->type == ACPI_TYPE_BUFFER) {  		mxm->mxms = kmemdup(obj->buffer.pointer,  					 obj->buffer.length, GFP_KERNEL); -	} else -	if (obj->type == ACPI_TYPE_INTEGER) { +	} else if (obj->type == ACPI_TYPE_INTEGER) {  		nv_debug(mxm, "DSM MXMS returned 0x%llx\n", obj->integer.value);  	} -	kfree(obj); +	ACPI_FREE(obj);  	return mxm->mxms != NULL;  }  #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c index af129c2e811..fcaabe8456e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c @@ -100,7 +100,7 @@ mxm_match_dcb(struct nouveau_mxm *mxm, u8 *data, void *info)  static int  mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)  { -	struct nouveau_mxm *mxm = nouveau_mxm(bios); +	struct nouveau_mxm *mxm = data;  	struct context ctx = { .outp = (u32 *)(bios->data + pdcb) };  	u8 type, i2cidx, link, ver, len;  	u8 *conn; @@ -150,7 +150,7 @@ mxm_dcb_sanitise_entry(struct nouveau_bios *bios, void *data, int idx, u16 pdcb)  	 * common example is DP->eDP.  	 */  	conn  = bios->data; -	conn += dcb_conn(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len); +	conn += nvbios_connEe(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len);  	type  = conn[0];  	switch (ctx.desc.conn_type) {  	case 0x01: /* LVDS */ @@ -199,7 +199,7 @@ mxm_dcb_sanitise(struct nouveau_mxm *mxm)  		return;  	} -	dcb_outp_foreach(bios, NULL, mxm_dcb_sanitise_entry); +	dcb_outp_foreach(bios, mxm, mxm_dcb_sanitise_entry);  	mxms_foreach(mxm, 0x01, mxm_show_unmatched, NULL);  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c new file mode 100644 index 00000000000..d4fd3bc9c66 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/base.c @@ -0,0 +1,247 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/pwr.h> +#include <subdev/timer.h> + +static int +nouveau_pwr_send(struct nouveau_pwr *ppwr, u32 reply[2], +		 u32 process, u32 message, u32 data0, u32 data1) +{ +	struct nouveau_subdev *subdev = nv_subdev(ppwr); +	u32 addr; + +	/* wait for a free slot in the fifo */ +	addr  = nv_rd32(ppwr, 0x10a4a0); +	if (!nv_wait_ne(ppwr, 0x10a4b0, 0xffffffff, addr ^ 8)) +		return -EBUSY; + +	/* we currently only support a single process at a time waiting +	 * on a synchronous reply, take the PPWR mutex and tell the +	 * receive handler what we're waiting for +	 */ +	if (reply) { +		mutex_lock(&subdev->mutex); +		ppwr->recv.message = message; +		ppwr->recv.process = process; +	} + +	/* acquire data segment access */ +	do { +		nv_wr32(ppwr, 0x10a580, 0x00000001); +	} while (nv_rd32(ppwr, 0x10a580) != 0x00000001); + +	/* write the packet */ +	nv_wr32(ppwr, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) + +				ppwr->send.base)); +	nv_wr32(ppwr, 0x10a1c4, process); +	nv_wr32(ppwr, 0x10a1c4, message); +	nv_wr32(ppwr, 0x10a1c4, data0); +	nv_wr32(ppwr, 0x10a1c4, data1); +	nv_wr32(ppwr, 0x10a4a0, (addr + 1) & 0x0f); + +	/* release data segment access */ +	nv_wr32(ppwr, 0x10a580, 0x00000000); + +	/* wait for reply, if requested */ +	if (reply) { +		wait_event(ppwr->recv.wait, (ppwr->recv.process == 0)); +		reply[0] = ppwr->recv.data[0]; +		reply[1] = ppwr->recv.data[1]; +		mutex_unlock(&subdev->mutex); +	} + +	return 0; +} + +static void +nouveau_pwr_recv(struct work_struct *work) +{ +	struct nouveau_pwr *ppwr = +		container_of(work, struct nouveau_pwr, recv.work); +	u32 process, message, data0, data1; + +	/* nothing to do if GET == PUT */ +	u32 addr =  nv_rd32(ppwr, 0x10a4cc); +	if (addr == nv_rd32(ppwr, 0x10a4c8)) +		return; + +	/* acquire data segment access */ +	do { +		nv_wr32(ppwr, 0x10a580, 0x00000002); +	} while (nv_rd32(ppwr, 0x10a580) != 0x00000002); + +	/* read the packet */ +	nv_wr32(ppwr, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) + +				ppwr->recv.base)); +	process = nv_rd32(ppwr, 0x10a1c4); +	message = nv_rd32(ppwr, 0x10a1c4); +	data0   = nv_rd32(ppwr, 0x10a1c4); +	data1   = nv_rd32(ppwr, 0x10a1c4); +	nv_wr32(ppwr, 0x10a4cc, (addr + 1) & 0x0f); + +	/* release data segment access */ +	nv_wr32(ppwr, 0x10a580, 0x00000000); + +	/* wake process if it's waiting on a synchronous reply */ +	if (ppwr->recv.process) { +		if (process == ppwr->recv.process && +		    message == ppwr->recv.message) { +			ppwr->recv.data[0] = data0; +			ppwr->recv.data[1] = data1; +			ppwr->recv.process = 0; +			wake_up(&ppwr->recv.wait); +			return; +		} +	} + +	/* right now there's no other expected responses from the engine, +	 * so assume that any unexpected message is an error. +	 */ +	nv_warn(ppwr, "%c%c%c%c 0x%08x 0x%08x 0x%08x 0x%08x\n", +		(char)((process & 0x000000ff) >>  0), +		(char)((process & 0x0000ff00) >>  8), +		(char)((process & 0x00ff0000) >> 16), +		(char)((process & 0xff000000) >> 24), +		process, message, data0, data1); +} + +static void +nouveau_pwr_intr(struct nouveau_subdev *subdev) +{ +	struct nouveau_pwr *ppwr = (void *)subdev; +	u32 disp = nv_rd32(ppwr, 0x10a01c); +	u32 intr = nv_rd32(ppwr, 0x10a008) & disp & ~(disp >> 16); + +	if (intr & 0x00000020) { +		u32 stat = nv_rd32(ppwr, 0x10a16c); +		if (stat & 0x80000000) { +			nv_error(ppwr, "UAS fault at 0x%06x addr 0x%08x\n", +				 stat & 0x00ffffff, nv_rd32(ppwr, 0x10a168)); +			nv_wr32(ppwr, 0x10a16c, 0x00000000); +			intr &= ~0x00000020; +		} +	} + +	if (intr & 0x00000040) { +		schedule_work(&ppwr->recv.work); +		nv_wr32(ppwr, 0x10a004, 0x00000040); +		intr &= ~0x00000040; +	} + +	if (intr & 0x00000080) { +		nv_info(ppwr, "wr32 0x%06x 0x%08x\n", nv_rd32(ppwr, 0x10a7a0), +						      nv_rd32(ppwr, 0x10a7a4)); +		nv_wr32(ppwr, 0x10a004, 0x00000080); +		intr &= ~0x00000080; +	} + +	if (intr) { +		nv_error(ppwr, "intr 0x%08x\n", intr); +		nv_wr32(ppwr, 0x10a004, intr); +	} +} + +int +_nouveau_pwr_fini(struct nouveau_object *object, bool suspend) +{ +	struct nouveau_pwr *ppwr = (void *)object; + +	nv_wr32(ppwr, 0x10a014, 0x00000060); +	flush_work(&ppwr->recv.work); + +	return nouveau_subdev_fini(&ppwr->base, suspend); +} + +int +_nouveau_pwr_init(struct nouveau_object *object) +{ +	struct nouveau_pwr *ppwr = (void *)object; +	int ret, i; + +	ret = nouveau_subdev_init(&ppwr->base); +	if (ret) +		return ret; + +	nv_subdev(ppwr)->intr = nouveau_pwr_intr; +	ppwr->message = nouveau_pwr_send; + +	/* prevent previous ucode from running, wait for idle, reset */ +	nv_wr32(ppwr, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */ +	nv_wait(ppwr, 0x10a04c, 0xffffffff, 0x00000000); +	nv_mask(ppwr, 0x000200, 0x00002000, 0x00000000); +	nv_mask(ppwr, 0x000200, 0x00002000, 0x00002000); + +	/* upload data segment */ +	nv_wr32(ppwr, 0x10a1c0, 0x01000000); +	for (i = 0; i < ppwr->data.size / 4; i++) +		nv_wr32(ppwr, 0x10a1c4, ppwr->data.data[i]); + +	/* upload code segment */ +	nv_wr32(ppwr, 0x10a180, 0x01000000); +	for (i = 0; i < ppwr->code.size / 4; i++) { +		if ((i & 0x3f) == 0) +			nv_wr32(ppwr, 0x10a188, i >> 6); +		nv_wr32(ppwr, 0x10a184, ppwr->code.data[i]); +	} + +	/* start it running */ +	nv_wr32(ppwr, 0x10a10c, 0x00000000); +	nv_wr32(ppwr, 0x10a104, 0x00000000); +	nv_wr32(ppwr, 0x10a100, 0x00000002); + +	/* wait for valid host->pwr ring configuration */ +	if (!nv_wait_ne(ppwr, 0x10a4d0, 0xffffffff, 0x00000000)) +		return -EBUSY; +	ppwr->send.base = nv_rd32(ppwr, 0x10a4d0) & 0x0000ffff; +	ppwr->send.size = nv_rd32(ppwr, 0x10a4d0) >> 16; + +	/* wait for valid pwr->host ring configuration */ +	if (!nv_wait_ne(ppwr, 0x10a4dc, 0xffffffff, 0x00000000)) +		return -EBUSY; +	ppwr->recv.base = nv_rd32(ppwr, 0x10a4dc) & 0x0000ffff; +	ppwr->recv.size = nv_rd32(ppwr, 0x10a4dc) >> 16; + +	nv_wr32(ppwr, 0x10a010, 0x000000e0); +	return 0; +} + +int +nouveau_pwr_create_(struct nouveau_object *parent, +		    struct nouveau_object *engine, +		    struct nouveau_oclass *oclass, int length, void **pobject) +{ +	struct nouveau_pwr *ppwr; +	int ret; + +	ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PPWR", +				     "pwr", length, pobject); +	ppwr = *pobject; +	if (ret) +		return ret; + +	INIT_WORK(&ppwr->recv.work, nouveau_pwr_recv); +	init_waitqueue_head(&ppwr->recv.wait); +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/host.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/host.fuc new file mode 100644 index 00000000000..c2bb616a8da --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/host.fuc @@ -0,0 +1,151 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifdef INCLUDE_PROC +process(PROC_HOST, #host_init, #host_recv) +#endif + +/****************************************************************************** + * HOST data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +// HOST (R)FIFO packet format +.equ #fifo_process 0x00 +.equ #fifo_message 0x04 +.equ #fifo_data0   0x08 +.equ #fifo_data1   0x0c + +// HOST HOST->PWR queue description +.equ #fifo_qlen 4 // log2(size of queue entry in bytes) +.equ #fifo_qnum 3 // log2(max number of entries in queue) +.equ #fifo_qmaskb (1 << #fifo_qnum) // max number of entries in queue +.equ #fifo_qmaskp (#fifo_qmaskb - 1) +.equ #fifo_qmaskf ((#fifo_qmaskb << 1) - 1) +.equ #fifo_qsize  (1 << (#fifo_qlen + #fifo_qnum)) +fifo_queue: .skip 128 // #fifo_qsize + +// HOST PWR->HOST queue description +.equ #rfifo_qlen 4 // log2(size of queue entry in bytes) +.equ #rfifo_qnum 3 // log2(max number of entries in queue) +.equ #rfifo_qmaskb (1 << #rfifo_qnum) // max number of entries in queue +.equ #rfifo_qmaskp (#rfifo_qmaskb - 1) +.equ #rfifo_qmaskf ((#rfifo_qmaskb << 1) - 1) +.equ #rfifo_qsize  (1 << (#rfifo_qlen + #rfifo_qnum)) +rfifo_queue: .skip 128 // #rfifo_qsize +#endif + +/****************************************************************************** + * HOST code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE +// HOST->PWR comms - dequeue message(s) for process(es) from FIFO +// +// $r15 - current (host) +// $r0  - zero +host_send: +	nv_iord($r1, NV_PPWR_FIFO_GET(0)) +	nv_iord($r2, NV_PPWR_FIFO_PUT(0)) +	cmp b32 $r1 $r2 +	bra e #host_send_done +		// calculate address of message +		and $r14 $r1 #fifo_qmaskp +		shl b32 $r14 $r14 #fifo_qlen +		add b32 $r14 #fifo_queue + +		// read message data, and pass to appropriate process +		ld b32 $r11 D[$r14 + #fifo_data1] +		ld b32 $r12 D[$r14 + #fifo_data0] +		ld b32 $r13 D[$r14 + #fifo_message] +		ld b32 $r14 D[$r14 + #fifo_process] +		call(send) + +		// increment GET +		add b32 $r1 0x1 +		and $r14 $r1 #fifo_qmaskf +		nv_iowr(NV_PPWR_FIFO_GET(0), $r14) +		bra #host_send +	host_send_done: +	ret + +// PWR->HOST comms - enqueue message for HOST to RFIFO +// +// $r15 - current (host) +// $r14 - process +// $r13 - message +// $r12 - message data 0 +// $r11 - message data 1 +// $r0  - zero +host_recv: +	// message from intr handler == HOST->PWR comms pending +	mov $r1 (PROC_KERN & 0x0000ffff) +	sethi $r1 (PROC_KERN & 0xffff0000) +	cmp b32 $r14 $r1 +	bra e #host_send + +	// wait for space in RFIFO +	host_recv_wait: +	nv_iord($r1, NV_PPWR_RFIFO_GET) +	nv_iord($r2, NV_PPWR_RFIFO_PUT) +	xor $r1 #rfifo_qmaskb +	cmp b32 $r1 $r2 +	bra e #host_recv_wait + +	and $r3 $r2 #rfifo_qmaskp +	shl b32 $r3 #rfifo_qlen +	add b32 $r3 #rfifo_queue + +	// enqueue message +	st b32 D[$r3 + #fifo_data1] $r11 +	st b32 D[$r3 + #fifo_data0] $r12 +	st b32 D[$r3 + #fifo_message] $r13 +	st b32 D[$r3 + #fifo_process] $r14 + +	add b32 $r2 0x1 +	and $r2 #rfifo_qmaskf +	nv_iowr(NV_PPWR_RFIFO_PUT, $r2) + +	// notify host of pending message +	mov $r2 NV_PPWR_INTR_TRIGGER_USER0 +	nv_iowr(NV_PPWR_INTR_TRIGGER, $r2) +	ret + +// $r15 - current (host) +// $r0  - zero +host_init: +	// store each fifo's base/size in H2D/D2H scratch regs +	mov $r1 #fifo_qsize +	shl b32 $r1 16 +	or $r1 #fifo_queue +	nv_iowr(NV_PPWR_H2D, $r1); + +	mov $r1 #rfifo_qsize +	shl b32 $r1 16 +	or $r1 #rfifo_queue +	nv_iowr(NV_PPWR_D2H, $r1); + +	// enable fifo subintr for first fifo +	mov $r1 1 +	nv_iowr(NV_PPWR_FIFO_INTR_EN, $r1) +	ret +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc new file mode 100644 index 00000000000..757dda70002 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/i2c_.fuc @@ -0,0 +1,393 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#define T_TIMEOUT  2200000 +#define T_RISEFALL 1000 +#define T_HOLD     5000 + +#ifdef INCLUDE_PROC +process(PROC_I2C_, #i2c_init, #i2c_recv) +#endif + +/****************************************************************************** + * I2C_ data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +i2c_scl_map: +.b32 NV_PPWR_OUTPUT_I2C_0_SCL +.b32 NV_PPWR_OUTPUT_I2C_1_SCL +.b32 NV_PPWR_OUTPUT_I2C_2_SCL +.b32 NV_PPWR_OUTPUT_I2C_3_SCL +.b32 NV_PPWR_OUTPUT_I2C_4_SCL +.b32 NV_PPWR_OUTPUT_I2C_5_SCL +.b32 NV_PPWR_OUTPUT_I2C_6_SCL +.b32 NV_PPWR_OUTPUT_I2C_7_SCL +.b32 NV_PPWR_OUTPUT_I2C_8_SCL +.b32 NV_PPWR_OUTPUT_I2C_9_SCL +i2c_sda_map: +.b32 NV_PPWR_OUTPUT_I2C_0_SDA +.b32 NV_PPWR_OUTPUT_I2C_1_SDA +.b32 NV_PPWR_OUTPUT_I2C_2_SDA +.b32 NV_PPWR_OUTPUT_I2C_3_SDA +.b32 NV_PPWR_OUTPUT_I2C_4_SDA +.b32 NV_PPWR_OUTPUT_I2C_5_SDA +.b32 NV_PPWR_OUTPUT_I2C_6_SDA +.b32 NV_PPWR_OUTPUT_I2C_7_SDA +.b32 NV_PPWR_OUTPUT_I2C_8_SDA +.b32 NV_PPWR_OUTPUT_I2C_9_SDA +#if NVKM_PPWR_CHIPSET < GF119 +i2c_ctrl: +.b32 0x00e138 +.b32 0x00e150 +.b32 0x00e168 +.b32 0x00e180 +.b32 0x00e254 +.b32 0x00e274 +.b32 0x00e764 +.b32 0x00e780 +.b32 0x00e79c +.b32 0x00e7b8 +#endif +#endif + +/****************************************************************************** + * I2C_ code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE + +// $r3  - value +// $r2  - sda line +// $r1  - scl line +// $r0  - zero +i2c_drive_scl: +	cmp b32 $r3 0 +	bra e #i2c_drive_scl_lo +	nv_iowr(NV_PPWR_OUTPUT_SET, $r1) +	ret +	i2c_drive_scl_lo: +	nv_iowr(NV_PPWR_OUTPUT_CLR, $r1) +	ret + +i2c_drive_sda: +	cmp b32 $r3 0 +	bra e #i2c_drive_sda_lo +	nv_iowr(NV_PPWR_OUTPUT_SET, $r2) +	ret +	i2c_drive_sda_lo: +	nv_iowr(NV_PPWR_OUTPUT_CLR, $r2) +	ret + +i2c_sense_scl: +	bclr $flags $p1 +	nv_iord($r3, NV_PPWR_INPUT) +	and $r3 $r1 +	bra z #i2c_sense_scl_done +		bset $flags $p1 +	i2c_sense_scl_done: +	ret + +i2c_sense_sda: +	bclr $flags $p1 +	nv_iord($r3, NV_PPWR_INPUT) +	and $r3 $r2 +	bra z #i2c_sense_sda_done +		bset $flags $p1 +	i2c_sense_sda_done: +	ret + +#define i2c_drive_scl(v) /* +*/	mov $r3 (v) /* +*/	call(i2c_drive_scl) +#define i2c_drive_sda(v) /* +*/	mov $r3 (v) /* +*/	call(i2c_drive_sda) +#define i2c_sense_scl() /* +*/	call(i2c_sense_scl) +#define i2c_sense_sda() /* +*/	call(i2c_sense_sda) +#define i2c_delay(v) /* +*/	mov $r14 (v) /* +*/	call(nsec) + +#define i2c_trace_init() /* +*/	imm32($r6, 0x10000000) /* +*/	sub b32 $r7 $r6 1 /* +*/ +#define i2c_trace_down() /* +*/	shr b32 $r6 4 /* +*/	push $r5 /* +*/	shl b32 $r5 $r6 4 /* +*/	sub b32 $r5 $r6 /* +*/	not b32 $r5 /* +*/	and $r7 $r5 /* +*/	pop $r5 /* +*/ +#define i2c_trace_exit() /* +*/	shl b32 $r6 4 /* +*/ +#define i2c_trace_next() /* +*/	add b32 $r7 $r6 /* +*/ +#define i2c_trace_call(func) /* +*/	i2c_trace_next() /* +*/	i2c_trace_down() /* +*/	call(func) /* +*/	i2c_trace_exit() /* +*/ + +i2c_raise_scl: +	push $r4 +	mov $r4 (T_TIMEOUT / T_RISEFALL) +	i2c_drive_scl(1) +	i2c_raise_scl_wait: +		i2c_delay(T_RISEFALL) +		i2c_sense_scl() +		bra $p1 #i2c_raise_scl_done +		sub b32 $r4 1 +		bra nz #i2c_raise_scl_wait +	i2c_raise_scl_done: +	pop $r4 +	ret + +i2c_start: +	i2c_sense_scl() +	bra not $p1 #i2c_start_rep +	i2c_sense_sda() +	bra not $p1 #i2c_start_rep +	bra #i2c_start_send +	i2c_start_rep: +		i2c_drive_scl(0) +		i2c_drive_sda(1) +		i2c_trace_call(i2c_raise_scl) +		bra not $p1 #i2c_start_out +	i2c_start_send: +	i2c_drive_sda(0) +	i2c_delay(T_HOLD) +	i2c_drive_scl(0) +	i2c_delay(T_HOLD) +	i2c_start_out: +	ret + +i2c_stop: +	i2c_drive_scl(0) +	i2c_drive_sda(0) +	i2c_delay(T_RISEFALL) +	i2c_drive_scl(1) +	i2c_delay(T_HOLD) +	i2c_drive_sda(1) +	i2c_delay(T_HOLD) +	ret + +// $r3  - value +// $r2  - sda line +// $r1  - scl line +// $r0  - zero +i2c_bitw: +	call(i2c_drive_sda) +	i2c_delay(T_RISEFALL) +	i2c_trace_call(i2c_raise_scl) +	bra not $p1 #i2c_bitw_out +	i2c_delay(T_HOLD) +	i2c_drive_scl(0) +	i2c_delay(T_HOLD) +	i2c_bitw_out: +	ret + +// $r3  - value (out) +// $r2  - sda line +// $r1  - scl line +// $r0  - zero +i2c_bitr: +	i2c_drive_sda(1) +	i2c_delay(T_RISEFALL) +	i2c_trace_call(i2c_raise_scl) +	bra not $p1 #i2c_bitr_done +	i2c_sense_sda() +	i2c_drive_scl(0) +	i2c_delay(T_HOLD) +	xbit $r3 $flags $p1 +	bset $flags $p1 +	i2c_bitr_done: +	ret + +i2c_get_byte: +	mov $r5 0 +	mov $r4 8 +	i2c_get_byte_next: +		shl b32 $r5 1 +		i2c_trace_call(i2c_bitr) +		bra not $p1 #i2c_get_byte_done +		or $r5 $r3 +		sub b32 $r4 1 +		bra nz #i2c_get_byte_next +	mov $r3 1 +	i2c_trace_call(i2c_bitw) +	i2c_get_byte_done: +	ret + +i2c_put_byte: +	mov $r4 8 +	i2c_put_byte_next: +		sub b32 $r4 1 +		xbit $r3 $r5 $r4 +		i2c_trace_call(i2c_bitw) +		bra not $p1 #i2c_put_byte_done +		cmp b32 $r4 0 +		bra ne #i2c_put_byte_next +	i2c_trace_call(i2c_bitr) +	bra not $p1 #i2c_put_byte_done +	i2c_trace_next() +	cmp b32 $r3 1 +	bra ne #i2c_put_byte_done +	bclr $flags $p1	// nack +	i2c_put_byte_done: +	ret + +i2c_addr: +	i2c_trace_call(i2c_start) +	bra not $p1 #i2c_addr_done +	extr $r3 $r12 I2C__MSG_DATA0_ADDR +	shl b32 $r3 1 +	or $r5 $r3 +	i2c_trace_call(i2c_put_byte) +	i2c_addr_done: +	ret + +i2c_acquire_addr: +	extr $r14 $r12 I2C__MSG_DATA0_PORT +#if NVKM_PPWR_CHIPSET < GF119 +	shl b32 $r14 2 +	add b32 $r14 #i2c_ctrl +	ld b32 $r14 D[$r14] +#else +	shl b32 $r14 5 +	add b32 $r14 0x00d014 +#endif +	ret + +i2c_acquire: +	call(i2c_acquire_addr) +	call(rd32) +	bset $r13 3 +	call(wr32) +	ret + +i2c_release: +	call(i2c_acquire_addr) +	call(rd32) +	bclr $r13 3 +	call(wr32) +	ret + +// description +// +// $r15 - current (i2c) +// $r14 - sender process name +// $r13 - message +// $r12 - data0 +// $r11 - data1 +// $r0  - zero +i2c_recv: +	bclr $flags $p1 +	extr $r1 $r12 I2C__MSG_DATA0_PORT +	shl b32 $r1 2 +	cmp b32 $r1 (#i2c_sda_map - #i2c_scl_map) +	bra ge #i2c_recv_done +	add b32 $r3 $r1 #i2c_sda_map +	ld b32 $r2 D[$r3] +	add b32 $r3 $r1 #i2c_scl_map +	ld b32 $r1 D[$r3] + +	bset $flags $p2 +	push $r13 +	push $r14 + +	push $r13 +	i2c_trace_init() +	i2c_trace_call(i2c_acquire) +	pop $r13 + +	cmp b32 $r13 I2C__MSG_RD08 +	bra ne #i2c_recv_not_rd08 +		mov $r5 0 +		i2c_trace_call(i2c_addr) +		bra not $p1 #i2c_recv_done +		extr $r5 $r12 I2C__MSG_DATA0_RD08_REG +		i2c_trace_call(i2c_put_byte) +		bra not $p1 #i2c_recv_done +		mov $r5 1 +		i2c_trace_call(i2c_addr) +		bra not $p1 #i2c_recv_done +		i2c_trace_call(i2c_get_byte) +		bra not $p1 #i2c_recv_done +		ins $r11 $r5 I2C__MSG_DATA1_RD08_VAL +		i2c_trace_call(i2c_stop) +		mov b32 $r11 $r5 +		clear b32 $r7 +		bra #i2c_recv_done + +	i2c_recv_not_rd08: +	cmp b32 $r13 I2C__MSG_WR08 +	bra ne #i2c_recv_not_wr08 +		mov $r5 0 +		call(i2c_addr) +		bra not $p1 #i2c_recv_done +		extr $r5 $r12 I2C__MSG_DATA0_WR08_REG +		call(i2c_put_byte) +		bra not $p1 #i2c_recv_done +		mov $r5 0 +		call(i2c_addr) +		bra not $p1 #i2c_recv_done +		extr $r5 $r11 I2C__MSG_DATA1_WR08_VAL +		call(i2c_put_byte) +		bra not $p1 #i2c_recv_done +		call(i2c_stop) +		clear b32 $r7 +		extr $r5 $r12 I2C__MSG_DATA0_WR08_SYNC +		bra nz #i2c_recv_done +		bclr $flags $p2 +		bra #i2c_recv_done + +	i2c_recv_not_wr08: + +	i2c_recv_done: +	extr $r14 $r12 I2C__MSG_DATA0_PORT +	call(i2c_release) + +	pop $r14 +	pop $r13 +	bra not $p2 #i2c_recv_exit +	mov b32 $r12 $r7 +	call(send) + +	i2c_recv_exit: +	ret + +// description +// +// $r15 - current (i2c) +// $r0  - zero +i2c_init: +	ret +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/idle.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/idle.fuc new file mode 100644 index 00000000000..98f1c3738b4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/idle.fuc @@ -0,0 +1,84 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifdef INCLUDE_PROC +process(PROC_IDLE, #idle, #idle_recv) +#endif + +/****************************************************************************** + * IDLE data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +#endif + +/****************************************************************************** + * IDLE code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE +// description +// +// $r15 - current (idle) +// $r14 - message +// $r0  - zero +idle_recv: +	ret + +// description +// +// $r15 - current (idle) +// $r0  - zero +idle: +	// set our "no interrupt has occurred during our execution" flag +	bset $flags $p0 + +	// count IDLE invocations for debugging purposes +	nv_iord($r1, NV_PPWR_DSCRATCH(1)) +	add b32 $r1 1 +	nv_iowr(NV_PPWR_DSCRATCH(1), $r1) + +	// keep looping while there's pending messages for any process +	idle_loop: +	mov $r1 #proc_list_head +	bclr $flags $p2 +	idle_proc: +		// process the process' messages until there's none left +		idle_proc_exec: +			push $r1 +			mov b32 $r14 $r1 +			call(recv) +			pop $r1 +			bra not $p1 #idle_proc_next +			bset $flags $p2 +			bra #idle_proc_exec +		// next process! +		idle_proc_next: +		add b32 $r1 #proc_size +		cmp b32 $r1 $r15 +		bra ne #idle_proc +	bra $p2 #idle_loop + +	// sleep if no interrupts have occurred +	sleep $p0 +	bra #idle +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc new file mode 100644 index 00000000000..8f29badd785 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/kernel.fuc @@ -0,0 +1,454 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +/****************************************************************************** + * kernel data segment + *****************************************************************************/ +#ifdef INCLUDE_PROC +proc_kern: +process(PROC_KERN, 0, 0) +proc_list_head: +#endif + +#ifdef INCLUDE_DATA +proc_list_tail: +time_prev: .b32 0 +time_next: .b32 0 +#endif + +/****************************************************************************** + * kernel code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE +	bra #init + +// read nv register +// +// $r15 - current +// $r14 - addr +// $r13 - data (return) +// $r0  - zero +rd32: +	nv_iowr(NV_PPWR_MMIO_ADDR, $r14) +	mov $r13 NV_PPWR_MMIO_CTRL_OP_RD +	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER +	nv_iowr(NV_PPWR_MMIO_CTRL, $r13) +	rd32_wait: +		nv_iord($r13, NV_PPWR_MMIO_CTRL) +		and $r13 NV_PPWR_MMIO_CTRL_STATUS +		bra nz #rd32_wait +	nv_iord($r13, NV_PPWR_MMIO_DATA) +	ret + +// write nv register +// +// $r15 - current +// $r14 - addr +// $r13 - data +// $r0  - zero +wr32: +	nv_iowr(NV_PPWR_MMIO_ADDR, $r14) +	nv_iowr(NV_PPWR_MMIO_DATA, $r13) +	mov $r13 NV_PPWR_MMIO_CTRL_OP_WR +	or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0 +	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER + +#ifdef NVKM_FALCON_MMIO_TRAP +	push $r13 +	mov $r13 NV_PPWR_INTR_TRIGGER_USER1 +	nv_iowr(NV_PPWR_INTR_TRIGGER, $r13) +	wr32_host: +		nv_iord($r13, NV_PPWR_INTR) +		and $r13 NV_PPWR_INTR_USER1 +		bra nz #wr32_host +	pop $r13 +#endif + +	nv_iowr(NV_PPWR_MMIO_CTRL, $r13) +	wr32_wait: +		nv_iord($r13, NV_PPWR_MMIO_CTRL) +		and $r13 NV_PPWR_MMIO_CTRL_STATUS +		bra nz #wr32_wait +	ret + +// busy-wait for a period of time +// +// $r15 - current +// $r14 - ns +// $r0  - zero +nsec: +	nv_iord($r8, NV_PPWR_TIMER_LOW) +	nsec_loop: +		nv_iord($r9, NV_PPWR_TIMER_LOW) +		sub b32 $r9 $r8 +		cmp b32 $r9 $r14 +		bra l #nsec_loop +	ret + +// busy-wait for a period of time +// +// $r15 - current +// $r14 - addr +// $r13 - mask +// $r12 - data +// $r11 - timeout (ns) +// $r0  - zero +wait: +	nv_iord($r8, NV_PPWR_TIMER_LOW) +	wait_loop: +		nv_rd32($r10, $r14) +		and $r10 $r13 +		cmp b32 $r10 $r12 +		bra e #wait_done +		nv_iord($r9, NV_PPWR_TIMER_LOW) +		sub b32 $r9 $r8 +		cmp b32 $r9 $r11 +		bra l #wait_loop +	wait_done: +	ret + +// $r15 - current (kern) +// $r14 - process +// $r8  - NV_PPWR_INTR +intr_watchdog: +	// read process' timer status, skip if not enabled +	ld b32 $r9 D[$r14 + #proc_time] +	cmp b32 $r9 0 +	bra z #intr_watchdog_next_proc + +	// subtract last timer's value from process' timer, +	// if it's <= 0 then the timer has expired +	ld b32 $r10 D[$r0 + #time_prev] +	sub b32 $r9 $r10 +	bra g #intr_watchdog_next_time +		mov $r13 KMSG_ALARM +		call(send_proc) +		clear b32 $r9 +		bra #intr_watchdog_next_proc + +	// otherwise, update the next timer's value if this +	// process' timer is the soonest +	intr_watchdog_next_time: +		// ... or if there's no next timer yet +		ld b32 $r10 D[$r0 + #time_next] +		cmp b32 $r10 0 +		bra z #intr_watchdog_next_time_set + +		cmp b32 $r9 $r10 +		bra g #intr_watchdog_next_proc +		intr_watchdog_next_time_set: +		st b32 D[$r0 + #time_next] $r9 + +	// update process' timer status, and advance +	intr_watchdog_next_proc: +	st b32 D[$r14 + #proc_time] $r9 +	add b32 $r14 #proc_size +	cmp b32 $r14 #proc_list_tail +	bra ne #intr_watchdog +	ret + +intr: +	push $r0 +	clear b32 $r0 +	push $r8 +	push $r9 +	push $r10 +	push $r11 +	push $r12 +	push $r13 +	push $r14 +	push $r15 +	mov $r15 #proc_kern +	mov $r8 $flags +	push $r8 + +	nv_iord($r8, NV_PPWR_DSCRATCH(0)) +	add b32 $r8 1 +	nv_iowr(NV_PPWR_DSCRATCH(0), $r8) + +	nv_iord($r8, NV_PPWR_INTR) +	and $r9 $r8 NV_PPWR_INTR_WATCHDOG +	bra z #intr_skip_watchdog +		st b32 D[$r0 + #time_next] $r0 +		mov $r14 #proc_list_head +		call(intr_watchdog) +		ld b32 $r9 D[$r0 + #time_next] +		cmp b32 $r9 0 +		bra z #intr_skip_watchdog +			nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9) +			st b32 D[$r0 + #time_prev] $r9 + +	intr_skip_watchdog: +	and $r9 $r8 NV_PPWR_INTR_SUBINTR +	bra z #intr_skip_subintr +		nv_iord($r9, NV_PPWR_SUBINTR) +		and $r10 $r9 NV_PPWR_SUBINTR_FIFO +		bra z #intr_subintr_skip_fifo +			nv_iord($r12, NV_PPWR_FIFO_INTR) +			push $r12 +			mov $r14 (PROC_HOST & 0x0000ffff) +			sethi $r14 (PROC_HOST & 0xffff0000) +			mov $r13 KMSG_FIFO +			call(send) +			pop $r12 +			nv_iowr(NV_PPWR_FIFO_INTR, $r12) +		intr_subintr_skip_fifo: +		nv_iowr(NV_PPWR_SUBINTR, $r9) + +	intr_skip_subintr: +	and $r9 $r8 NV_PPWR_INTR_PAUSE +	bra z #intr_skip_pause +		and $r10 0xffbf + +	intr_skip_pause: +	and $r9 $r8 NV_PPWR_INTR_USER0 +	bra z #intr_skip_user0 +		and $r10 0xffbf + +	intr_skip_user0: +	nv_iowr(NV_PPWR_INTR_ACK, $r8) +	pop $r8 +	mov $flags $r8 +	pop $r15 +	pop $r14 +	pop $r13 +	pop $r12 +	pop $r11 +	pop $r10 +	pop $r9 +	pop $r8 +	pop $r0 +	bclr $flags $p0 +	iret + +// request the current process be sent a message after a timeout expires +// +// $r15 - current +// $r14 - ticks +// $r0  - zero +timer: +	// interrupts off to prevent racing with timer isr +	bclr $flags ie0 + +	// if current process already has a timer set, bail +	ld b32 $r8 D[$r15 + #proc_time] +	cmp b32 $r8 0 +	bra g #timer_done +	st b32 D[$r15 + #proc_time] $r14 + +	// halt watchdog timer temporarily and check for a pending +	// interrupt.  if there's one already pending, we can just +	// bail since the timer isr will queue the next soonest +	// right after it's done +	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8) +	nv_iord($r8, NV_PPWR_INTR) +	and $r8 NV_PPWR_INTR_WATCHDOG +	bra nz #timer_enable + +	// update the watchdog if this timer should expire first, +	// or if there's no timeout already set +	nv_iord($r8, NV_PPWR_WATCHDOG_TIME) +	cmp b32 $r14 $r0 +	bra e #timer_reset +	cmp b32 $r14 $r8 +	bra l #timer_done +	timer_reset: +	nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14) +	st b32 D[$r0 + #time_prev] $r14 + +	// re-enable the watchdog timer +	timer_enable: +	mov $r8 1 +	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8) + +	// interrupts back on +	timer_done: +	bset $flags ie0 +	ret + +// send message to another process +// +// $r15 - current +// $r14 - process +// $r13 - message +// $r12 - message data 0 +// $r11 - message data 1 +// $r0  - zero +send_proc: +	push $r8 +	push $r9 +	// check for space in queue +	ld b32 $r8 D[$r14 + #proc_qget] +	ld b32 $r9 D[$r14 + #proc_qput] +	xor $r8 #proc_qmaskb +	cmp b32 $r8 $r9 +	bra e #send_done + +	// enqueue message +	and $r8 $r9 #proc_qmaskp +	shl b32 $r8 $r8 #proc_qlen +	add b32 $r8 #proc_queue +	add b32 $r8 $r14 + +	ld b32 $r10 D[$r15 + #proc_id] +	st b32 D[$r8 + #msg_process] $r10 +	st b32 D[$r8 + #msg_message] $r13 +	st b32 D[$r8 + #msg_data0] $r12 +	st b32 D[$r8 + #msg_data1] $r11 + +	// increment PUT +	add b32 $r9 1 +	and $r9 #proc_qmaskf +	st b32 D[$r14 + #proc_qput] $r9 +	bset $flags $p2 +	send_done: +	pop $r9 +	pop $r8 +	ret + +// lookup process structure by its name +// +// $r15 - current +// $r14 - process name +// $r0  - zero +// +// $r14 - process +// $p1  - success +find: +	push $r8 +	mov $r8 #proc_list_head +	bset $flags $p1 +	find_loop: +		ld b32 $r10 D[$r8 + #proc_id] +		cmp b32 $r10 $r14 +		bra e #find_done +		add b32 $r8 #proc_size +		cmp b32 $r8 #proc_list_tail +		bra ne #find_loop +		bclr $flags $p1 +	find_done: +	mov b32 $r14 $r8 +	pop $r8 +	ret + +// send message to another process +// +// $r15 - current +// $r14 - process id +// $r13 - message +// $r12 - message data 0 +// $r11 - message data 1 +// $r0  - zero +send: +	call(find) +	bra $p1 #send_proc +	ret + +// process single message for a given process +// +// $r15 - current +// $r14 - process +// $r0  - zero +recv: +	ld b32 $r8 D[$r14 + #proc_qget] +	ld b32 $r9 D[$r14 + #proc_qput] +	bclr $flags $p1 +	cmp b32 $r8 $r9 +	bra e #recv_done +		// dequeue message +		and $r9 $r8 #proc_qmaskp +		add b32 $r8 1 +		and $r8 #proc_qmaskf +		st b32 D[$r14 + #proc_qget] $r8 +		ld b32 $r10 D[$r14 + #proc_recv] + +		push $r15 +		mov $r15 $flags +		push $r15 +		mov b32 $r15 $r14 + +		shl b32 $r9 $r9 #proc_qlen +		add b32 $r14 $r9 +		add b32 $r14 #proc_queue +		ld b32 $r11 D[$r14 + #msg_data1] +		ld b32 $r12 D[$r14 + #msg_data0] +		ld b32 $r13 D[$r14 + #msg_message] +		ld b32 $r14 D[$r14 + #msg_process] + +		// process it +		call $r10 +		pop $r15 +		mov $flags $r15 +		bset $flags $p1 +		pop $r15 +	recv_done: +	ret + +init: +	// setup stack +	nv_iord($r1, NV_PPWR_CAPS) +	extr $r1 $r1 9:17 +	shl b32 $r1 8 +	mov $sp $r1 + +#ifdef NVKM_FALCON_MMIO_UAS +	// somehow allows the magic "access mmio via D[]" stuff that's +	// used by the nv_rd32/nv_wr32 macros to work +	mov $r1 0x0010 +	sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE +	nv_iowrs(NV_PPWR_UAS_CONFIG, $r1) +#endif + +	// route all interrupts except user0/1 and pause to fuc +	mov $r1 0x00e0 +	sethi $r1 0x00000000 +	nv_iowr(NV_PPWR_INTR_ROUTE, $r1) + +	// enable watchdog and subintr intrs +	mov $r1 NV_PPWR_INTR_EN_CLR_MASK +	nv_iowr(NV_PPWR_INTR_EN_CLR, $r1) +	mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG +	or $r1 NV_PPWR_INTR_EN_SET_SUBINTR +	nv_iowr(NV_PPWR_INTR_EN_SET, $r1) + +	// enable interrupts globally +	mov $r1 #intr +	sethi $r1 0x00000000 +	mov $iv0 $r1 +	bset $flags ie0 + +	// enable watchdog timer +	mov $r1 1 +	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1) + +	// bootstrap processes, idle process will be last, and not return +	mov $r15 #proc_list_head +	init_proc: +		ld b32 $r1 D[$r15 + #proc_init] +		cmp b32 $r1 0 +		bra z #init_proc +		call $r1 +		add b32 $r15 #proc_size +		bra #init_proc +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc new file mode 100644 index 00000000000..e2a63ac5422 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/macros.fuc @@ -0,0 +1,252 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#define GT215 0xa3 +#define GF100 0xc0 +#define GF119 0xd9 +#define GK208 0x108 + +#include "os.h" + +// IO addresses +#define NV_PPWR_INTR_TRIGGER                                             0x0000 +#define NV_PPWR_INTR_TRIGGER_USER1                                   0x00000080 +#define NV_PPWR_INTR_TRIGGER_USER0                                   0x00000040 +#define NV_PPWR_INTR_ACK                                                 0x0004 +#define NV_PPWR_INTR_ACK_SUBINTR                                     0x00000800 +#define NV_PPWR_INTR_ACK_WATCHDOG                                    0x00000002 +#define NV_PPWR_INTR                                                     0x0008 +#define NV_PPWR_INTR_SUBINTR                                         0x00000800 +#define NV_PPWR_INTR_USER1                                           0x00000080 +#define NV_PPWR_INTR_USER0                                           0x00000040 +#define NV_PPWR_INTR_PAUSE                                           0x00000020 +#define NV_PPWR_INTR_WATCHDOG                                        0x00000002 +#define NV_PPWR_INTR_EN_SET                                              0x0010 +#define NV_PPWR_INTR_EN_SET_SUBINTR                                  0x00000800 +#define NV_PPWR_INTR_EN_SET_WATCHDOG                                 0x00000002 +#define NV_PPWR_INTR_EN_CLR                                              0x0014 +#define NV_PPWR_INTR_EN_CLR_MASK                    /* fuck i hate envyas */ -1 +#define NV_PPWR_INTR_ROUTE                                               0x001c +#define NV_PPWR_TIMER_LOW                                                0x002c +#define NV_PPWR_WATCHDOG_TIME                                            0x0034 +#define NV_PPWR_WATCHDOG_ENABLE                                          0x0038 +#define NV_PPWR_CAPS                                                     0x0108 +#define NV_PPWR_UAS_CONFIG                                               0x0164 +#define NV_PPWR_UAS_CONFIG_ENABLE                                    0x00010000 +#if NVKM_PPWR_CHIPSET >= GK208 +#define NV_PPWR_DSCRATCH(i)                                   (4 * (i) + 0x0450) +#endif +#define NV_PPWR_FIFO_PUT(i)                                   (4 * (i) + 0x04a0) +#define NV_PPWR_FIFO_GET(i)                                   (4 * (i) + 0x04b0) +#define NV_PPWR_FIFO_INTR                                                0x04c0 +#define NV_PPWR_FIFO_INTR_EN                                             0x04c4 +#define NV_PPWR_RFIFO_PUT                                                0x04c8 +#define NV_PPWR_RFIFO_GET                                                0x04cc +#define NV_PPWR_H2D                                                      0x04d0 +#define NV_PPWR_D2H                                                      0x04dc +#if NVKM_PPWR_CHIPSET < GK208 +#define NV_PPWR_DSCRATCH(i)                                   (4 * (i) + 0x05d0) +#endif +#define NV_PPWR_SUBINTR                                                  0x0688 +#define NV_PPWR_SUBINTR_FIFO                                         0x00000002 +#define NV_PPWR_MMIO_ADDR                                                0x07a0 +#define NV_PPWR_MMIO_DATA                                                0x07a4 +#define NV_PPWR_MMIO_CTRL                                                0x07ac +#define NV_PPWR_MMIO_CTRL_TRIGGER                                    0x00010000 +#define NV_PPWR_MMIO_CTRL_STATUS                                     0x00007000 +#define NV_PPWR_MMIO_CTRL_STATUS_IDLE                                0x00000000 +#define NV_PPWR_MMIO_CTRL_MASK                                       0x000000f0 +#define NV_PPWR_MMIO_CTRL_MASK_B32_0                                 0x000000f0 +#define NV_PPWR_MMIO_CTRL_OP                                         0x00000003 +#define NV_PPWR_MMIO_CTRL_OP_RD                                      0x00000001 +#define NV_PPWR_MMIO_CTRL_OP_WR                                      0x00000002 +#define NV_PPWR_OUTPUT                                                   0x07c0 +#define NV_PPWR_OUTPUT_FB_PAUSE                                      0x00000004 +#if NVKM_PPWR_CHIPSET < GF119 +#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00000100 +#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00000200 +#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00001000 +#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00002000 +#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00004000 +#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00008000 +#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00010000 +#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00020000 +#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00040000 +#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x00080000 +#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00100000 +#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x00200000 +#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00400000 +#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x00800000 +#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x01000000 +#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x02000000 +#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x04000000 +#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x08000000 +#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x10000000 +#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000 +#else +#define NV_PPWR_OUTPUT_I2C_0_SCL                                     0x00000400 +#define NV_PPWR_OUTPUT_I2C_1_SCL                                     0x00000800 +#define NV_PPWR_OUTPUT_I2C_2_SCL                                     0x00001000 +#define NV_PPWR_OUTPUT_I2C_3_SCL                                     0x00002000 +#define NV_PPWR_OUTPUT_I2C_4_SCL                                     0x00004000 +#define NV_PPWR_OUTPUT_I2C_5_SCL                                     0x00008000 +#define NV_PPWR_OUTPUT_I2C_6_SCL                                     0x00010000 +#define NV_PPWR_OUTPUT_I2C_7_SCL                                     0x00020000 +#define NV_PPWR_OUTPUT_I2C_8_SCL                                     0x00040000 +#define NV_PPWR_OUTPUT_I2C_9_SCL                                     0x00080000 +#define NV_PPWR_OUTPUT_I2C_0_SDA                                     0x00100000 +#define NV_PPWR_OUTPUT_I2C_1_SDA                                     0x00200000 +#define NV_PPWR_OUTPUT_I2C_2_SDA                                     0x00400000 +#define NV_PPWR_OUTPUT_I2C_3_SDA                                     0x00800000 +#define NV_PPWR_OUTPUT_I2C_4_SDA                                     0x01000000 +#define NV_PPWR_OUTPUT_I2C_5_SDA                                     0x02000000 +#define NV_PPWR_OUTPUT_I2C_6_SDA                                     0x04000000 +#define NV_PPWR_OUTPUT_I2C_7_SDA                                     0x08000000 +#define NV_PPWR_OUTPUT_I2C_8_SDA                                     0x10000000 +#define NV_PPWR_OUTPUT_I2C_9_SDA                                     0x20000000 +#endif +#define NV_PPWR_INPUT                                                    0x07c4 +#define NV_PPWR_OUTPUT_SET                                               0x07e0 +#define NV_PPWR_OUTPUT_SET_FB_PAUSE                                  0x00000004 +#define NV_PPWR_OUTPUT_CLR                                               0x07e4 +#define NV_PPWR_OUTPUT_CLR_FB_PAUSE                                  0x00000004 + +// Inter-process message format +.equ #msg_process 0x00 /* send() target, recv() sender */ +.equ #msg_message 0x04 +.equ #msg_data0   0x08 +.equ #msg_data1   0x0c + +// Kernel message IDs +#define KMSG_FIFO  0x00000000 +#define KMSG_ALARM 0x00000001 + +// Process message queue description +.equ #proc_qlen 4 // log2(size of queue entry in bytes) +.equ #proc_qnum 2 // log2(max number of entries in queue) +.equ #proc_qmaskb (1 << #proc_qnum) // max number of entries in queue +.equ #proc_qmaskp (#proc_qmaskb - 1) +.equ #proc_qmaskf ((#proc_qmaskb << 1) - 1) +.equ #proc_qsize  (1 << (#proc_qlen + #proc_qnum)) + +// Process table entry +.equ #proc_id    0x00 +.equ #proc_init  0x04 +.equ #proc_recv  0x08 +.equ #proc_time  0x0c +.equ #proc_qput  0x10 +.equ #proc_qget  0x14 +.equ #proc_queue 0x18 +.equ #proc_size (0x18 + #proc_qsize) + +#define process(id,init,recv) /* +*/	.b32 id /* +*/	.b32 init /* +*/	.b32 recv /* +*/	.b32 0 /* +*/	.b32 0 /* +*/	.b32 0 /* +*/	.skip 64 + +#if NV_PPWR_CHIPSET < GK208 +#define imm32(reg,val) /* +*/	movw reg  ((val) & 0x0000ffff) /* +*/	sethi reg ((val) & 0xffff0000) +#else +#define imm32(reg,val) /* +*/	mov reg (val) +#endif + +#ifndef NVKM_FALCON_UNSHIFTED_IO +#define nv_iord(reg,ior) /* +*/	mov reg ior /* +*/ 	shl b32 reg 6 /* +*/ 	iord reg I[reg + 0x000] +#else +#define nv_iord(reg,ior) /* +*/	mov reg ior /* +*/ 	iord reg I[reg + 0x000] +#endif + +#ifndef NVKM_FALCON_UNSHIFTED_IO +#define nv_iowr(ior,reg) /* +*/	mov $r0 ior /* +*/ 	shl b32 $r0 6 /* +*/ 	iowr I[$r0 + 0x000] reg /* +*/	clear b32 $r0 +#else +#define nv_iowr(ior,reg) /* +*/	mov $r0 ior /* +*/ 	iowr I[$r0 + 0x000] reg /* +*/	clear b32 $r0 +#endif + +#ifndef NVKM_FALCON_UNSHIFTED_IO +#define nv_iowrs(ior,reg) /* +*/	mov $r0 ior /* +*/ 	shl b32 $r0 6 /* +*/ 	iowrs I[$r0 + 0x000] reg /* +*/	clear b32 $r0 +#else +#define nv_iowrs(ior,reg) /* +*/	mov $r0 ior /* +*/ 	iowrs I[$r0 + 0x000] reg /* +*/	clear b32 $r0 +#endif + +#define hash # +#define fn(a) a +#ifndef NVKM_FALCON_PC24 +#define call(a) call fn(hash)a +#else +#define call(a) lcall fn(hash)a +#endif + +#ifndef NVKM_FALCON_MMIO_UAS +#define nv_rd32(reg,addr) /* +*/	mov b32 $r14 addr /* +*/	call(rd32) /* +*/	mov b32 reg $r13 +#else +#define nv_rd32(reg,addr) /* +*/ 	sethi $r0 0x14000000 /* +*/	or $r0 addr /* +*/	ld b32 reg D[$r0] /* +*/	clear b32 $r0 +#endif + +#if !defined(NVKM_FALCON_MMIO_UAS) || defined(NVKM_FALCON_MMIO_TRAP) +#define nv_wr32(addr,reg) /* +*/	push addr /* +*/	push reg /* +*/	pop $r13 /* +*/	pop $r14 /* +*/	call(wr32) /* +#else +#define nv_wr32(addr,reg) /* +*/ 	sethi $r0 0x14000000 /* +*/	or $r0 addr /* +*/	st b32 D[$r0] reg /* +*/	clear b32 $r0 +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/memx.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/memx.fuc new file mode 100644 index 00000000000..d43741eccb1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/memx.fuc @@ -0,0 +1,219 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifdef INCLUDE_PROC +process(PROC_MEMX, #memx_init, #memx_recv) +#endif + +/****************************************************************************** + * MEMX data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +.equ #memx_opcode 0 +.equ #memx_header 2 +.equ #memx_length 4 +.equ #memx_func   8 + +#define handler(cmd,hdr,len,func) /* +*/	.b16 MEMX_##cmd /* +*/	.b16 hdr /* +*/	.b16 len /* +*/      .b16 0 /* +*/	.b32 func + +memx_func_head: +handler(ENTER , 0x0001, 0x0000, #memx_func_enter) +memx_func_next: +handler(LEAVE , 0x0000, 0x0000, #memx_func_leave) +handler(WR32  , 0x0000, 0x0002, #memx_func_wr32) +handler(WAIT  , 0x0004, 0x0000, #memx_func_wait) +handler(DELAY , 0x0001, 0x0000, #memx_func_delay) +memx_func_tail: + +.equ #memx_func_size #memx_func_next - #memx_func_head +.equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size + +memx_data_head: +.skip 0x0800 +memx_data_tail: +#endif + +/****************************************************************************** + * MEMX code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE +// description +// +// $r15 - current (memx) +// $r4  - packet length +//	+00: bitmask of heads to wait for vblank on +// $r3  - opcode desciption +// $r0  - zero +memx_func_enter: +	mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE +	nv_iowr(NV_PPWR_OUTPUT_SET, $r6) +	memx_func_enter_wait: +		nv_iord($r6, NV_PPWR_OUTPUT) +		and $r6 NV_PPWR_OUTPUT_FB_PAUSE +		bra z #memx_func_enter_wait +	//XXX: TODO +	ld b32 $r6 D[$r1 + 0x00] +	add b32 $r1 0x04 +	ret + +// description +// +// $r15 - current (memx) +// $r4  - packet length +// $r3  - opcode desciption +// $r0  - zero +memx_func_leave: +	mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE +	nv_iowr(NV_PPWR_OUTPUT_CLR, $r6) +	memx_func_leave_wait: +		nv_iord($r6, NV_PPWR_OUTPUT) +		and $r6 NV_PPWR_OUTPUT_FB_PAUSE +		bra nz #memx_func_leave_wait +	ret + +// description +// +// $r15 - current (memx) +// $r4  - packet length +//	+00*n: addr +//	+04*n: data +// $r3  - opcode desciption +// $r0  - zero +memx_func_wr32: +	ld b32 $r6 D[$r1 + 0x00] +	ld b32 $r5 D[$r1 + 0x04] +	add b32 $r1 0x08 +	nv_wr32($r6, $r5) +	sub b32 $r4 0x02 +	bra nz #memx_func_wr32 +	ret + +// description +// +// $r15 - current (memx) +// $r4  - packet length +//	+00: addr +//	+04: mask +//	+08: data +//	+0c: timeout (ns) +// $r3  - opcode desciption +// $r0  - zero +memx_func_wait: +	nv_iord($r8, NV_PPWR_TIMER_LOW) +	ld b32 $r14 D[$r1 + 0x00] +	ld b32 $r13 D[$r1 + 0x04] +	ld b32 $r12 D[$r1 + 0x08] +	ld b32 $r11 D[$r1 + 0x0c] +	add b32 $r1 0x10 +	call(wait) +	ret + +// description +// +// $r15 - current (memx) +// $r4  - packet length +//	+00: time (ns) +// $r3  - opcode desciption +// $r0  - zero +memx_func_delay: +	ld b32 $r14 D[$r1 + 0x00] +	add b32 $r1 0x04 +	call(nsec) +	ret + +// description +// +// $r15 - current (memx) +// $r14 - sender process name +// $r13 - message (exec) +// $r12 - head of script +// $r11 - tail of script +// $r0  - zero +memx_exec: +	push $r14 +	push $r13 +	mov b32 $r1 $r12 +	mov b32 $r2 $r11 +	memx_exec_next: +		// fetch the packet header, and locate opcode info +		ld b32 $r3 D[$r1] +		add b32 $r1 4 +		shr b32 $r4 $r3 16 +		mulu $r3 #memx_func_size + +		// execute the opcode handler +		ld b32 $r5 D[$r3 + #memx_func_head + #memx_func] +		call $r5 + +		// keep going, if we haven't reached the end +		cmp b32 $r1 $r2 +		bra l #memx_exec_next + +	// send completion reply +	pop $r13 +	pop $r14 +	call(send) +	ret + +// description +// +// $r15 - current (memx) +// $r14 - sender process name +// $r13 - message +// $r12 - data0 +// $r11 - data1 +// $r0  - zero +memx_info: +	mov $r12 #memx_data_head +	mov $r11 #memx_data_tail - #memx_data_head +	call(send) +	ret + +// description +// +// $r15 - current (memx) +// $r14 - sender process name +// $r13 - message +// $r12 - data0 +// $r11 - data1 +// $r0  - zero +memx_recv: +	cmp b32 $r13 MEMX_MSG_EXEC +	bra e #memx_exec +	cmp b32 $r13 MEMX_MSG_INFO +	bra e #memx_info +	ret + +// description +// +// $r15 - current (memx) +// $r0  - zero +memx_init: +	ret +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc new file mode 100644 index 00000000000..17a8a383d91 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc @@ -0,0 +1,66 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#define NVKM_PPWR_CHIPSET GK208 + +#define NVKM_FALCON_PC24 +#define NVKM_FALCON_UNSHIFTED_IO +//#define NVKM_FALCON_MMIO_UAS +//#define NVKM_FALCON_MMIO_TRAP + +#include "macros.fuc" + +.section #nv108_pwr_data +#define INCLUDE_PROC +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_PROC + +#define INCLUDE_DATA +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_DATA +.align 256 + +.section #nv108_pwr_code +#define INCLUDE_CODE +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_CODE +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h new file mode 100644 index 00000000000..39a5dc150a0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nv108.fuc.h @@ -0,0 +1,1460 @@ +uint32_t nv108_pwr_data[] = { +/* 0x0000: proc_kern */ +	0x52544e49, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0058: proc_list_head */ +	0x54534f48, +	0x00000379, +	0x0000032a, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x584d454d, +	0x0000046f, +	0x00000461, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x46524550, +	0x00000473, +	0x00000471, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x5f433249, +	0x00000877, +	0x0000071e, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x54534554, +	0x00000898, +	0x00000879, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x454c4449, +	0x000008a3, +	0x000008a1, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ +	0x00000000, +/* 0x026c: time_next */ +	0x00000000, +/* 0x0270: fifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x02f0: rfifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0370: memx_func_head */ +	0x00010000, +	0x00000000, +	0x000003a9, +/* 0x037c: memx_func_next */ +	0x00000001, +	0x00000000, +	0x000003c7, +	0x00000002, +	0x00000002, +	0x000003df, +	0x00040003, +	0x00000000, +	0x00000407, +	0x00010004, +	0x00000000, +	0x00000421, +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ +	0x00000400, +	0x00000800, +	0x00001000, +	0x00002000, +	0x00004000, +	0x00008000, +	0x00010000, +	0x00020000, +	0x00040000, +	0x00080000, +/* 0x0bd4: i2c_sda_map */ +	0x00100000, +	0x00200000, +	0x00400000, +	0x00800000, +	0x01000000, +	0x02000000, +	0x04000000, +	0x08000000, +	0x10000000, +	0x20000000, +	0x00000000, +}; + +uint32_t nv108_pwr_code[] = { +	0x02910ef5, +/* 0x0004: rd32 */ +	0xf607a040, +	0x04bd000e, +	0xd3f0010d, +	0x07ac4001, +	0xbd000df6, +/* 0x0019: rd32_wait */ +	0x07ac4d04, +	0xf100ddcf, +	0xf47000d4, +	0xa44df61b, +	0x00ddcf07, +/* 0x002e: wr32 */ +	0xa04000f8, +	0x000ef607, +	0xa44004bd, +	0x000df607, +	0x020d04bd, +	0xf0f0d5f0, +	0xac4001d3, +	0x000df607, +/* 0x004e: wr32_wait */ +	0xac4d04bd, +	0x00ddcf07, +	0x7000d4f1, +	0xf8f61bf4, +/* 0x005d: nsec */ +	0xcf2c0800, +/* 0x0062: nsec_loop */ +	0x2c090088, +	0xbb0099cf, +	0x9ea60298, +	0xf8f61ef4, +/* 0x0071: wait */ +	0xcf2c0800, +/* 0x0076: wait_loop */ +	0xeeb20088, +	0x0000047e, +	0xadfddab2, +	0xf4aca604, +	0x2c09100b, +	0xbb0099cf, +	0x9ba60298, +/* 0x0093: wait_done */ +	0xf8e61ef4, +/* 0x0095: intr_watchdog */ +	0x03e99800, +	0xf40096b0, +	0x0a98280b, +	0x029abb9a, +	0x0d0e1cf4, +	0x01de7e01, +	0xf494bd00, +/* 0x00b2: intr_watchdog_next_time */ +	0x0a98140e, +	0x00a6b09b, +	0xa6080bf4, +	0x061cf49a, +/* 0x00c0: intr_watchdog_next_time_set */ +/* 0x00c3: intr_watchdog_next_proc */ +	0xb59b09b5, +	0xe0b603e9, +	0x68e6b158, +	0xc81bf402, +/* 0x00d2: intr */ +	0x00f900f8, +	0x80f904bd, +	0xa0f990f9, +	0xc0f9b0f9, +	0xe0f9d0f9, +	0x000ff0f9, +	0xf90188fe, +	0x04504880, +	0xb60088cf, +	0x50400180, +	0x0008f604, +	0x080804bd, +	0xc40088cf, +	0x0bf40289, +	0x9b00b51f, +	0x957e580e, +	0x09980000, +	0x0096b09b, +	0x000d0bf4, +	0x0009f634, +	0x09b504bd, +/* 0x0125: intr_skip_watchdog */ +	0x0089e49a, +	0x360bf408, +	0xcf068849, +	0x9ac40099, +	0x220bf402, +	0xcf04c04c, +	0xc0f900cc, +	0xf14f484e, +	0x0d5453e3, +	0x023f7e00, +	0x40c0fc00, +	0x0cf604c0, +/* 0x0157: intr_subintr_skip_fifo */ +	0x4004bd00, +	0x09f60688, +/* 0x015f: intr_skip_subintr */ +	0xc404bd00, +	0x0bf42089, +	0xbfa4f107, +/* 0x0169: intr_skip_pause */ +	0x4089c4ff, +	0xf1070bf4, +/* 0x0173: intr_skip_user0 */ +	0x00ffbfa4, +	0x0008f604, +	0x80fc04bd, +	0xfc0088fe, +	0xfce0fcf0, +	0xfcc0fcd0, +	0xfca0fcb0, +	0xfc80fc90, +	0x0032f400, +/* 0x0196: timer */ +	0x32f401f8, +	0x03f89810, +	0xf40086b0, +	0xfeb53a1c, +	0xf6380003, +	0x04bd0008, +	0x88cf0808, +	0x0284f000, +	0x081c1bf4, +	0x0088cf34, +	0x0bf4e0a6, +	0xf4e8a608, +/* 0x01c6: timer_reset */ +	0x3400161e, +	0xbd000ef6, +	0x9a0eb504, +/* 0x01d0: timer_enable */ +	0x38000108, +	0xbd0008f6, +/* 0x01d9: timer_done */ +	0x1031f404, +/* 0x01de: send_proc */ +	0x80f900f8, +	0xe89890f9, +	0x04e99805, +	0xa60486f0, +	0x2a0bf489, +	0x940398c4, +	0x80b60488, +	0x008ebb18, +	0xb500fa98, +	0x8db5008a, +	0x028cb501, +	0xb6038bb5, +	0x94f00190, +	0x04e9b507, +/* 0x0217: send_done */ +	0xfc0231f4, +	0xf880fc90, +/* 0x021d: find */ +	0x0880f900, +	0x0131f458, +/* 0x0224: find_loop */ +	0xa6008a98, +	0x100bf4ae, +	0xb15880b6, +	0xf4026886, +	0x32f4f11b, +/* 0x0239: find_done */ +	0xfc8eb201, +/* 0x023f: send */ +	0x7e00f880, +	0xf400021d, +	0x00f89b01, +/* 0x0248: recv */ +	0x9805e898, +	0x32f404e9, +	0xf489a601, +	0x89c43c0b, +	0x0180b603, +	0xb50784f0, +	0xea9805e8, +	0xfef0f902, +	0xf0f9018f, +	0x9994efb2, +	0x00e9bb04, +	0x9818e0b6, +	0xec9803eb, +	0x01ed9802, +	0xf900ee98, +	0xfef0fca5, +	0x31f400f8, +/* 0x028f: recv_done */ +	0xf8f0fc01, +/* 0x0291: init */ +	0x01084100, +	0xe70011cf, +	0xb6010911, +	0x14fe0814, +	0x00e04100, +	0x000013f0, +	0x0001f61c, +	0xff0104bd, +	0x01f61400, +	0x0104bd00, +	0x0015f102, +	0xf6100008, +	0x04bd0001, +	0xf000d241, +	0x10fe0013, +	0x1031f400, +	0x38000101, +	0xbd0001f6, +/* 0x02db: init_proc */ +	0x98580f04, +	0x16b001f1, +	0xfa0bf400, +	0xf0b615f9, +	0xf20ef458, +/* 0x02ec: host_send */ +	0xcf04b041, +	0xa0420011, +	0x0022cf04, +	0x0bf412a6, +	0x071ec42e, +	0xb704ee94, +	0x980270e0, +	0xec9803eb, +	0x01ed9802, +	0x7e00ee98, +	0xb600023f, +	0x1ec40110, +	0x04b0400f, +	0xbd000ef6, +	0xc70ef404, +/* 0x0328: host_send_done */ +/* 0x032a: host_recv */ +	0x494100f8, +	0x5413f14e, +	0xf4e1a652, +/* 0x0336: host_recv_wait */ +	0xcc41b90b, +	0x0011cf04, +	0xcf04c842, +	0x16f00022, +	0xf412a608, +	0x23c4ef0b, +	0x0434b607, +	0x02f030b7, +	0xb5033bb5, +	0x3db5023c, +	0x003eb501, +	0xf00120b6, +	0xc8400f24, +	0x0002f604, +	0x400204bd, +	0x02f60000, +	0xf804bd00, +/* 0x0379: host_init */ +	0x00804100, +	0xf11014b6, +	0x40027015, +	0x01f604d0, +	0x4104bd00, +	0x14b60080, +	0xf015f110, +	0x04dc4002, +	0xbd0001f6, +	0x40010104, +	0x01f604c4, +	0xf804bd00, +/* 0x03a9: memx_func_enter */ +	0x40040600, +	0x06f607e0, +/* 0x03b3: memx_func_enter_wait */ +	0x4604bd00, +	0x66cf07c0, +	0x0464f000, +	0x98f70bf4, +	0x10b60016, +/* 0x03c7: memx_func_leave */ +	0x0600f804, +	0x07e44004, +	0xbd0006f6, +/* 0x03d1: memx_func_leave_wait */ +	0x07c04604, +	0xf00066cf, +	0x1bf40464, +/* 0x03df: memx_func_wr32 */ +	0x9800f8f7, +	0x15980016, +	0x0810b601, +	0x50f960f9, +	0xe0fcd0fc, +	0x00002e7e, +	0x140003f1, +	0xa00506fd, +	0xb604bd05, +	0x1bf40242, +/* 0x0407: memx_func_wait */ +	0x0800f8dd, +	0x0088cf2c, +	0x98001e98, +	0x1c98011d, +	0x031b9802, +	0x7e1010b6, +	0xf8000071, +/* 0x0421: memx_func_delay */ +	0x001e9800, +	0x7e0410b6, +	0xf800005d, +/* 0x042d: memx_exec */ +	0xf9e0f900, +	0xb2c1b2d0, +/* 0x0435: memx_exec_next */ +	0x001398b2, +	0x950410b6, +	0x30f01034, +	0xde35980c, +	0x12a655f9, +	0xfced1ef4, +	0x7ee0fcd0, +	0xf800023f, +/* 0x0455: memx_info */ +	0x03ac4c00, +	0x7e08004b, +	0xf800023f, +/* 0x0461: memx_recv */ +	0x01d6b000, +	0xb0c90bf4, +	0x0bf400d6, +/* 0x046f: memx_init */ +	0xf800f8eb, +/* 0x0471: perf_recv */ +/* 0x0473: perf_init */ +	0xf800f800, +/* 0x0475: i2c_drive_scl */ +	0x0036b000, +	0x400d0bf4, +	0x01f607e0, +	0xf804bd00, +/* 0x0485: i2c_drive_scl_lo */ +	0x07e44000, +	0xbd0001f6, +/* 0x048f: i2c_drive_sda */ +	0xb000f804, +	0x0bf40036, +	0x07e0400d, +	0xbd0002f6, +/* 0x049f: i2c_drive_sda_lo */ +	0x4000f804, +	0x02f607e4, +	0xf804bd00, +/* 0x04a9: i2c_sense_scl */ +	0x0132f400, +	0xcf07c443, +	0x31fd0033, +	0x060bf404, +/* 0x04bb: i2c_sense_scl_done */ +	0xf80131f4, +/* 0x04bd: i2c_sense_sda */ +	0x0132f400, +	0xcf07c443, +	0x32fd0033, +	0x060bf404, +/* 0x04cf: i2c_sense_sda_done */ +	0xf80131f4, +/* 0x04d1: i2c_raise_scl */ +	0x4440f900, +	0x01030898, +	0x0004757e, +/* 0x04dc: i2c_raise_scl_wait */ +	0x7e03e84e, +	0x7e00005d, +	0xf40004a9, +	0x42b60901, +	0xef1bf401, +/* 0x04f0: i2c_raise_scl_done */ +	0x00f840fc, +/* 0x04f4: i2c_start */ +	0x0004a97e, +	0x7e0d11f4, +	0xf40004bd, +	0x0ef40611, +/* 0x0505: i2c_start_rep */ +	0x7e00032e, +	0x03000475, +	0x048f7e01, +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0xd17e50fc, +	0x64b60004, +	0x1d11f404, +/* 0x0530: i2c_start_send */ +	0x8f7e0003, +	0x884e0004, +	0x005d7e13, +	0x7e000300, +	0x4e000475, +	0x5d7e1388, +/* 0x054a: i2c_start_out */ +	0x00f80000, +/* 0x054c: i2c_stop */ +	0x757e0003, +	0x00030004, +	0x00048f7e, +	0x7e03e84e, +	0x0300005d, +	0x04757e01, +	0x13884e00, +	0x00005d7e, +	0x8f7e0103, +	0x884e0004, +	0x005d7e13, +/* 0x057b: i2c_bitw */ +	0x7e00f800, +	0x4e00048f, +	0x5d7e03e8, +	0x76bb0000, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0x7e50fc04, +	0xb60004d1, +	0x11f40464, +	0x13884e17, +	0x00005d7e, +	0x757e0003, +	0x884e0004, +	0x005d7e13, +/* 0x05b9: i2c_bitw_out */ +/* 0x05bb: i2c_bitr */ +	0x0300f800, +	0x048f7e01, +	0x03e84e00, +	0x00005d7e, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x04d17e50, +	0x0464b600, +	0x7e1a11f4, +	0x030004bd, +	0x04757e00, +	0x13884e00, +	0x00005d7e, +	0xf4013cf0, +/* 0x05fe: i2c_bitr_done */ +	0x00f80131, +/* 0x0600: i2c_get_byte */ +	0x08040005, +/* 0x0604: i2c_get_byte_next */ +	0xbb0154b6, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x0005bb7e, +	0xf40464b6, +	0x53fd2a11, +	0x0142b605, +	0x03d81bf4, +	0x0076bb01, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x7b7e50fc, +	0x64b60005, +/* 0x064d: i2c_get_byte_done */ +/* 0x064f: i2c_put_byte */ +	0x0400f804, +/* 0x0651: i2c_put_byte_next */ +	0x0142b608, +	0xbb3854ff, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x00057b7e, +	0xf40464b6, +	0x46b03411, +	0xd81bf400, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x05bb7e50, +	0x0464b600, +	0xbb0f11f4, +	0x36b00076, +	0x061bf401, +/* 0x06a7: i2c_put_byte_done */ +	0xf80132f4, +/* 0x06a9: i2c_addr */ +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0xf47e50fc, +	0x64b60004, +	0x2911f404, +	0x012ec3e7, +	0xfd0134b6, +	0x76bb0553, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0x7e50fc04, +	0xb600064f, +/* 0x06ee: i2c_addr_done */ +	0x00f80464, +/* 0x06f0: i2c_acquire_addr */ +	0xb6f8cec7, +	0xe0b705e4, +	0x00f8d014, +/* 0x06fc: i2c_acquire */ +	0x0006f07e, +	0x0000047e, +	0x7e03d9f0, +	0xf800002e, +/* 0x070d: i2c_release */ +	0x06f07e00, +	0x00047e00, +	0x03daf000, +	0x00002e7e, +/* 0x071e: i2c_recv */ +	0x32f400f8, +	0xf8c1c701, +	0xb00214b6, +	0x1ff52816, +	0x13b80137, +	0x98000bd4, +	0x13b80032, +	0x98000bac, +	0x31f40031, +	0xf9d0f902, +	0xf1d0f9e0, +	0xf1000067, +	0x92100063, +	0x76bb0167, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0x7e50fc04, +	0xb60006fc, +	0xd0fc0464, +	0xf500d6b0, +	0x0500b01b, +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0xa97e50fc, +	0x64b60006, +	0xcc11f504, +	0xe0c5c700, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x064f7e50, +	0x0464b600, +	0x00a911f5, +	0x76bb0105, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0x7e50fc04, +	0xb60006a9, +	0x11f50464, +	0x76bb0087, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0x7e50fc04, +	0xb6000600, +	0x11f40464, +	0xe05bcb67, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x054c7e50, +	0x0464b600, +	0x74bd5bb2, +/* 0x0823: i2c_recv_not_rd08 */ +	0xb0410ef4, +	0x1bf401d6, +	0x7e00053b, +	0xf40006a9, +	0xc5c73211, +	0x064f7ee0, +	0x2811f400, +	0xa97e0005, +	0x11f40006, +	0xe0b5c71f, +	0x00064f7e, +	0x7e1511f4, +	0xbd00054c, +	0x08c5c774, +	0xf4091bf4, +	0x0ef40232, +/* 0x0861: i2c_recv_not_wr08 */ +/* 0x0861: i2c_recv_done */ +	0xf8cec703, +	0x00070d7e, +	0xd0fce0fc, +	0xb20912f4, +	0x023f7e7c, +/* 0x0875: i2c_recv_exit */ +/* 0x0877: i2c_init */ +	0xf800f800, +/* 0x0879: test_recv */ +	0x04584100, +	0xb60011cf, +	0x58400110, +	0x0001f604, +	0xe7f104bd, +	0xe3f1d900, +	0x967e134f, +	0x00f80001, +/* 0x0898: test_init */ +	0x7e08004e, +	0xf8000196, +/* 0x08a1: idle_recv */ +/* 0x08a3: idle */ +	0xf400f800, +	0x54410031, +	0x0011cf04, +	0x400110b6, +	0x01f60454, +/* 0x08b7: idle_loop */ +	0x0104bd00, +	0x0232f458, +/* 0x08bc: idle_proc */ +/* 0x08bc: idle_proc_exec */ +	0x1eb210f9, +	0x0002487e, +	0x11f410fc, +	0x0231f409, +/* 0x08cf: idle_proc_next */ +	0xb6f00ef4, +	0x1fa65810, +	0xf4e81bf4, +	0x28f4e002, +	0xc60ef400, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc new file mode 100644 index 00000000000..6744fcc0615 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc @@ -0,0 +1,66 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#define NVKM_PPWR_CHIPSET GT215 + +//#define NVKM_FALCON_PC24 +//#define NVKM_FALCON_UNSHIFTED_IO +//#define NVKM_FALCON_MMIO_UAS +//#define NVKM_FALCON_MMIO_TRAP + +#include "macros.fuc" + +.section #nva3_pwr_data +#define INCLUDE_PROC +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_PROC + +#define INCLUDE_DATA +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_DATA +.align 256 + +.section #nva3_pwr_code +#define INCLUDE_CODE +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_CODE +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h new file mode 100644 index 00000000000..254205cd516 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nva3.fuc.h @@ -0,0 +1,1589 @@ +uint32_t nva3_pwr_data[] = { +/* 0x0000: proc_kern */ +	0x52544e49, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0058: proc_list_head */ +	0x54534f48, +	0x00000430, +	0x000003cd, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x584d454d, +	0x0000054e, +	0x00000540, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x46524550, +	0x00000552, +	0x00000550, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x5f433249, +	0x00000982, +	0x00000825, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x54534554, +	0x000009ab, +	0x00000984, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x454c4449, +	0x000009b7, +	0x000009b5, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ +	0x00000000, +/* 0x026c: time_next */ +	0x00000000, +/* 0x0270: fifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x02f0: rfifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0370: memx_func_head */ +	0x00010000, +	0x00000000, +	0x0000046f, +/* 0x037c: memx_func_next */ +	0x00000001, +	0x00000000, +	0x00000496, +	0x00000002, +	0x00000002, +	0x000004b7, +	0x00040003, +	0x00000000, +	0x000004df, +	0x00010004, +	0x00000000, +	0x000004fc, +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ +	0x00001000, +	0x00004000, +	0x00010000, +	0x00000100, +	0x00040000, +	0x00100000, +	0x00400000, +	0x01000000, +	0x04000000, +	0x10000000, +/* 0x0bd4: i2c_sda_map */ +	0x00002000, +	0x00008000, +	0x00020000, +	0x00000200, +	0x00080000, +	0x00200000, +	0x00800000, +	0x02000000, +	0x08000000, +	0x20000000, +/* 0x0bfc: i2c_ctrl */ +	0x0000e138, +	0x0000e150, +	0x0000e168, +	0x0000e180, +	0x0000e254, +	0x0000e274, +	0x0000e764, +	0x0000e780, +	0x0000e79c, +	0x0000e7b8, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; + +uint32_t nva3_pwr_code[] = { +	0x030d0ef5, +/* 0x0004: rd32 */ +	0x07a007f1, +	0xd00604b6, +	0x04bd000e, +	0xf001d7f0, +	0x07f101d3, +	0x04b607ac, +	0x000dd006, +/* 0x0022: rd32_wait */ +	0xd7f104bd, +	0xd4b607ac, +	0x00ddcf06, +	0x7000d4f1, +	0xf1f21bf4, +	0xb607a4d7, +	0xddcf06d4, +/* 0x003f: wr32 */ +	0xf100f800, +	0xb607a007, +	0x0ed00604, +	0xf104bd00, +	0xb607a407, +	0x0dd00604, +	0xf004bd00, +	0xd5f002d7, +	0x01d3f0f0, +	0x07ac07f1, +	0xd00604b6, +	0x04bd000d, +/* 0x006c: wr32_wait */ +	0x07acd7f1, +	0xcf06d4b6, +	0xd4f100dd, +	0x1bf47000, +/* 0x007f: nsec */ +	0xf000f8f2, +	0x84b62c87, +	0x0088cf06, +/* 0x0088: nsec_loop */ +	0xb62c97f0, +	0x99cf0694, +	0x0298bb00, +	0xf4069eb8, +	0x00f8f11e, +/* 0x009c: wait */ +	0xb62c87f0, +	0x88cf0684, +/* 0x00a5: wait_loop */ +	0x02eeb900, +	0xb90421f4, +	0xadfd02da, +	0x06acb804, +	0xf0150bf4, +	0x94b62c97, +	0x0099cf06, +	0xb80298bb, +	0x1ef4069b, +/* 0x00c9: wait_done */ +/* 0x00cb: intr_watchdog */ +	0x9800f8df, +	0x96b003e9, +	0x2a0bf400, +	0xbb9a0a98, +	0x1cf4029a, +	0x01d7f00f, +	0x025421f5, +	0x0ef494bd, +/* 0x00e9: intr_watchdog_next_time */ +	0x9b0a9815, +	0xf400a6b0, +	0x9ab8090b, +	0x061cf406, +/* 0x00f8: intr_watchdog_next_time_set */ +/* 0x00fb: intr_watchdog_next_proc */ +	0x809b0980, +	0xe0b603e9, +	0x68e6b158, +	0xc61bf402, +/* 0x010a: intr */ +	0x00f900f8, +	0x80f904bd, +	0xa0f990f9, +	0xc0f9b0f9, +	0xe0f9d0f9, +	0xf7f0f0f9, +	0x0188fe00, +	0x87f180f9, +	0x84b605d0, +	0x0088cf06, +	0xf10180b6, +	0xb605d007, +	0x08d00604, +	0xf004bd00, +	0x84b60887, +	0x0088cf06, +	0xf40289c4, +	0x0080230b, +	0x58e7f09b, +	0x98cb21f4, +	0x96b09b09, +	0x110bf400, +	0xb63407f0, +	0x09d00604, +	0x8004bd00, +/* 0x016e: intr_skip_watchdog */ +	0x89e49a09, +	0x0bf40800, +	0x8897f148, +	0x0694b606, +	0xc40099cf, +	0x0bf4029a, +	0xc0c7f12c, +	0x06c4b604, +	0xf900cccf, +	0x48e7f1c0, +	0x53e3f14f, +	0x00d7f054, +	0x02b921f5, +	0x07f1c0fc, +	0x04b604c0, +	0x000cd006, +/* 0x01ae: intr_subintr_skip_fifo */ +	0x07f104bd, +	0x04b60688, +	0x0009d006, +/* 0x01ba: intr_skip_subintr */ +	0x89c404bd, +	0x070bf420, +	0xffbfa4f1, +/* 0x01c4: intr_skip_pause */ +	0xf44089c4, +	0xa4f1070b, +/* 0x01ce: intr_skip_user0 */ +	0x07f0ffbf, +	0x0604b604, +	0xbd0008d0, +	0xfe80fc04, +	0xf0fc0088, +	0xd0fce0fc, +	0xb0fcc0fc, +	0x90fca0fc, +	0x00fc80fc, +	0xf80032f4, +/* 0x01f5: timer */ +	0x1032f401, +	0xb003f898, +	0x1cf40086, +	0x03fe8051, +	0xb63807f0, +	0x08d00604, +	0xf004bd00, +	0x84b60887, +	0x0088cf06, +	0xf40284f0, +	0x87f0261b, +	0x0684b634, +	0xb80088cf, +	0x0bf406e0, +	0x06e8b809, +/* 0x0233: timer_reset */ +	0xf01f1ef4, +	0x04b63407, +	0x000ed006, +	0x0e8004bd, +/* 0x0241: timer_enable */ +	0x0187f09a, +	0xb63807f0, +	0x08d00604, +/* 0x024f: timer_done */ +	0xf404bd00, +	0x00f81031, +/* 0x0254: send_proc */ +	0x90f980f9, +	0x9805e898, +	0x86f004e9, +	0x0689b804, +	0xc42a0bf4, +	0x88940398, +	0x1880b604, +	0x98008ebb, +	0x8a8000fa, +	0x018d8000, +	0x80028c80, +	0x90b6038b, +	0x0794f001, +	0xf404e980, +/* 0x028e: send_done */ +	0x90fc0231, +	0x00f880fc, +/* 0x0294: find */ +	0x87f080f9, +	0x0131f458, +/* 0x029c: find_loop */ +	0xb8008a98, +	0x0bf406ae, +	0x5880b610, +	0x026886b1, +	0xf4f01bf4, +/* 0x02b2: find_done */ +	0x8eb90132, +	0xf880fc02, +/* 0x02b9: send */ +	0x9421f500, +	0x9701f402, +/* 0x02c2: recv */ +	0xe89800f8, +	0x04e99805, +	0xb80132f4, +	0x0bf40689, +	0x0389c43d, +	0xf00180b6, +	0xe8800784, +	0x02ea9805, +	0x8ffef0f9, +	0xb9f0f901, +	0x999402ef, +	0x00e9bb04, +	0x9818e0b6, +	0xec9803eb, +	0x01ed9802, +	0xf900ee98, +	0xfef0fca5, +	0x31f400f8, +/* 0x030b: recv_done */ +	0xf8f0fc01, +/* 0x030d: init */ +	0x0817f100, +	0x0614b601, +	0xe70011cf, +	0xb6010911, +	0x14fe0814, +	0xe017f100, +	0x0013f000, +	0xb61c07f0, +	0x01d00604, +	0xf004bd00, +	0x07f0ff17, +	0x0604b614, +	0xbd0001d0, +	0x0217f004, +	0x080015f1, +	0xb61007f0, +	0x01d00604, +	0xf104bd00, +	0xf0010a17, +	0x10fe0013, +	0x1031f400, +	0xf00117f0, +	0x04b63807, +	0x0001d006, +	0xf7f004bd, +/* 0x0371: init_proc */ +	0x01f19858, +	0xf40016b0, +	0x15f9fa0b, +	0xf458f0b6, +/* 0x0382: host_send */ +	0x17f1f20e, +	0x14b604b0, +	0x0011cf06, +	0x04a027f1, +	0xcf0624b6, +	0x12b80022, +	0x320bf406, +	0x94071ec4, +	0xe0b704ee, +	0xeb980270, +	0x02ec9803, +	0x9801ed98, +	0x21f500ee, +	0x10b602b9, +	0x0f1ec401, +	0x04b007f1, +	0xd00604b6, +	0x04bd000e, +/* 0x03cb: host_send_done */ +	0xf8ba0ef4, +/* 0x03cd: host_recv */ +	0x4917f100, +	0x5413f14e, +	0x06e1b852, +/* 0x03db: host_recv_wait */ +	0xf1aa0bf4, +	0xb604cc17, +	0x11cf0614, +	0xc827f100, +	0x0624b604, +	0xf00022cf, +	0x12b80816, +	0xe60bf406, +	0xb60723c4, +	0x30b70434, +	0x3b8002f0, +	0x023c8003, +	0x80013d80, +	0x20b6003e, +	0x0f24f001, +	0x04c807f1, +	0xd00604b6, +	0x04bd0002, +	0xf04027f0, +	0x04b60007, +	0x0002d006, +	0x00f804bd, +/* 0x0430: host_init */ +	0x008017f1, +	0xf11014b6, +	0xf1027015, +	0xb604d007, +	0x01d00604, +	0xf104bd00, +	0xb6008017, +	0x15f11014, +	0x07f102f0, +	0x04b604dc, +	0x0001d006, +	0x17f004bd, +	0xc407f101, +	0x0604b604, +	0xbd0001d0, +/* 0x046f: memx_func_enter */ +	0xf000f804, +	0x07f10467, +	0x04b607e0, +	0x0006d006, +/* 0x047e: memx_func_enter_wait */ +	0x67f104bd, +	0x64b607c0, +	0x0066cf06, +	0xf40464f0, +	0x1698f30b, +	0x0410b600, +/* 0x0496: memx_func_leave */ +	0x67f000f8, +	0xe407f104, +	0x0604b607, +	0xbd0006d0, +/* 0x04a5: memx_func_leave_wait */ +	0xc067f104, +	0x0664b607, +	0xf00066cf, +	0x1bf40464, +/* 0x04b7: memx_func_wr32 */ +	0x9800f8f3, +	0x15980016, +	0x0810b601, +	0x50f960f9, +	0xe0fcd0fc, +	0xf13f21f4, +	0xfd140003, +	0x05800506, +	0xb604bd00, +	0x1bf40242, +/* 0x04df: memx_func_wait */ +	0xf000f8dd, +	0x84b62c87, +	0x0088cf06, +	0x98001e98, +	0x1c98011d, +	0x031b9802, +	0xf41010b6, +	0x00f89c21, +/* 0x04fc: memx_func_delay */ +	0xb6001e98, +	0x21f40410, +/* 0x0507: memx_exec */ +	0xf900f87f, +	0xb9d0f9e0, +	0xb2b902c1, +/* 0x0511: memx_exec_next */ +	0x00139802, +	0x950410b6, +	0x30f01034, +	0xde35980c, +	0x12b855f9, +	0xec1ef406, +	0xe0fcd0fc, +	0x02b921f5, +/* 0x0532: memx_info */ +	0xc7f100f8, +	0xb7f103ac, +	0x21f50800, +	0x00f802b9, +/* 0x0540: memx_recv */ +	0xf401d6b0, +	0xd6b0c40b, +	0xe90bf400, +/* 0x054e: memx_init */ +	0x00f800f8, +/* 0x0550: perf_recv */ +/* 0x0552: perf_init */ +	0x00f800f8, +/* 0x0554: i2c_drive_scl */ +	0xf40036b0, +	0x07f1110b, +	0x04b607e0, +	0x0001d006, +	0x00f804bd, +/* 0x0568: i2c_drive_scl_lo */ +	0x07e407f1, +	0xd00604b6, +	0x04bd0001, +/* 0x0576: i2c_drive_sda */ +	0x36b000f8, +	0x110bf400, +	0x07e007f1, +	0xd00604b6, +	0x04bd0002, +/* 0x058a: i2c_drive_sda_lo */ +	0x07f100f8, +	0x04b607e4, +	0x0002d006, +	0x00f804bd, +/* 0x0598: i2c_sense_scl */ +	0xf10132f4, +	0xb607c437, +	0x33cf0634, +	0x0431fd00, +	0xf4060bf4, +/* 0x05ae: i2c_sense_scl_done */ +	0x00f80131, +/* 0x05b0: i2c_sense_sda */ +	0xf10132f4, +	0xb607c437, +	0x33cf0634, +	0x0432fd00, +	0xf4060bf4, +/* 0x05c6: i2c_sense_sda_done */ +	0x00f80131, +/* 0x05c8: i2c_raise_scl */ +	0x47f140f9, +	0x37f00898, +	0x5421f501, +/* 0x05d5: i2c_raise_scl_wait */ +	0xe8e7f105, +	0x7f21f403, +	0x059821f5, +	0xb60901f4, +	0x1bf40142, +/* 0x05e9: i2c_raise_scl_done */ +	0xf840fcef, +/* 0x05ed: i2c_start */ +	0x9821f500, +	0x0d11f405, +	0x05b021f5, +	0xf40611f4, +/* 0x05fe: i2c_start_rep */ +	0x37f0300e, +	0x5421f500, +	0x0137f005, +	0x057621f5, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0xc821f550, +	0x0464b605, +/* 0x062b: i2c_start_send */ +	0xf01f11f4, +	0x21f50037, +	0xe7f10576, +	0x21f41388, +	0x0037f07f, +	0x055421f5, +	0x1388e7f1, +/* 0x0647: i2c_start_out */ +	0xf87f21f4, +/* 0x0649: i2c_stop */ +	0x0037f000, +	0x055421f5, +	0xf50037f0, +	0xf1057621, +	0xf403e8e7, +	0x37f07f21, +	0x5421f501, +	0x88e7f105, +	0x7f21f413, +	0xf50137f0, +	0xf1057621, +	0xf41388e7, +	0x00f87f21, +/* 0x067c: i2c_bitw */ +	0x057621f5, +	0x03e8e7f1, +	0xbb7f21f4, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x05c821f5, +	0xf40464b6, +	0xe7f11811, +	0x21f41388, +	0x0037f07f, +	0x055421f5, +	0x1388e7f1, +/* 0x06bb: i2c_bitw_out */ +	0xf87f21f4, +/* 0x06bd: i2c_bitr */ +	0x0137f000, +	0x057621f5, +	0x03e8e7f1, +	0xbb7f21f4, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x05c821f5, +	0xf40464b6, +	0x21f51b11, +	0x37f005b0, +	0x5421f500, +	0x88e7f105, +	0x7f21f413, +	0xf4013cf0, +/* 0x0702: i2c_bitr_done */ +	0x00f80131, +/* 0x0704: i2c_get_byte */ +	0xf00057f0, +/* 0x070a: i2c_get_byte_next */ +	0x54b60847, +	0x0076bb01, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b606bd, +	0x2b11f404, +	0xb60553fd, +	0x1bf40142, +	0x0137f0d8, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x7c21f550, +	0x0464b606, +/* 0x0754: i2c_get_byte_done */ +/* 0x0756: i2c_put_byte */ +	0x47f000f8, +/* 0x0759: i2c_put_byte_next */ +	0x0142b608, +	0xbb3854ff, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x067c21f5, +	0xf40464b6, +	0x46b03411, +	0xd81bf400, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0xbd21f550, +	0x0464b606, +	0xbb0f11f4, +	0x36b00076, +	0x061bf401, +/* 0x07af: i2c_put_byte_done */ +	0xf80132f4, +/* 0x07b1: i2c_addr */ +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b605ed, +	0x2911f404, +	0x012ec3e7, +	0xfd0134b6, +	0x76bb0553, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb6075621, +/* 0x07f6: i2c_addr_done */ +	0x00f80464, +/* 0x07f8: i2c_acquire_addr */ +	0xb6f8cec7, +	0xe0b702e4, +	0xee980bfc, +/* 0x0807: i2c_acquire */ +	0xf500f800, +	0xf407f821, +	0xd9f00421, +	0x3f21f403, +/* 0x0816: i2c_release */ +	0x21f500f8, +	0x21f407f8, +	0x03daf004, +	0xf83f21f4, +/* 0x0825: i2c_recv */ +	0x0132f400, +	0xb6f8c1c7, +	0x16b00214, +	0x3a1ff528, +	0xd413a001, +	0x0032980b, +	0x0bac13a0, +	0xf4003198, +	0xd0f90231, +	0xd0f9e0f9, +	0x000067f1, +	0x100063f1, +	0xbb016792, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x080721f5, +	0xfc0464b6, +	0x00d6b0d0, +	0x00b31bf5, +	0xbb0057f0, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x07b121f5, +	0xf50464b6, +	0xc700d011, +	0x76bbe0c5, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb6075621, +	0x11f50464, +	0x57f000ad, +	0x0076bb01, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b607b1, +	0x8a11f504, +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b60704, +	0x6a11f404, +	0xbbe05bcb, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x064921f5, +	0xb90464b6, +	0x74bd025b, +/* 0x092b: i2c_recv_not_rd08 */ +	0xb0430ef4, +	0x1bf401d6, +	0x0057f03d, +	0x07b121f5, +	0xc73311f4, +	0x21f5e0c5, +	0x11f40756, +	0x0057f029, +	0x07b121f5, +	0xc71f11f4, +	0x21f5e0b5, +	0x11f40756, +	0x4921f515, +	0xc774bd06, +	0x1bf408c5, +	0x0232f409, +/* 0x096b: i2c_recv_not_wr08 */ +/* 0x096b: i2c_recv_done */ +	0xc7030ef4, +	0x21f5f8ce, +	0xe0fc0816, +	0x12f4d0fc, +	0x027cb90a, +	0x02b921f5, +/* 0x0980: i2c_recv_exit */ +/* 0x0982: i2c_init */ +	0x00f800f8, +/* 0x0984: test_recv */ +	0x05d817f1, +	0xcf0614b6, +	0x10b60011, +	0xd807f101, +	0x0604b605, +	0xbd0001d0, +	0x00e7f104, +	0x4fe3f1d9, +	0xf521f513, +/* 0x09ab: test_init */ +	0xf100f801, +	0xf50800e7, +	0xf801f521, +/* 0x09b5: idle_recv */ +/* 0x09b7: idle */ +	0xf400f800, +	0x17f10031, +	0x14b605d4, +	0x0011cf06, +	0xf10110b6, +	0xb605d407, +	0x01d00604, +/* 0x09d3: idle_loop */ +	0xf004bd00, +	0x32f45817, +/* 0x09d9: idle_proc */ +/* 0x09d9: idle_proc_exec */ +	0xb910f902, +	0x21f5021e, +	0x10fc02c2, +	0xf40911f4, +	0x0ef40231, +/* 0x09ed: idle_proc_next */ +	0x5810b6ef, +	0xf4061fb8, +	0x02f4e61b, +	0x0028f4dd, +	0x00bb0ef4, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc new file mode 100644 index 00000000000..48f79434a44 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc @@ -0,0 +1,66 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#define NVKM_PPWR_CHIPSET GF100 + +//#define NVKM_FALCON_PC24 +//#define NVKM_FALCON_UNSHIFTED_IO +//#define NVKM_FALCON_MMIO_UAS +//#define NVKM_FALCON_MMIO_TRAP + +#include "macros.fuc" + +.section #nvc0_pwr_data +#define INCLUDE_PROC +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_PROC + +#define INCLUDE_DATA +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_DATA +.align 256 + +.section #nvc0_pwr_code +#define INCLUDE_CODE +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_CODE +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h new file mode 100644 index 00000000000..7ac87405d01 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvc0.fuc.h @@ -0,0 +1,1589 @@ +uint32_t nvc0_pwr_data[] = { +/* 0x0000: proc_kern */ +	0x52544e49, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0058: proc_list_head */ +	0x54534f48, +	0x00000430, +	0x000003cd, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x584d454d, +	0x0000054e, +	0x00000540, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x46524550, +	0x00000552, +	0x00000550, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x5f433249, +	0x00000982, +	0x00000825, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x54534554, +	0x000009ab, +	0x00000984, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x454c4449, +	0x000009b7, +	0x000009b5, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ +	0x00000000, +/* 0x026c: time_next */ +	0x00000000, +/* 0x0270: fifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x02f0: rfifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0370: memx_func_head */ +	0x00010000, +	0x00000000, +	0x0000046f, +/* 0x037c: memx_func_next */ +	0x00000001, +	0x00000000, +	0x00000496, +	0x00000002, +	0x00000002, +	0x000004b7, +	0x00040003, +	0x00000000, +	0x000004df, +	0x00010004, +	0x00000000, +	0x000004fc, +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ +	0x00001000, +	0x00004000, +	0x00010000, +	0x00000100, +	0x00040000, +	0x00100000, +	0x00400000, +	0x01000000, +	0x04000000, +	0x10000000, +/* 0x0bd4: i2c_sda_map */ +	0x00002000, +	0x00008000, +	0x00020000, +	0x00000200, +	0x00080000, +	0x00200000, +	0x00800000, +	0x02000000, +	0x08000000, +	0x20000000, +/* 0x0bfc: i2c_ctrl */ +	0x0000e138, +	0x0000e150, +	0x0000e168, +	0x0000e180, +	0x0000e254, +	0x0000e274, +	0x0000e764, +	0x0000e780, +	0x0000e79c, +	0x0000e7b8, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; + +uint32_t nvc0_pwr_code[] = { +	0x030d0ef5, +/* 0x0004: rd32 */ +	0x07a007f1, +	0xd00604b6, +	0x04bd000e, +	0xf001d7f0, +	0x07f101d3, +	0x04b607ac, +	0x000dd006, +/* 0x0022: rd32_wait */ +	0xd7f104bd, +	0xd4b607ac, +	0x00ddcf06, +	0x7000d4f1, +	0xf1f21bf4, +	0xb607a4d7, +	0xddcf06d4, +/* 0x003f: wr32 */ +	0xf100f800, +	0xb607a007, +	0x0ed00604, +	0xf104bd00, +	0xb607a407, +	0x0dd00604, +	0xf004bd00, +	0xd5f002d7, +	0x01d3f0f0, +	0x07ac07f1, +	0xd00604b6, +	0x04bd000d, +/* 0x006c: wr32_wait */ +	0x07acd7f1, +	0xcf06d4b6, +	0xd4f100dd, +	0x1bf47000, +/* 0x007f: nsec */ +	0xf000f8f2, +	0x84b62c87, +	0x0088cf06, +/* 0x0088: nsec_loop */ +	0xb62c97f0, +	0x99cf0694, +	0x0298bb00, +	0xf4069eb8, +	0x00f8f11e, +/* 0x009c: wait */ +	0xb62c87f0, +	0x88cf0684, +/* 0x00a5: wait_loop */ +	0x02eeb900, +	0xb90421f4, +	0xadfd02da, +	0x06acb804, +	0xf0150bf4, +	0x94b62c97, +	0x0099cf06, +	0xb80298bb, +	0x1ef4069b, +/* 0x00c9: wait_done */ +/* 0x00cb: intr_watchdog */ +	0x9800f8df, +	0x96b003e9, +	0x2a0bf400, +	0xbb9a0a98, +	0x1cf4029a, +	0x01d7f00f, +	0x025421f5, +	0x0ef494bd, +/* 0x00e9: intr_watchdog_next_time */ +	0x9b0a9815, +	0xf400a6b0, +	0x9ab8090b, +	0x061cf406, +/* 0x00f8: intr_watchdog_next_time_set */ +/* 0x00fb: intr_watchdog_next_proc */ +	0x809b0980, +	0xe0b603e9, +	0x68e6b158, +	0xc61bf402, +/* 0x010a: intr */ +	0x00f900f8, +	0x80f904bd, +	0xa0f990f9, +	0xc0f9b0f9, +	0xe0f9d0f9, +	0xf7f0f0f9, +	0x0188fe00, +	0x87f180f9, +	0x84b605d0, +	0x0088cf06, +	0xf10180b6, +	0xb605d007, +	0x08d00604, +	0xf004bd00, +	0x84b60887, +	0x0088cf06, +	0xf40289c4, +	0x0080230b, +	0x58e7f09b, +	0x98cb21f4, +	0x96b09b09, +	0x110bf400, +	0xb63407f0, +	0x09d00604, +	0x8004bd00, +/* 0x016e: intr_skip_watchdog */ +	0x89e49a09, +	0x0bf40800, +	0x8897f148, +	0x0694b606, +	0xc40099cf, +	0x0bf4029a, +	0xc0c7f12c, +	0x06c4b604, +	0xf900cccf, +	0x48e7f1c0, +	0x53e3f14f, +	0x00d7f054, +	0x02b921f5, +	0x07f1c0fc, +	0x04b604c0, +	0x000cd006, +/* 0x01ae: intr_subintr_skip_fifo */ +	0x07f104bd, +	0x04b60688, +	0x0009d006, +/* 0x01ba: intr_skip_subintr */ +	0x89c404bd, +	0x070bf420, +	0xffbfa4f1, +/* 0x01c4: intr_skip_pause */ +	0xf44089c4, +	0xa4f1070b, +/* 0x01ce: intr_skip_user0 */ +	0x07f0ffbf, +	0x0604b604, +	0xbd0008d0, +	0xfe80fc04, +	0xf0fc0088, +	0xd0fce0fc, +	0xb0fcc0fc, +	0x90fca0fc, +	0x00fc80fc, +	0xf80032f4, +/* 0x01f5: timer */ +	0x1032f401, +	0xb003f898, +	0x1cf40086, +	0x03fe8051, +	0xb63807f0, +	0x08d00604, +	0xf004bd00, +	0x84b60887, +	0x0088cf06, +	0xf40284f0, +	0x87f0261b, +	0x0684b634, +	0xb80088cf, +	0x0bf406e0, +	0x06e8b809, +/* 0x0233: timer_reset */ +	0xf01f1ef4, +	0x04b63407, +	0x000ed006, +	0x0e8004bd, +/* 0x0241: timer_enable */ +	0x0187f09a, +	0xb63807f0, +	0x08d00604, +/* 0x024f: timer_done */ +	0xf404bd00, +	0x00f81031, +/* 0x0254: send_proc */ +	0x90f980f9, +	0x9805e898, +	0x86f004e9, +	0x0689b804, +	0xc42a0bf4, +	0x88940398, +	0x1880b604, +	0x98008ebb, +	0x8a8000fa, +	0x018d8000, +	0x80028c80, +	0x90b6038b, +	0x0794f001, +	0xf404e980, +/* 0x028e: send_done */ +	0x90fc0231, +	0x00f880fc, +/* 0x0294: find */ +	0x87f080f9, +	0x0131f458, +/* 0x029c: find_loop */ +	0xb8008a98, +	0x0bf406ae, +	0x5880b610, +	0x026886b1, +	0xf4f01bf4, +/* 0x02b2: find_done */ +	0x8eb90132, +	0xf880fc02, +/* 0x02b9: send */ +	0x9421f500, +	0x9701f402, +/* 0x02c2: recv */ +	0xe89800f8, +	0x04e99805, +	0xb80132f4, +	0x0bf40689, +	0x0389c43d, +	0xf00180b6, +	0xe8800784, +	0x02ea9805, +	0x8ffef0f9, +	0xb9f0f901, +	0x999402ef, +	0x00e9bb04, +	0x9818e0b6, +	0xec9803eb, +	0x01ed9802, +	0xf900ee98, +	0xfef0fca5, +	0x31f400f8, +/* 0x030b: recv_done */ +	0xf8f0fc01, +/* 0x030d: init */ +	0x0817f100, +	0x0614b601, +	0xe70011cf, +	0xb6010911, +	0x14fe0814, +	0xe017f100, +	0x0013f000, +	0xb61c07f0, +	0x01d00604, +	0xf004bd00, +	0x07f0ff17, +	0x0604b614, +	0xbd0001d0, +	0x0217f004, +	0x080015f1, +	0xb61007f0, +	0x01d00604, +	0xf104bd00, +	0xf0010a17, +	0x10fe0013, +	0x1031f400, +	0xf00117f0, +	0x04b63807, +	0x0001d006, +	0xf7f004bd, +/* 0x0371: init_proc */ +	0x01f19858, +	0xf40016b0, +	0x15f9fa0b, +	0xf458f0b6, +/* 0x0382: host_send */ +	0x17f1f20e, +	0x14b604b0, +	0x0011cf06, +	0x04a027f1, +	0xcf0624b6, +	0x12b80022, +	0x320bf406, +	0x94071ec4, +	0xe0b704ee, +	0xeb980270, +	0x02ec9803, +	0x9801ed98, +	0x21f500ee, +	0x10b602b9, +	0x0f1ec401, +	0x04b007f1, +	0xd00604b6, +	0x04bd000e, +/* 0x03cb: host_send_done */ +	0xf8ba0ef4, +/* 0x03cd: host_recv */ +	0x4917f100, +	0x5413f14e, +	0x06e1b852, +/* 0x03db: host_recv_wait */ +	0xf1aa0bf4, +	0xb604cc17, +	0x11cf0614, +	0xc827f100, +	0x0624b604, +	0xf00022cf, +	0x12b80816, +	0xe60bf406, +	0xb60723c4, +	0x30b70434, +	0x3b8002f0, +	0x023c8003, +	0x80013d80, +	0x20b6003e, +	0x0f24f001, +	0x04c807f1, +	0xd00604b6, +	0x04bd0002, +	0xf04027f0, +	0x04b60007, +	0x0002d006, +	0x00f804bd, +/* 0x0430: host_init */ +	0x008017f1, +	0xf11014b6, +	0xf1027015, +	0xb604d007, +	0x01d00604, +	0xf104bd00, +	0xb6008017, +	0x15f11014, +	0x07f102f0, +	0x04b604dc, +	0x0001d006, +	0x17f004bd, +	0xc407f101, +	0x0604b604, +	0xbd0001d0, +/* 0x046f: memx_func_enter */ +	0xf000f804, +	0x07f10467, +	0x04b607e0, +	0x0006d006, +/* 0x047e: memx_func_enter_wait */ +	0x67f104bd, +	0x64b607c0, +	0x0066cf06, +	0xf40464f0, +	0x1698f30b, +	0x0410b600, +/* 0x0496: memx_func_leave */ +	0x67f000f8, +	0xe407f104, +	0x0604b607, +	0xbd0006d0, +/* 0x04a5: memx_func_leave_wait */ +	0xc067f104, +	0x0664b607, +	0xf00066cf, +	0x1bf40464, +/* 0x04b7: memx_func_wr32 */ +	0x9800f8f3, +	0x15980016, +	0x0810b601, +	0x50f960f9, +	0xe0fcd0fc, +	0xf13f21f4, +	0xfd140003, +	0x05800506, +	0xb604bd00, +	0x1bf40242, +/* 0x04df: memx_func_wait */ +	0xf000f8dd, +	0x84b62c87, +	0x0088cf06, +	0x98001e98, +	0x1c98011d, +	0x031b9802, +	0xf41010b6, +	0x00f89c21, +/* 0x04fc: memx_func_delay */ +	0xb6001e98, +	0x21f40410, +/* 0x0507: memx_exec */ +	0xf900f87f, +	0xb9d0f9e0, +	0xb2b902c1, +/* 0x0511: memx_exec_next */ +	0x00139802, +	0x950410b6, +	0x30f01034, +	0xde35980c, +	0x12b855f9, +	0xec1ef406, +	0xe0fcd0fc, +	0x02b921f5, +/* 0x0532: memx_info */ +	0xc7f100f8, +	0xb7f103ac, +	0x21f50800, +	0x00f802b9, +/* 0x0540: memx_recv */ +	0xf401d6b0, +	0xd6b0c40b, +	0xe90bf400, +/* 0x054e: memx_init */ +	0x00f800f8, +/* 0x0550: perf_recv */ +/* 0x0552: perf_init */ +	0x00f800f8, +/* 0x0554: i2c_drive_scl */ +	0xf40036b0, +	0x07f1110b, +	0x04b607e0, +	0x0001d006, +	0x00f804bd, +/* 0x0568: i2c_drive_scl_lo */ +	0x07e407f1, +	0xd00604b6, +	0x04bd0001, +/* 0x0576: i2c_drive_sda */ +	0x36b000f8, +	0x110bf400, +	0x07e007f1, +	0xd00604b6, +	0x04bd0002, +/* 0x058a: i2c_drive_sda_lo */ +	0x07f100f8, +	0x04b607e4, +	0x0002d006, +	0x00f804bd, +/* 0x0598: i2c_sense_scl */ +	0xf10132f4, +	0xb607c437, +	0x33cf0634, +	0x0431fd00, +	0xf4060bf4, +/* 0x05ae: i2c_sense_scl_done */ +	0x00f80131, +/* 0x05b0: i2c_sense_sda */ +	0xf10132f4, +	0xb607c437, +	0x33cf0634, +	0x0432fd00, +	0xf4060bf4, +/* 0x05c6: i2c_sense_sda_done */ +	0x00f80131, +/* 0x05c8: i2c_raise_scl */ +	0x47f140f9, +	0x37f00898, +	0x5421f501, +/* 0x05d5: i2c_raise_scl_wait */ +	0xe8e7f105, +	0x7f21f403, +	0x059821f5, +	0xb60901f4, +	0x1bf40142, +/* 0x05e9: i2c_raise_scl_done */ +	0xf840fcef, +/* 0x05ed: i2c_start */ +	0x9821f500, +	0x0d11f405, +	0x05b021f5, +	0xf40611f4, +/* 0x05fe: i2c_start_rep */ +	0x37f0300e, +	0x5421f500, +	0x0137f005, +	0x057621f5, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0xc821f550, +	0x0464b605, +/* 0x062b: i2c_start_send */ +	0xf01f11f4, +	0x21f50037, +	0xe7f10576, +	0x21f41388, +	0x0037f07f, +	0x055421f5, +	0x1388e7f1, +/* 0x0647: i2c_start_out */ +	0xf87f21f4, +/* 0x0649: i2c_stop */ +	0x0037f000, +	0x055421f5, +	0xf50037f0, +	0xf1057621, +	0xf403e8e7, +	0x37f07f21, +	0x5421f501, +	0x88e7f105, +	0x7f21f413, +	0xf50137f0, +	0xf1057621, +	0xf41388e7, +	0x00f87f21, +/* 0x067c: i2c_bitw */ +	0x057621f5, +	0x03e8e7f1, +	0xbb7f21f4, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x05c821f5, +	0xf40464b6, +	0xe7f11811, +	0x21f41388, +	0x0037f07f, +	0x055421f5, +	0x1388e7f1, +/* 0x06bb: i2c_bitw_out */ +	0xf87f21f4, +/* 0x06bd: i2c_bitr */ +	0x0137f000, +	0x057621f5, +	0x03e8e7f1, +	0xbb7f21f4, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x05c821f5, +	0xf40464b6, +	0x21f51b11, +	0x37f005b0, +	0x5421f500, +	0x88e7f105, +	0x7f21f413, +	0xf4013cf0, +/* 0x0702: i2c_bitr_done */ +	0x00f80131, +/* 0x0704: i2c_get_byte */ +	0xf00057f0, +/* 0x070a: i2c_get_byte_next */ +	0x54b60847, +	0x0076bb01, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b606bd, +	0x2b11f404, +	0xb60553fd, +	0x1bf40142, +	0x0137f0d8, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x7c21f550, +	0x0464b606, +/* 0x0754: i2c_get_byte_done */ +/* 0x0756: i2c_put_byte */ +	0x47f000f8, +/* 0x0759: i2c_put_byte_next */ +	0x0142b608, +	0xbb3854ff, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x067c21f5, +	0xf40464b6, +	0x46b03411, +	0xd81bf400, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0xbd21f550, +	0x0464b606, +	0xbb0f11f4, +	0x36b00076, +	0x061bf401, +/* 0x07af: i2c_put_byte_done */ +	0xf80132f4, +/* 0x07b1: i2c_addr */ +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b605ed, +	0x2911f404, +	0x012ec3e7, +	0xfd0134b6, +	0x76bb0553, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb6075621, +/* 0x07f6: i2c_addr_done */ +	0x00f80464, +/* 0x07f8: i2c_acquire_addr */ +	0xb6f8cec7, +	0xe0b702e4, +	0xee980bfc, +/* 0x0807: i2c_acquire */ +	0xf500f800, +	0xf407f821, +	0xd9f00421, +	0x3f21f403, +/* 0x0816: i2c_release */ +	0x21f500f8, +	0x21f407f8, +	0x03daf004, +	0xf83f21f4, +/* 0x0825: i2c_recv */ +	0x0132f400, +	0xb6f8c1c7, +	0x16b00214, +	0x3a1ff528, +	0xd413a001, +	0x0032980b, +	0x0bac13a0, +	0xf4003198, +	0xd0f90231, +	0xd0f9e0f9, +	0x000067f1, +	0x100063f1, +	0xbb016792, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x080721f5, +	0xfc0464b6, +	0x00d6b0d0, +	0x00b31bf5, +	0xbb0057f0, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x07b121f5, +	0xf50464b6, +	0xc700d011, +	0x76bbe0c5, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb6075621, +	0x11f50464, +	0x57f000ad, +	0x0076bb01, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b607b1, +	0x8a11f504, +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b60704, +	0x6a11f404, +	0xbbe05bcb, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x064921f5, +	0xb90464b6, +	0x74bd025b, +/* 0x092b: i2c_recv_not_rd08 */ +	0xb0430ef4, +	0x1bf401d6, +	0x0057f03d, +	0x07b121f5, +	0xc73311f4, +	0x21f5e0c5, +	0x11f40756, +	0x0057f029, +	0x07b121f5, +	0xc71f11f4, +	0x21f5e0b5, +	0x11f40756, +	0x4921f515, +	0xc774bd06, +	0x1bf408c5, +	0x0232f409, +/* 0x096b: i2c_recv_not_wr08 */ +/* 0x096b: i2c_recv_done */ +	0xc7030ef4, +	0x21f5f8ce, +	0xe0fc0816, +	0x12f4d0fc, +	0x027cb90a, +	0x02b921f5, +/* 0x0980: i2c_recv_exit */ +/* 0x0982: i2c_init */ +	0x00f800f8, +/* 0x0984: test_recv */ +	0x05d817f1, +	0xcf0614b6, +	0x10b60011, +	0xd807f101, +	0x0604b605, +	0xbd0001d0, +	0x00e7f104, +	0x4fe3f1d9, +	0xf521f513, +/* 0x09ab: test_init */ +	0xf100f801, +	0xf50800e7, +	0xf801f521, +/* 0x09b5: idle_recv */ +/* 0x09b7: idle */ +	0xf400f800, +	0x17f10031, +	0x14b605d4, +	0x0011cf06, +	0xf10110b6, +	0xb605d407, +	0x01d00604, +/* 0x09d3: idle_loop */ +	0xf004bd00, +	0x32f45817, +/* 0x09d9: idle_proc */ +/* 0x09d9: idle_proc_exec */ +	0xb910f902, +	0x21f5021e, +	0x10fc02c2, +	0xf40911f4, +	0x0ef40231, +/* 0x09ed: idle_proc_next */ +	0x5810b6ef, +	0xf4061fb8, +	0x02f4e61b, +	0x0028f4dd, +	0x00bb0ef4, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc new file mode 100644 index 00000000000..8a89dfe41ce --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc @@ -0,0 +1,66 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#define NVKM_PPWR_CHIPSET GF119 + +//#define NVKM_FALCON_PC24 +#define NVKM_FALCON_UNSHIFTED_IO +//#define NVKM_FALCON_MMIO_UAS +//#define NVKM_FALCON_MMIO_TRAP + +#include "macros.fuc" + +.section #nvd0_pwr_data +#define INCLUDE_PROC +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_PROC + +#define INCLUDE_DATA +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_DATA +.align 256 + +.section #nvd0_pwr_code +#define INCLUDE_CODE +#include "kernel.fuc" +#include "host.fuc" +#include "memx.fuc" +#include "perf.fuc" +#include "i2c_.fuc" +#include "test.fuc" +#include "idle.fuc" +#undef INCLUDE_CODE +.align 256 diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h new file mode 100644 index 00000000000..cd9ff1a7328 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/nvd0.fuc.h @@ -0,0 +1,1524 @@ +uint32_t nvd0_pwr_data[] = { +/* 0x0000: proc_kern */ +	0x52544e49, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0058: proc_list_head */ +	0x54534f48, +	0x000003be, +	0x00000367, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x584d454d, +	0x000004c4, +	0x000004b6, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x46524550, +	0x000004c8, +	0x000004c6, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x5f433249, +	0x000008e3, +	0x00000786, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x54534554, +	0x00000906, +	0x000008e5, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x454c4449, +	0x00000912, +	0x00000910, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0268: proc_list_tail */ +/* 0x0268: time_prev */ +	0x00000000, +/* 0x026c: time_next */ +	0x00000000, +/* 0x0270: fifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x02f0: rfifo_queue */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0370: memx_func_head */ +	0x00010000, +	0x00000000, +	0x000003f4, +/* 0x037c: memx_func_next */ +	0x00000001, +	0x00000000, +	0x00000415, +	0x00000002, +	0x00000002, +	0x00000430, +	0x00040003, +	0x00000000, +	0x00000458, +	0x00010004, +	0x00000000, +	0x00000472, +/* 0x03ac: memx_func_tail */ +/* 0x03ac: memx_data_head */ +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +/* 0x0bac: memx_data_tail */ +/* 0x0bac: i2c_scl_map */ +	0x00000400, +	0x00000800, +	0x00001000, +	0x00002000, +	0x00004000, +	0x00008000, +	0x00010000, +	0x00020000, +	0x00040000, +	0x00080000, +/* 0x0bd4: i2c_sda_map */ +	0x00100000, +	0x00200000, +	0x00400000, +	0x00800000, +	0x01000000, +	0x02000000, +	0x04000000, +	0x08000000, +	0x10000000, +	0x20000000, +	0x00000000, +}; + +uint32_t nvd0_pwr_code[] = { +	0x02bf0ef5, +/* 0x0004: rd32 */ +	0x07a007f1, +	0xbd000ed0, +	0x01d7f004, +	0xf101d3f0, +	0xd007ac07, +	0x04bd000d, +/* 0x001c: rd32_wait */ +	0x07acd7f1, +	0xf100ddcf, +	0xf47000d4, +	0xd7f1f51b, +	0xddcf07a4, +/* 0x0033: wr32 */ +	0xf100f800, +	0xd007a007, +	0x04bd000e, +	0x07a407f1, +	0xbd000dd0, +	0x02d7f004, +	0xf0f0d5f0, +	0x07f101d3, +	0x0dd007ac, +/* 0x0057: wr32_wait */ +	0xf104bd00, +	0xcf07acd7, +	0xd4f100dd, +	0x1bf47000, +/* 0x0067: nsec */ +	0xf000f8f5, +	0x88cf2c87, +/* 0x006d: nsec_loop */ +	0x2c97f000, +	0xbb0099cf, +	0x9eb80298, +	0xf41ef406, +/* 0x007e: wait */ +	0x87f000f8, +	0x0088cf2c, +/* 0x0084: wait_loop */ +	0xf402eeb9, +	0xdab90421, +	0x04adfd02, +	0xf406acb8, +	0x97f0120b, +	0x0099cf2c, +	0xb80298bb, +	0x1ef4069b, +/* 0x00a5: wait_done */ +/* 0x00a7: intr_watchdog */ +	0x9800f8e2, +	0x96b003e9, +	0x2a0bf400, +	0xbb9a0a98, +	0x1cf4029a, +	0x01d7f00f, +	0x020621f5, +	0x0ef494bd, +/* 0x00c5: intr_watchdog_next_time */ +	0x9b0a9815, +	0xf400a6b0, +	0x9ab8090b, +	0x061cf406, +/* 0x00d4: intr_watchdog_next_time_set */ +/* 0x00d7: intr_watchdog_next_proc */ +	0x809b0980, +	0xe0b603e9, +	0x68e6b158, +	0xc61bf402, +/* 0x00e6: intr */ +	0x00f900f8, +	0x80f904bd, +	0xa0f990f9, +	0xc0f9b0f9, +	0xe0f9d0f9, +	0xf7f0f0f9, +	0x0188fe00, +	0x87f180f9, +	0x88cf05d0, +	0x0180b600, +	0x05d007f1, +	0xbd0008d0, +	0x0887f004, +	0xc40088cf, +	0x0bf40289, +	0x9b008020, +	0xf458e7f0, +	0x0998a721, +	0x0096b09b, +	0xf00e0bf4, +	0x09d03407, +	0x8004bd00, +/* 0x013e: intr_skip_watchdog */ +	0x89e49a09, +	0x0bf40800, +	0x8897f13c, +	0x0099cf06, +	0xf4029ac4, +	0xc7f1260b, +	0xcccf04c0, +	0xf1c0f900, +	0xf14f48e7, +	0xf05453e3, +	0x21f500d7, +	0xc0fc026b, +	0x04c007f1, +	0xbd000cd0, +/* 0x0175: intr_subintr_skip_fifo */ +	0x8807f104, +	0x0009d006, +/* 0x017e: intr_skip_subintr */ +	0x89c404bd, +	0x070bf420, +	0xffbfa4f1, +/* 0x0188: intr_skip_pause */ +	0xf44089c4, +	0xa4f1070b, +/* 0x0192: intr_skip_user0 */ +	0x07f0ffbf, +	0x0008d004, +	0x80fc04bd, +	0xfc0088fe, +	0xfce0fcf0, +	0xfcc0fcd0, +	0xfca0fcb0, +	0xfc80fc90, +	0x0032f400, +/* 0x01b6: timer */ +	0x32f401f8, +	0x03f89810, +	0xf40086b0, +	0xfe80421c, +	0x3807f003, +	0xbd0008d0, +	0x0887f004, +	0xf00088cf, +	0x1bf40284, +	0x3487f020, +	0xb80088cf, +	0x0bf406e0, +	0x06e8b809, +/* 0x01eb: timer_reset */ +	0xf0191ef4, +	0x0ed03407, +	0x8004bd00, +/* 0x01f6: timer_enable */ +	0x87f09a0e, +	0x3807f001, +	0xbd0008d0, +/* 0x0201: timer_done */ +	0x1031f404, +/* 0x0206: send_proc */ +	0x80f900f8, +	0xe89890f9, +	0x04e99805, +	0xb80486f0, +	0x0bf40689, +	0x0398c42a, +	0xb6048894, +	0x8ebb1880, +	0x00fa9800, +	0x80008a80, +	0x8c80018d, +	0x038b8002, +	0xf00190b6, +	0xe9800794, +	0x0231f404, +/* 0x0240: send_done */ +	0x80fc90fc, +/* 0x0246: find */ +	0x80f900f8, +	0xf45887f0, +/* 0x024e: find_loop */ +	0x8a980131, +	0x06aeb800, +	0xb6100bf4, +	0x86b15880, +	0x1bf40268, +	0x0132f4f0, +/* 0x0264: find_done */ +	0xfc028eb9, +/* 0x026b: send */ +	0xf500f880, +	0xf4024621, +	0x00f89701, +/* 0x0274: recv */ +	0x9805e898, +	0x32f404e9, +	0x0689b801, +	0xc43d0bf4, +	0x80b60389, +	0x0784f001, +	0x9805e880, +	0xf0f902ea, +	0xf9018ffe, +	0x02efb9f0, +	0xbb049994, +	0xe0b600e9, +	0x03eb9818, +	0x9802ec98, +	0xee9801ed, +	0xfca5f900, +	0x00f8fef0, +	0xfc0131f4, +/* 0x02bd: recv_done */ +/* 0x02bf: init */ +	0xf100f8f0, +	0xcf010817, +	0x11e70011, +	0x14b60109, +	0x0014fe08, +	0x00e017f1, +	0xf00013f0, +	0x01d01c07, +	0xf004bd00, +	0x07f0ff17, +	0x0001d014, +	0x17f004bd, +	0x0015f102, +	0x1007f008, +	0xbd0001d0, +	0xe617f104, +	0x0013f000, +	0xf40010fe, +	0x17f01031, +	0x3807f001, +	0xbd0001d0, +	0x58f7f004, +/* 0x0314: init_proc */ +	0xb001f198, +	0x0bf40016, +	0xb615f9fa, +	0x0ef458f0, +/* 0x0325: host_send */ +	0xb017f1f2, +	0x0011cf04, +	0x04a027f1, +	0xb80022cf, +	0x0bf40612, +	0x071ec42f, +	0xb704ee94, +	0x980270e0, +	0xec9803eb, +	0x01ed9802, +	0xf500ee98, +	0xb6026b21, +	0x1ec40110, +	0xb007f10f, +	0x000ed004, +	0x0ef404bd, +/* 0x0365: host_send_done */ +/* 0x0367: host_recv */ +	0xf100f8c3, +	0xf14e4917, +	0xb8525413, +	0x0bf406e1, +/* 0x0375: host_recv_wait */ +	0xcc17f1b3, +	0x0011cf04, +	0x04c827f1, +	0xf00022cf, +	0x12b80816, +	0xec0bf406, +	0xb60723c4, +	0x30b70434, +	0x3b8002f0, +	0x023c8003, +	0x80013d80, +	0x20b6003e, +	0x0f24f001, +	0x04c807f1, +	0xbd0002d0, +	0x4027f004, +	0xd00007f0, +	0x04bd0002, +/* 0x03be: host_init */ +	0x17f100f8, +	0x14b60080, +	0x7015f110, +	0xd007f102, +	0x0001d004, +	0x17f104bd, +	0x14b60080, +	0xf015f110, +	0xdc07f102, +	0x0001d004, +	0x17f004bd, +	0xc407f101, +	0x0001d004, +	0x00f804bd, +/* 0x03f4: memx_func_enter */ +	0xf10467f0, +	0xd007e007, +	0x04bd0006, +/* 0x0400: memx_func_enter_wait */ +	0x07c067f1, +	0xf00066cf, +	0x0bf40464, +	0x001698f6, +	0xf80410b6, +/* 0x0415: memx_func_leave */ +	0x0467f000, +	0x07e407f1, +	0xbd0006d0, +/* 0x0421: memx_func_leave_wait */ +	0xc067f104, +	0x0066cf07, +	0xf40464f0, +	0x00f8f61b, +/* 0x0430: memx_func_wr32 */ +	0x98001698, +	0x10b60115, +	0xf960f908, +	0xfcd0fc50, +	0x3321f4e0, +	0x140003f1, +	0x800506fd, +	0x04bd0005, +	0xf40242b6, +	0x00f8dd1b, +/* 0x0458: memx_func_wait */ +	0xcf2c87f0, +	0x1e980088, +	0x011d9800, +	0x98021c98, +	0x10b6031b, +	0x7e21f410, +/* 0x0472: memx_func_delay */ +	0x1e9800f8, +	0x0410b600, +	0xf86721f4, +/* 0x047d: memx_exec */ +	0xf9e0f900, +	0x02c1b9d0, +/* 0x0487: memx_exec_next */ +	0x9802b2b9, +	0x10b60013, +	0x10349504, +	0x980c30f0, +	0x55f9de35, +	0xf40612b8, +	0xd0fcec1e, +	0x21f5e0fc, +	0x00f8026b, +/* 0x04a8: memx_info */ +	0x03acc7f1, +	0x0800b7f1, +	0x026b21f5, +/* 0x04b6: memx_recv */ +	0xd6b000f8, +	0xc40bf401, +	0xf400d6b0, +	0x00f8e90b, +/* 0x04c4: memx_init */ +/* 0x04c6: perf_recv */ +	0x00f800f8, +/* 0x04c8: perf_init */ +/* 0x04ca: i2c_drive_scl */ +	0x36b000f8, +	0x0e0bf400, +	0x07e007f1, +	0xbd0001d0, +/* 0x04db: i2c_drive_scl_lo */ +	0xf100f804, +	0xd007e407, +	0x04bd0001, +/* 0x04e6: i2c_drive_sda */ +	0x36b000f8, +	0x0e0bf400, +	0x07e007f1, +	0xbd0002d0, +/* 0x04f7: i2c_drive_sda_lo */ +	0xf100f804, +	0xd007e407, +	0x04bd0002, +/* 0x0502: i2c_sense_scl */ +	0x32f400f8, +	0xc437f101, +	0x0033cf07, +	0xf40431fd, +	0x31f4060b, +/* 0x0515: i2c_sense_scl_done */ +/* 0x0517: i2c_sense_sda */ +	0xf400f801, +	0x37f10132, +	0x33cf07c4, +	0x0432fd00, +	0xf4060bf4, +/* 0x052a: i2c_sense_sda_done */ +	0x00f80131, +/* 0x052c: i2c_raise_scl */ +	0x47f140f9, +	0x37f00898, +	0xca21f501, +/* 0x0539: i2c_raise_scl_wait */ +	0xe8e7f104, +	0x6721f403, +	0x050221f5, +	0xb60901f4, +	0x1bf40142, +/* 0x054d: i2c_raise_scl_done */ +	0xf840fcef, +/* 0x0551: i2c_start */ +	0x0221f500, +	0x0d11f405, +	0x051721f5, +	0xf40611f4, +/* 0x0562: i2c_start_rep */ +	0x37f0300e, +	0xca21f500, +	0x0137f004, +	0x04e621f5, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x2c21f550, +	0x0464b605, +/* 0x058f: i2c_start_send */ +	0xf01f11f4, +	0x21f50037, +	0xe7f104e6, +	0x21f41388, +	0x0037f067, +	0x04ca21f5, +	0x1388e7f1, +/* 0x05ab: i2c_start_out */ +	0xf86721f4, +/* 0x05ad: i2c_stop */ +	0x0037f000, +	0x04ca21f5, +	0xf50037f0, +	0xf104e621, +	0xf403e8e7, +	0x37f06721, +	0xca21f501, +	0x88e7f104, +	0x6721f413, +	0xf50137f0, +	0xf104e621, +	0xf41388e7, +	0x00f86721, +/* 0x05e0: i2c_bitw */ +	0x04e621f5, +	0x03e8e7f1, +	0xbb6721f4, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x052c21f5, +	0xf40464b6, +	0xe7f11811, +	0x21f41388, +	0x0037f067, +	0x04ca21f5, +	0x1388e7f1, +/* 0x061f: i2c_bitw_out */ +	0xf86721f4, +/* 0x0621: i2c_bitr */ +	0x0137f000, +	0x04e621f5, +	0x03e8e7f1, +	0xbb6721f4, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x052c21f5, +	0xf40464b6, +	0x21f51b11, +	0x37f00517, +	0xca21f500, +	0x88e7f104, +	0x6721f413, +	0xf4013cf0, +/* 0x0666: i2c_bitr_done */ +	0x00f80131, +/* 0x0668: i2c_get_byte */ +	0xf00057f0, +/* 0x066e: i2c_get_byte_next */ +	0x54b60847, +	0x0076bb01, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b60621, +	0x2b11f404, +	0xb60553fd, +	0x1bf40142, +	0x0137f0d8, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0xe021f550, +	0x0464b605, +/* 0x06b8: i2c_get_byte_done */ +/* 0x06ba: i2c_put_byte */ +	0x47f000f8, +/* 0x06bd: i2c_put_byte_next */ +	0x0142b608, +	0xbb3854ff, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x05e021f5, +	0xf40464b6, +	0x46b03411, +	0xd81bf400, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x2121f550, +	0x0464b606, +	0xbb0f11f4, +	0x36b00076, +	0x061bf401, +/* 0x0713: i2c_put_byte_done */ +	0xf80132f4, +/* 0x0715: i2c_addr */ +	0x0076bb00, +	0xf90465b6, +	0x04659450, +	0xbd0256bb, +	0x0475fd50, +	0x21f550fc, +	0x64b60551, +	0x2911f404, +	0x012ec3e7, +	0xfd0134b6, +	0x76bb0553, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb606ba21, +/* 0x075a: i2c_addr_done */ +	0x00f80464, +/* 0x075c: i2c_acquire_addr */ +	0xb6f8cec7, +	0xe0b705e4, +	0x00f8d014, +/* 0x0768: i2c_acquire */ +	0x075c21f5, +	0xf00421f4, +	0x21f403d9, +/* 0x0777: i2c_release */ +	0xf500f833, +	0xf4075c21, +	0xdaf00421, +	0x3321f403, +/* 0x0786: i2c_recv */ +	0x32f400f8, +	0xf8c1c701, +	0xb00214b6, +	0x1ff52816, +	0x13a0013a, +	0x32980bd4, +	0xac13a000, +	0x0031980b, +	0xf90231f4, +	0xf9e0f9d0, +	0x0067f1d0, +	0x0063f100, +	0x01679210, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x6821f550, +	0x0464b607, +	0xd6b0d0fc, +	0xb31bf500, +	0x0057f000, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0x1521f550, +	0x0464b607, +	0x00d011f5, +	0xbbe0c5c7, +	0x65b60076, +	0x9450f904, +	0x56bb0465, +	0xfd50bd02, +	0x50fc0475, +	0x06ba21f5, +	0xf50464b6, +	0xf000ad11, +	0x76bb0157, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb6071521, +	0x11f50464, +	0x76bb008a, +	0x0465b600, +	0x659450f9, +	0x0256bb04, +	0x75fd50bd, +	0xf550fc04, +	0xb6066821, +	0x11f40464, +	0xe05bcb6a, +	0xb60076bb, +	0x50f90465, +	0xbb046594, +	0x50bd0256, +	0xfc0475fd, +	0xad21f550, +	0x0464b605, +	0xbd025bb9, +	0x430ef474, +/* 0x088c: i2c_recv_not_rd08 */ +	0xf401d6b0, +	0x57f03d1b, +	0x1521f500, +	0x3311f407, +	0xf5e0c5c7, +	0xf406ba21, +	0x57f02911, +	0x1521f500, +	0x1f11f407, +	0xf5e0b5c7, +	0xf406ba21, +	0x21f51511, +	0x74bd05ad, +	0xf408c5c7, +	0x32f4091b, +	0x030ef402, +/* 0x08cc: i2c_recv_not_wr08 */ +/* 0x08cc: i2c_recv_done */ +	0xf5f8cec7, +	0xfc077721, +	0xf4d0fce0, +	0x7cb90a12, +	0x6b21f502, +/* 0x08e1: i2c_recv_exit */ +/* 0x08e3: i2c_init */ +	0xf800f802, +/* 0x08e5: test_recv */ +	0xd817f100, +	0x0011cf05, +	0xf10110b6, +	0xd005d807, +	0x04bd0001, +	0xd900e7f1, +	0x134fe3f1, +	0x01b621f5, +/* 0x0906: test_init */ +	0xe7f100f8, +	0x21f50800, +	0x00f801b6, +/* 0x0910: idle_recv */ +/* 0x0912: idle */ +	0x31f400f8, +	0xd417f100, +	0x0011cf05, +	0xf10110b6, +	0xd005d407, +	0x04bd0001, +/* 0x0928: idle_loop */ +	0xf45817f0, +/* 0x092e: idle_proc */ +/* 0x092e: idle_proc_exec */ +	0x10f90232, +	0xf5021eb9, +	0xfc027421, +	0x0911f410, +	0xf40231f4, +/* 0x0942: idle_proc_next */ +	0x10b6ef0e, +	0x061fb858, +	0xf4e61bf4, +	0x28f4dd02, +	0xc10ef400, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +	0x00000000, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h new file mode 100644 index 00000000000..574acfa44c8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/os.h @@ -0,0 +1,46 @@ +#ifndef __NVKM_PWR_OS_H__ +#define __NVKM_PWR_OS_H__ + +/* Process names */ +#define PROC_KERN 0x52544e49 +#define PROC_IDLE 0x454c4449 +#define PROC_HOST 0x54534f48 +#define PROC_MEMX 0x584d454d +#define PROC_PERF 0x46524550 +#define PROC_I2C_ 0x5f433249 +#define PROC_TEST 0x54534554 + +/* KERN: message identifiers */ +#define KMSG_FIFO   0x00000000 +#define KMSG_ALARM  0x00000001 + +/* MEMX: message identifiers */ +#define MEMX_MSG_INFO 0 +#define MEMX_MSG_EXEC 1 + +/* MEMX: script opcode definitions */ +#define MEMX_ENTER  0 +#define MEMX_LEAVE  1 +#define MEMX_WR32   2 +#define MEMX_WAIT   3 +#define MEMX_DELAY  4 + +/* I2C_: message identifiers */ +#define I2C__MSG_RD08 0 +#define I2C__MSG_WR08 1 + +#define I2C__MSG_DATA0_PORT 24:31 +#define I2C__MSG_DATA0_ADDR 14:23 + +#define I2C__MSG_DATA0_RD08_PORT I2C__MSG_DATA0_PORT +#define I2C__MSG_DATA0_RD08_ADDR I2C__MSG_DATA0_ADDR +#define I2C__MSG_DATA0_RD08_REG 0:7 +#define I2C__MSG_DATA1_RD08_VAL 0:7 + +#define I2C__MSG_DATA0_WR08_PORT I2C__MSG_DATA0_PORT +#define I2C__MSG_DATA0_WR08_ADDR I2C__MSG_DATA0_ADDR +#define I2C__MSG_DATA0_WR08_SYNC 8:8 +#define I2C__MSG_DATA0_WR08_REG 0:7 +#define I2C__MSG_DATA1_WR08_VAL 0:7 + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/perf.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/perf.fuc new file mode 100644 index 00000000000..38eadf705cb --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/perf.fuc @@ -0,0 +1,57 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifdef INCLUDE_PROC +process(PROC_PERF, #perf_init, #perf_recv) +#endif + +/****************************************************************************** + * PERF data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +#endif + +/****************************************************************************** + * PERF code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE + +// description +// +// $r15 - current (perf) +// $r14 - sender process name +// $r13 - message +// $r12 - data0 +// $r11 - data1 +// $r0  - zero +perf_recv: +	ret + +// description +// +// $r15 - current (perf) +// $r0  - zero +perf_init: +	ret +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/test.fuc b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/test.fuc new file mode 100644 index 00000000000..0c3a71bf545 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/fuc/test.fuc @@ -0,0 +1,64 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifdef INCLUDE_PROC +process(PROC_TEST, #test_init, #test_recv) +#endif + +/****************************************************************************** + * TEST data segment + *****************************************************************************/ +#ifdef INCLUDE_DATA +#endif + +/****************************************************************************** + * TEST code segment + *****************************************************************************/ +#ifdef INCLUDE_CODE +// description +// +// $r15 - current (test) +// $r14 - sender process name +// $r13 - message +// $r12 - data0 +// $r11 - data1 +// $r0  - zero +test_recv: +	nv_iord($r1, NV_PPWR_DSCRATCH(2)) +	add b32 $r1 1 +	nv_iowr(NV_PPWR_DSCRATCH(2), $r1) +	mov $r14 -0x2700 /* 0xd900, envyas grrr! */ +	sethi $r14 0x134f0000 +	call(timer) +	ret + +// description +// +// $r15 - current (test) +// $r0  - zero +test_init: +	mov $r14 0x800 +	call(timer) +	ret +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c new file mode 100644 index 00000000000..03de3107d29 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/memx.c @@ -0,0 +1,121 @@ +#ifndef __NVKM_PWR_MEMX_H__ +#define __NVKM_PWR_MEMX_H__ + +#include <subdev/pwr.h> +#include <subdev/pwr/fuc/os.h> + +struct nouveau_memx { +	struct nouveau_pwr *ppwr; +	u32 base; +	u32 size; +	struct { +		u32 mthd; +		u32 size; +		u32 data[64]; +	} c; +}; + +static void +memx_out(struct nouveau_memx *memx) +{ +	struct nouveau_pwr *ppwr = memx->ppwr; +	int i; + +	if (memx->c.size) { +		nv_wr32(ppwr, 0x10a1c4, (memx->c.size << 16) | memx->c.mthd); +		for (i = 0; i < memx->c.size; i++) +			nv_wr32(ppwr, 0x10a1c4, memx->c.data[i]); +		memx->c.size = 0; +	} +} + +static void +memx_cmd(struct nouveau_memx *memx, u32 mthd, u32 size, u32 data[]) +{ +	if ((memx->c.size + size >= ARRAY_SIZE(memx->c.data)) || +	    (memx->c.size && memx->c.mthd != mthd)) +		memx_out(memx); +	memcpy(&memx->c.data[memx->c.size], data, size * sizeof(data[0])); +	memx->c.size += size; +	memx->c.mthd  = mthd; +} + +int +nouveau_memx_init(struct nouveau_pwr *ppwr, struct nouveau_memx **pmemx) +{ +	struct nouveau_memx *memx; +	u32 reply[2]; +	int ret; + +	ret = ppwr->message(ppwr, reply, PROC_MEMX, MEMX_MSG_INFO, 0, 0); +	if (ret) +		return ret; + +	memx = *pmemx = kzalloc(sizeof(*memx), GFP_KERNEL); +	if (!memx) +		return -ENOMEM; +	memx->ppwr = ppwr; +	memx->base = reply[0]; +	memx->size = reply[1]; + +	/* acquire data segment access */ +	do { +		nv_wr32(ppwr, 0x10a580, 0x00000003); +	} while (nv_rd32(ppwr, 0x10a580) != 0x00000003); +	nv_wr32(ppwr, 0x10a1c0, 0x01000000 | memx->base); +	nv_wr32(ppwr, 0x10a1c4, 0x00010000 | MEMX_ENTER); +	nv_wr32(ppwr, 0x10a1c4, 0x00000000); +	return 0; +} + +int +nouveau_memx_fini(struct nouveau_memx **pmemx, bool exec) +{ +	struct nouveau_memx *memx = *pmemx; +	struct nouveau_pwr *ppwr = memx->ppwr; +	u32 finish, reply[2]; + +	/* flush the cache... */ +	memx_out(memx); + +	/* release data segment access */ +	nv_wr32(ppwr, 0x10a1c4, 0x00000000 | MEMX_LEAVE); +	finish = nv_rd32(ppwr, 0x10a1c0) & 0x00ffffff; +	nv_wr32(ppwr, 0x10a580, 0x00000000); + +	/* call MEMX process to execute the script, and wait for reply */ +	if (exec) { +		ppwr->message(ppwr, reply, PROC_MEMX, MEMX_MSG_EXEC, +				 memx->base, finish); +	} + +	kfree(memx); +	return 0; +} + +void +nouveau_memx_wr32(struct nouveau_memx *memx, u32 addr, u32 data) +{ +	nv_debug(memx->ppwr, "R[%06x] = 0x%08x\n", addr, data); +	memx_cmd(memx, MEMX_WR32, 2, (u32[]){ addr, data }); +} + +void +nouveau_memx_wait(struct nouveau_memx *memx, +		  u32 addr, u32 mask, u32 data, u32 nsec) +{ +	nv_debug(memx->ppwr, "R[%06x] & 0x%08x == 0x%08x, %d us\n", +				addr, mask, data, nsec); +	memx_cmd(memx, MEMX_WAIT, 4, (u32[]){ addr, ~mask, data, nsec }); +	memx_out(memx); /* fuc can't handle multiple */ +} + +void +nouveau_memx_nsec(struct nouveau_memx *memx, u32 nsec) +{ +	nv_debug(memx->ppwr, "    DELAY = %d ns\n", nsec); +	memx_cmd(memx, MEMX_DELAY, 1, (u32[]){ nsec }); +	memx_out(memx); /* fuc can't handle multiple */ +} + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c new file mode 100644 index 00000000000..52c85414866 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nv108.c @@ -0,0 +1,62 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/pwr.h> + +#include "fuc/nv108.fuc.h" + +struct nv108_pwr_priv { +	struct nouveau_pwr base; +}; + +static int +nv108_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct nv108_pwr_priv *priv; +	int ret; + +	ret = nouveau_pwr_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.code.data = nv108_pwr_code; +	priv->base.code.size = sizeof(nv108_pwr_code); +	priv->base.data.data = nv108_pwr_data; +	priv->base.data.size = sizeof(nv108_pwr_data); +	return 0; +} + +struct nouveau_oclass +nv108_pwr_oclass = { +	.handle = NV_SUBDEV(PWR, 0x00), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv108_pwr_ctor, +		.dtor = _nouveau_pwr_dtor, +		.init = _nouveau_pwr_init, +		.fini = _nouveau_pwr_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c new file mode 100644 index 00000000000..c132b7ca974 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nva3.c @@ -0,0 +1,71 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/pwr.h> + +#include "fuc/nva3.fuc.h" + +struct nva3_pwr_priv { +	struct nouveau_pwr base; +}; + +static int +nva3_pwr_init(struct nouveau_object *object) +{ +	struct nva3_pwr_priv *priv = (void *)object; +	nv_mask(priv, 0x022210, 0x00000001, 0x00000000); +	nv_mask(priv, 0x022210, 0x00000001, 0x00000001); +	return nouveau_pwr_init(&priv->base); +} + +static int +nva3_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 size, +	      struct nouveau_object **pobject) +{ +	struct nva3_pwr_priv *priv; +	int ret; + +	ret = nouveau_pwr_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.code.data = nva3_pwr_code; +	priv->base.code.size = sizeof(nva3_pwr_code); +	priv->base.data.data = nva3_pwr_data; +	priv->base.data.size = sizeof(nva3_pwr_data); +	return 0; +} + +struct nouveau_oclass +nva3_pwr_oclass = { +	.handle = NV_SUBDEV(PWR, 0xa3), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nva3_pwr_ctor, +		.dtor = _nouveau_pwr_dtor, +		.init = nva3_pwr_init, +		.fini = _nouveau_pwr_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c new file mode 100644 index 00000000000..495f6857428 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvc0.c @@ -0,0 +1,62 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/pwr.h> + +#include "fuc/nvc0.fuc.h" + +struct nvc0_pwr_priv { +	struct nouveau_pwr base; +}; + +static int +nvc0_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 size, +	      struct nouveau_object **pobject) +{ +	struct nvc0_pwr_priv *priv; +	int ret; + +	ret = nouveau_pwr_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.code.data = nvc0_pwr_code; +	priv->base.code.size = sizeof(nvc0_pwr_code); +	priv->base.data.data = nvc0_pwr_data; +	priv->base.data.size = sizeof(nvc0_pwr_data); +	return 0; +} + +struct nouveau_oclass +nvc0_pwr_oclass = { +	.handle = NV_SUBDEV(PWR, 0xc0), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvc0_pwr_ctor, +		.dtor = _nouveau_pwr_dtor, +		.init = _nouveau_pwr_init, +		.fini = _nouveau_pwr_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c new file mode 100644 index 00000000000..043aa142fe8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/pwr/nvd0.c @@ -0,0 +1,62 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/pwr.h> + +#include "fuc/nvd0.fuc.h" + +struct nvd0_pwr_priv { +	struct nouveau_pwr base; +}; + +static int +nvd0_pwr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	      struct nouveau_oclass *oclass, void *data, u32 size, +	      struct nouveau_object **pobject) +{ +	struct nvd0_pwr_priv *priv; +	int ret; + +	ret = nouveau_pwr_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.code.data = nvd0_pwr_code; +	priv->base.code.size = sizeof(nvd0_pwr_code); +	priv->base.data.data = nvd0_pwr_data; +	priv->base.data.size = sizeof(nvd0_pwr_data); +	return 0; +} + +struct nouveau_oclass +nvd0_pwr_oclass = { +	.handle = NV_SUBDEV(PWR, 0xd0), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nvd0_pwr_ctor, +		.dtor = _nouveau_pwr_dtor, +		.init = _nouveau_pwr_init, +		.fini = _nouveau_pwr_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index f1de7a9c572..9ad01da6eac 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c @@ -92,10 +92,11 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)  	struct nouveau_timer *ptimer = nouveau_timer(therm);  	struct nouveau_therm_priv *priv = (void *)therm;  	unsigned long flags; -	int duty; +	bool immd = true; +	bool poll = true; +	int duty = -1;  	spin_lock_irqsave(&priv->lock, flags); -	nv_debug(therm, "FAN speed check\n");  	if (mode < 0)  		mode = priv->mode;  	priv->mode = mode; @@ -106,28 +107,51 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode)  		duty = nouveau_therm_fan_get(therm);  		if (duty < 0)  			duty = 100; +		poll = false;  		break;  	case NOUVEAU_THERM_CTRL_AUTO: -		if (priv->fan->bios.nr_fan_trip) +		switch(priv->fan->bios.fan_mode) { +		case NVBIOS_THERM_FAN_TRIP:  			duty = nouveau_therm_update_trip(therm); -		else +			break; +		case NVBIOS_THERM_FAN_LINEAR:  			duty = nouveau_therm_update_linear(therm); +			break; +		case NVBIOS_THERM_FAN_OTHER: +			if (priv->cstate) +				duty = priv->cstate; +			poll = false; +			break; +		} +		immd = false;  		break;  	case NOUVEAU_THERM_CTRL_NONE:  	default:  		ptimer->alarm_cancel(ptimer, &priv->alarm); -		goto done; +		poll = false;  	} -	nv_debug(therm, "FAN target request: %d%%\n", duty); -	nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty); - -done: -	if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) +	if (list_empty(&priv->alarm.head) && poll)  		ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); -	else if (!list_empty(&priv->alarm.head)) -		nv_debug(therm, "therm fan alarm list is not empty\n");  	spin_unlock_irqrestore(&priv->lock, flags); + +	if (duty >= 0) { +		nv_debug(therm, "FAN target request: %d%%\n", duty); +		nouveau_therm_fan_set(therm, immd, duty); +	} +} + +int +nouveau_therm_cstate(struct nouveau_therm *ptherm, int fan, int dir) +{ +	struct nouveau_therm_priv *priv = (void *)ptherm; +	if (!dir || (dir < 0 && fan < priv->cstate) || +		    (dir > 0 && fan > priv->cstate)) { +		nv_debug(ptherm, "default fan speed -> %d%%\n", fan); +		priv->cstate = fan; +		nouveau_therm_update(ptherm, -1); +	} +	return 0;  }  static void @@ -149,14 +173,15 @@ nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)  		"automatic"  	}; -	/* The default PDAEMON ucode interferes with fan management */ +	/* The default PPWR ucode on fermi interferes with fan management */  	if ((mode >= ARRAY_SIZE(name)) || -	    (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) +	    (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0 && +	     !nouveau_subdev(device, NVDEV_SUBDEV_PWR)))  		return -EINVAL;  	/* do not allow automatic fan management if the thermal sensor is  	 * not available */ -	if (priv->mode == 2 && therm->temp_get(therm) < 0) +	if (mode == NOUVEAU_THERM_CTRL_AUTO && therm->temp_get(therm) < 0)  		return -EINVAL;  	if (priv->mode == mode) @@ -335,7 +360,7 @@ nouveau_therm_preinit(struct nouveau_therm *therm)  	nouveau_therm_ic_ctor(therm);  	nouveau_therm_fan_ctor(therm); -	nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_NONE); +	nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_AUTO);  	nouveau_therm_sensor_preinit(therm);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index 39f47b950ad..016990a8252 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -54,8 +54,10 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)  	/* check that we're not already at the target duty cycle */  	duty = fan->get(therm); -	if (duty == target) -		goto done; +	if (duty == target) { +		spin_unlock_irqrestore(&fan->lock, flags); +		return 0; +	}  	/* smooth out the fanspeed increase/decrease */  	if (!immediate && duty >= 0) { @@ -73,8 +75,15 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)  	nv_debug(therm, "FAN update: %d\n", duty);  	ret = fan->set(therm, duty); -	if (ret) -		goto done; +	if (ret) { +		spin_unlock_irqrestore(&fan->lock, flags); +		return ret; +	} + +	/* fan speed updated, drop the fan lock before grabbing the +	 * alarm-scheduling lock and risking a deadlock +	 */ +	spin_unlock_irqrestore(&fan->lock, flags);  	/* schedule next fan update, if not at target speed already */  	if (list_empty(&fan->alarm.head) && target != duty) { @@ -92,8 +101,6 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target)  		ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm);  	} -done: -	spin_unlock_irqrestore(&fan->lock, flags);  	return ret;  } @@ -232,7 +239,8 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm)  	/* attempt to locate a drivable fan, and determine control method */  	ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);  	if (ret == 0) { -		if (func.log[0] & DCB_GPIO_LOG_DIR_IN) { +		/* FIXME: is this really the place to perform such checks ? */ +		if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {  			nv_debug(therm, "GPIO_FAN is in input mode\n");  			ret = -EINVAL;  		} else { diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c index 5f71db8e899..9a5c0734026 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c @@ -67,7 +67,7 @@ nouveau_fanpwm_set(struct nouveau_therm *therm, int percent)  	if (priv->base.bios.pwm_freq) {  		divs = 1;  		if (therm->pwm_clock) -			divs = therm->pwm_clock(therm); +			divs = therm->pwm_clock(therm, priv->func.line);  		divs /= priv->base.bios.pwm_freq;  	} diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c index e601773ee47..f69dab11f72 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c @@ -97,6 +97,13 @@ nouveau_fantog_create(struct nouveau_therm *therm, struct dcb_gpio_func *func)  {  	struct nouveau_therm_priv *tpriv = (void *)therm;  	struct nouveau_fantog_priv *priv; +	int ret; + +	if (therm->pwm_ctrl) { +		ret = therm->pwm_ctrl(therm, func->line, false); +		if (ret) +			return ret; +	}  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	tpriv->fan = &priv->base; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index 8b3adec5fbb..ca9ad9fd47b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -29,9 +29,9 @@  static bool  probe_monitoring_device(struct nouveau_i2c_port *i2c, -			struct i2c_board_info *info) +			struct i2c_board_info *info, void *data)  { -	struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); +	struct nouveau_therm_priv *priv = data;  	struct nvbios_therm_sensor *sensor = &priv->bios_sensor;  	struct i2c_client *client; @@ -41,7 +41,8 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,  	if (!client)  		return false; -	if (!client->driver || client->driver->detect(client, info)) { +	if (!client->dev.driver || +	    to_i2c_driver(client->dev.driver)->detect(client, info)) {  		i2c_unregister_device(client);  		return false;  	} @@ -55,28 +56,28 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,  	return true;  } -static struct i2c_board_info +static struct nouveau_i2c_board_info  nv_board_infos[] = { -	{ I2C_BOARD_INFO("w83l785ts", 0x2d) }, -	{ I2C_BOARD_INFO("w83781d", 0x2d) }, -	{ I2C_BOARD_INFO("adt7473", 0x2e) }, -	{ I2C_BOARD_INFO("adt7473", 0x2d) }, -	{ I2C_BOARD_INFO("adt7473", 0x2c) }, -	{ I2C_BOARD_INFO("f75375", 0x2e) }, -	{ I2C_BOARD_INFO("lm99", 0x4c) }, -	{ I2C_BOARD_INFO("lm90", 0x4c) }, -	{ I2C_BOARD_INFO("lm90", 0x4d) }, -	{ I2C_BOARD_INFO("adm1021", 0x18) }, -	{ I2C_BOARD_INFO("adm1021", 0x19) }, -	{ I2C_BOARD_INFO("adm1021", 0x1a) }, -	{ I2C_BOARD_INFO("adm1021", 0x29) }, -	{ I2C_BOARD_INFO("adm1021", 0x2a) }, -	{ I2C_BOARD_INFO("adm1021", 0x2b) }, -	{ I2C_BOARD_INFO("adm1021", 0x4c) }, -	{ I2C_BOARD_INFO("adm1021", 0x4d) }, -	{ I2C_BOARD_INFO("adm1021", 0x4e) }, -	{ I2C_BOARD_INFO("lm63", 0x18) }, -	{ I2C_BOARD_INFO("lm63", 0x4e) }, +	{ { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 0 }, +	{ { I2C_BOARD_INFO("w83781d", 0x2d) }, 0  }, +	{ { I2C_BOARD_INFO("adt7473", 0x2e) }, 40  }, +	{ { I2C_BOARD_INFO("adt7473", 0x2d) }, 40  }, +	{ { I2C_BOARD_INFO("adt7473", 0x2c) }, 40  }, +	{ { I2C_BOARD_INFO("f75375", 0x2e) }, 0  }, +	{ { I2C_BOARD_INFO("lm99", 0x4c) }, 0  }, +	{ { I2C_BOARD_INFO("lm90", 0x4c) }, 0  }, +	{ { I2C_BOARD_INFO("lm90", 0x4d) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x18) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x19) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x1a) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x29) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x2a) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x2b) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x4c) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x4d) }, 0  }, +	{ { I2C_BOARD_INFO("adm1021", 0x4e) }, 0  }, +	{ { I2C_BOARD_INFO("lm63", 0x18) }, 0  }, +	{ { I2C_BOARD_INFO("lm63", 0x4e) }, 0  },  	{ }  }; @@ -89,25 +90,25 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)  	struct nvbios_extdev_func extdev_entry;  	if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { -		struct i2c_board_info board[] = { -			{ I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, -			{ } +		struct nouveau_i2c_board_info board[] = { +		  { { I2C_BOARD_INFO("lm90", extdev_entry.addr >> 1) }, 0}, +		  { }  		};  		i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", -				  board, probe_monitoring_device); +			      board, probe_monitoring_device, therm);  		if (priv->ic)  			return;  	}  	if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_ADT7473, &extdev_entry)) { -		struct i2c_board_info board[] = { -			{ I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, -			{ } +		struct nouveau_i2c_board_info board[] = { +		  { { I2C_BOARD_INFO("adt7473", extdev_entry.addr >> 1) }, 20 }, +		  { }  		};  		i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", -				  board, probe_monitoring_device); +			      board, probe_monitoring_device, therm);  		if (priv->ic)  			return;  	} @@ -116,5 +117,5 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm)  	   device. Let's try our static list.  	 */  	i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", -		      nv_board_infos, probe_monitoring_device); +		      nv_board_infos, probe_monitoring_device, therm);  } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index 8cf7597a218..321db927d63 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -93,7 +93,7 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)  }  int -nv50_fan_pwm_clock(struct nouveau_therm *therm) +nv50_fan_pwm_clock(struct nouveau_therm *therm, int line)  {  	int chipset = nv_device(therm)->chipset;  	int crystal = nv_device(therm)->crystal; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c index 42ba633ccff..1d15c52fad0 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv84.c @@ -126,7 +126,7 @@ nv84_therm_intr(struct nouveau_subdev *subdev)  	spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); -	intr = nv_rd32(therm, 0x20100); +	intr = nv_rd32(therm, 0x20100) & 0x3ff;  	/* THRS_4: downclock */  	if (intr & 0x002) { @@ -209,6 +209,19 @@ nv84_therm_ctor(struct nouveau_object *parent,  	return nouveau_therm_preinit(&priv->base.base);  } +int +nv84_therm_fini(struct nouveau_object *object, bool suspend) +{ +	/* Disable PTherm IRQs */ +	nv_wr32(object, 0x20000, 0x00000000); + +	/* ACK all PTherm IRQs */ +	nv_wr32(object, 0x20100, 0xffffffff); +	nv_wr32(object, 0x1100, 0x10000); /* PBUS */ + +	return _nouveau_therm_fini(object, suspend); +} +  struct nouveau_oclass  nv84_therm_oclass = {  	.handle = NV_SUBDEV(THERM, 0x84), @@ -216,6 +229,6 @@ nv84_therm_oclass = {  		.ctor = nv84_therm_ctor,  		.dtor = _nouveau_therm_dtor,  		.init = _nouveau_therm_init, -		.fini = _nouveau_therm_fini, +		.fini = nv84_therm_fini,  	},  }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c index d11a7c40081..0478b2e3fb1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c @@ -36,7 +36,7 @@ nva3_therm_fan_sense(struct nouveau_therm *therm)  	u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff;  	u32 ctrl = nv_rd32(therm, 0x00e720);  	if (ctrl & 0x00000001) -		return tach * 60; +		return tach * 60 / 2;  	return -ENODEV;  } @@ -94,6 +94,6 @@ nva3_therm_oclass = {  		.ctor = nva3_therm_ctor,  		.dtor = _nouveau_therm_dtor,  		.init = nva3_therm_init, -		.fini = _nouveau_therm_fini, +		.fini = nv84_therm_fini,  	},  }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c index 54c28bdc420..bbf117be572 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c @@ -32,12 +32,15 @@ static int  pwm_info(struct nouveau_therm *therm, int line)  {  	u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04)); +  	switch (gpio & 0x000000c0) {  	case 0x00000000: /* normal mode, possibly pwm forced off by us */  	case 0x00000040: /* nvio special */  		switch (gpio & 0x0000001f) { +		case 0x00: return 2;  		case 0x19: return 1;  		case 0x1c: return 0; +		case 0x1e: return 2;  		default:  			break;  		} @@ -56,8 +59,9 @@ nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)  	int indx = pwm_info(therm, line);  	if (indx < 0)  		return indx; - -	nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); +	else if (indx < 2) +		nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); +	/* nothing to do for indx == 2, it seems hardwired to PTHERM */  	return 0;  } @@ -67,10 +71,15 @@ nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)  	int indx = pwm_info(therm, line);  	if (indx < 0)  		return indx; - -	if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { -		*divs = nv_rd32(therm, 0x00e114 + (indx * 8)); -		*duty = nv_rd32(therm, 0x00e118 + (indx * 8)); +	else if (indx < 2) { +		if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { +			*divs = nv_rd32(therm, 0x00e114 + (indx * 8)); +			*duty = nv_rd32(therm, 0x00e118 + (indx * 8)); +			return 0; +		} +	} else if (indx == 2) { +		*divs = nv_rd32(therm, 0x0200d8) & 0x1fff; +		*duty = nv_rd32(therm, 0x0200dc) & 0x1fff;  		return 0;  	} @@ -83,16 +92,26 @@ nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)  	int indx = pwm_info(therm, line);  	if (indx < 0)  		return indx; - -	nv_wr32(therm, 0x00e114 + (indx * 8), divs); -	nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); +	else if (indx < 2) { +		nv_wr32(therm, 0x00e114 + (indx * 8), divs); +		nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); +	} else if (indx == 2) { +		nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */ +		nv_wr32(therm, 0x0200dc, duty | 0x40000000); +	}  	return 0;  }  static int -nvd0_fan_pwm_clock(struct nouveau_therm *therm) +nvd0_fan_pwm_clock(struct nouveau_therm *therm, int line)  { -	return (nv_device(therm)->crystal * 1000) / 20; +	int indx = pwm_info(therm, line); +	if (indx < 0) +		return 0; +	else if (indx < 2) +		return (nv_device(therm)->crystal * 1000) / 20; +	else +		return nv_device(therm)->crystal * 1000 / 10;  }  static int @@ -148,6 +167,6 @@ nvd0_therm_oclass = {  		.ctor = nvd0_therm_ctor,  		.dtor = _nouveau_therm_dtor,  		.init = nvd0_therm_init, -		.fini = _nouveau_therm_fini, +		.fini = nv84_therm_fini,  	},  }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index dd38529262f..916fca5c781 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -76,6 +76,7 @@ struct nouveau_therm_priv {  	spinlock_t lock;  	struct nouveau_therm_trip_point *last_trip;  	int mode; +	int cstate;  	int suspend;  	/* bios */ @@ -142,8 +143,9 @@ void nv40_therm_intr(struct nouveau_subdev *);  int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);  int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *);  int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32); -int nv50_fan_pwm_clock(struct nouveau_therm *); +int nv50_fan_pwm_clock(struct nouveau_therm *, int);  int nv84_temp_get(struct nouveau_therm *therm); +int nv84_therm_fini(struct nouveau_object *object, bool suspend);  int nva3_therm_fan_sense(struct nouveau_therm *); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index b80a33011b9..6212537b90c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c @@ -180,8 +180,6 @@ alarm_timer_callback(struct nouveau_alarm *alarm)  	spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); -	nv_debug(therm, "polling the internal temperature\n"); -  	nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost,  					     NOUVEAU_THERM_THRS_FANBOOST); @@ -194,11 +192,11 @@ alarm_timer_callback(struct nouveau_alarm *alarm)  	nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown,  					     NOUVEAU_THERM_THRS_SHUTDOWN); +	spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); +  	/* schedule the next poll in one second */  	if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head)) -		ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); - -	spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); +		ptimer->alarm(ptimer, 1000000000ULL, alarm);  }  void diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c new file mode 100644 index 00000000000..37484db1f7f --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/gk20a.c @@ -0,0 +1,57 @@ +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "nv04.h" + +static int +gk20a_timer_init(struct nouveau_object *object) +{ +	struct nv04_timer_priv *priv = (void *)object; +	u32 hi = upper_32_bits(priv->suspend_time); +	u32 lo = lower_32_bits(priv->suspend_time); +	int ret; + +	ret = nouveau_timer_init(&priv->base); +	if (ret) +		return ret; + +	nv_debug(priv, "time low        : 0x%08x\n", lo); +	nv_debug(priv, "time high       : 0x%08x\n", hi); + +	/* restore the time before suspend */ +	nv_wr32(priv, NV04_PTIMER_TIME_1, hi); +	nv_wr32(priv, NV04_PTIMER_TIME_0, lo); +	return 0; +} + +struct nouveau_oclass +gk20a_timer_oclass = { +	.handle = NV_SUBDEV(TIMER, 0xff), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv04_timer_ctor, +		.dtor = nv04_timer_dtor, +		.init = gk20a_timer_init, +		.fini = nv04_timer_fini, +	} +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 57711ecb566..240ed0b983a 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -22,22 +22,7 @@   * Authors: Ben Skeggs   */ -#include <subdev/timer.h> - -#define NV04_PTIMER_INTR_0      0x009100 -#define NV04_PTIMER_INTR_EN_0   0x009140 -#define NV04_PTIMER_NUMERATOR   0x009200 -#define NV04_PTIMER_DENOMINATOR 0x009210 -#define NV04_PTIMER_TIME_0      0x009400 -#define NV04_PTIMER_TIME_1      0x009410 -#define NV04_PTIMER_ALARM_0     0x009420 - -struct nv04_timer_priv { -	struct nouveau_timer base; -	struct list_head alarms; -	spinlock_t lock; -	u64 suspend_time; -}; +#include "nv04.h"  static u64  nv04_timer_read(struct nouveau_timer *ptimer) @@ -119,16 +104,8 @@ nv04_timer_alarm_cancel(struct nouveau_timer *ptimer,  {  	struct nv04_timer_priv *priv = (void *)ptimer;  	unsigned long flags; - -	/* avoid deleting an entry while the alarm intr is running */  	spin_lock_irqsave(&priv->lock, flags); - -	/* delete the alarm from the list */ -	list_del(&alarm->head); - -	/* reset the head so as list_empty returns 1 */ -	INIT_LIST_HEAD(&alarm->head); - +	list_del_init(&alarm->head);  	spin_unlock_irqrestore(&priv->lock, flags);  } @@ -150,35 +127,14 @@ nv04_timer_intr(struct nouveau_subdev *subdev)  	}  } -static int -nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, -		struct nouveau_oclass *oclass, void *data, u32 size, -		struct nouveau_object **pobject) -{ -	struct nv04_timer_priv *priv; -	int ret; - -	ret = nouveau_timer_create(parent, engine, oclass, &priv); -	*pobject = nv_object(priv); -	if (ret) -		return ret; - -	priv->base.base.intr = nv04_timer_intr; -	priv->base.read = nv04_timer_read; -	priv->base.alarm = nv04_timer_alarm; -	priv->base.alarm_cancel = nv04_timer_alarm_cancel; -	priv->suspend_time = 0; - -	INIT_LIST_HEAD(&priv->alarms); -	spin_lock_init(&priv->lock); -	return 0; -} - -static void -nv04_timer_dtor(struct nouveau_object *object) +int +nv04_timer_fini(struct nouveau_object *object, bool suspend)  {  	struct nv04_timer_priv *priv = (void *)object; -	return nouveau_timer_destroy(&priv->base); +	if (suspend) +		priv->suspend_time = nv04_timer_read(&priv->base); +	nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); +	return nouveau_timer_fini(&priv->base, suspend);  }  static int @@ -265,14 +221,35 @@ nv04_timer_init(struct nouveau_object *object)  	return 0;  } -static int -nv04_timer_fini(struct nouveau_object *object, bool suspend) +void +nv04_timer_dtor(struct nouveau_object *object)  {  	struct nv04_timer_priv *priv = (void *)object; -	if (suspend) -		priv->suspend_time = nv04_timer_read(&priv->base); -	nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); -	return nouveau_timer_fini(&priv->base, suspend); +	return nouveau_timer_destroy(&priv->base); +} + +int +nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +		struct nouveau_oclass *oclass, void *data, u32 size, +		struct nouveau_object **pobject) +{ +	struct nv04_timer_priv *priv; +	int ret; + +	ret = nouveau_timer_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	priv->base.base.intr = nv04_timer_intr; +	priv->base.read = nv04_timer_read; +	priv->base.alarm = nv04_timer_alarm; +	priv->base.alarm_cancel = nv04_timer_alarm_cancel; +	priv->suspend_time = 0; + +	INIT_LIST_HEAD(&priv->alarms); +	spin_lock_init(&priv->lock); +	return 0;  }  struct nouveau_oclass diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h new file mode 100644 index 00000000000..4bc152697c3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.h @@ -0,0 +1,27 @@ +#ifndef __NVKM_TIMER_NV04_H__ +#define __NVKM_TIMER_NV04_H__ + +#include "priv.h" + +#define NV04_PTIMER_INTR_0      0x009100 +#define NV04_PTIMER_INTR_EN_0   0x009140 +#define NV04_PTIMER_NUMERATOR   0x009200 +#define NV04_PTIMER_DENOMINATOR 0x009210 +#define NV04_PTIMER_TIME_0      0x009400 +#define NV04_PTIMER_TIME_1      0x009410 +#define NV04_PTIMER_ALARM_0     0x009420 + +struct nv04_timer_priv { +	struct nouveau_timer base; +	struct list_head alarms; +	spinlock_t lock; +	u64 suspend_time; +}; + +int  nv04_timer_ctor(struct nouveau_object *, struct nouveau_object *, +		     struct nouveau_oclass *, void *, u32, +		     struct nouveau_object **); +void nv04_timer_dtor(struct nouveau_object *); +int  nv04_timer_fini(struct nouveau_object *, bool); + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h new file mode 100644 index 00000000000..799dae3f230 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/priv.h @@ -0,0 +1,6 @@ +#ifndef __NVKM_TIMER_PRIV_H__ +#define __NVKM_TIMER_PRIV_H__ + +#include <subdev/timer.h> + +#endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index ef3133e7575..7dd680ff2f6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c @@ -72,13 +72,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)  	vmm->flush(vm);  } -void -nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) -{ -	nouveau_vm_map_at(vma, 0, node); -} - -void +static void  nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,  			struct nouveau_mem *mem)  { @@ -136,7 +130,7 @@ finish:  	vmm->flush(vm);  } -void +static void  nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,  		  struct nouveau_mem *mem)  { @@ -175,6 +169,18 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,  }  void +nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) +{ +	if (node->sg) +		nouveau_vm_map_sg_table(vma, 0, node->size << 12, node); +	else +	if (node->pages) +		nouveau_vm_map_sg(vma, 0, node->size << 12, node); +	else +		nouveau_vm_map_at(vma, 0, node); +} + +void  nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length)  {  	struct nouveau_vm *vm = vma->vm; diff --git a/drivers/gpu/drm/nouveau/core/subdev/volt/base.c b/drivers/gpu/drm/nouveau/core/subdev/volt/base.c new file mode 100644 index 00000000000..32794a99910 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/volt/base.c @@ -0,0 +1,198 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/volt.h> + +#include <subdev/bios.h> +#include <subdev/bios/vmap.h> +#include <subdev/bios/volt.h> + +static int +nouveau_volt_get(struct nouveau_volt *volt) +{ +	if (volt->vid_get) { +		int ret = volt->vid_get(volt), i; +		if (ret >= 0) { +			for (i = 0; i < volt->vid_nr; i++) { +				if (volt->vid[i].vid == ret) +					return volt->vid[i].uv; +			} +			ret = -EINVAL; +		} +		return ret; +	} +	return -ENODEV; +} + +static int +nouveau_volt_set(struct nouveau_volt *volt, u32 uv) +{ +	if (volt->vid_set) { +		int i, ret = -EINVAL; +		for (i = 0; i < volt->vid_nr; i++) { +			if (volt->vid[i].uv == uv) { +				ret = volt->vid_set(volt, volt->vid[i].vid); +				nv_debug(volt, "set %duv: %d\n", uv, ret); +				break; +			} +		} +		return ret; +	} +	return -ENODEV; +} + +static int +nouveau_volt_map(struct nouveau_volt *volt, u8 id) +{ +	struct nouveau_bios *bios = nouveau_bios(volt); +	struct nvbios_vmap_entry info; +	u8  ver, len; +	u16 vmap; + +	vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info); +	if (vmap) { +		if (info.link != 0xff) { +			int ret = nouveau_volt_map(volt, info.link); +			if (ret < 0) +				return ret; +			info.min += ret; +		} +		return info.min; +	} + +	return id ? id * 10000 : -ENODEV; +} + +static int +nouveau_volt_set_id(struct nouveau_volt *volt, u8 id, int condition) +{ +	int ret = nouveau_volt_map(volt, id); +	if (ret >= 0) { +		int prev = nouveau_volt_get(volt); +		if (!condition || prev < 0 || +		    (condition < 0 && ret < prev) || +		    (condition > 0 && ret > prev)) { +			ret = nouveau_volt_set(volt, ret); +		} else { +			ret = 0; +		} +	} +	return ret; +} + +int +_nouveau_volt_init(struct nouveau_object *object) +{ +	struct nouveau_volt *volt = (void *)object; +	int ret; + +	ret = nouveau_subdev_init(&volt->base); +	if (ret) +		return ret; + +	ret = volt->get(volt); +	if (ret < 0) { +		if (ret != -ENODEV) +			nv_debug(volt, "current voltage unknown\n"); +		return 0; +	} + +	nv_info(volt, "GPU voltage: %duv\n", ret); +	return 0; +} + +void +_nouveau_volt_dtor(struct nouveau_object *object) +{ +	struct nouveau_volt *volt = (void *)object; +	nouveau_subdev_destroy(&volt->base); +} + +int +nouveau_volt_create_(struct nouveau_object *parent, +		     struct nouveau_object *engine, +		     struct nouveau_oclass *oclass, int length, void **pobject) +{ +	struct nouveau_bios *bios = nouveau_bios(parent); +	struct nouveau_volt *volt; +	struct nvbios_volt_entry ivid; +	struct nvbios_volt info; +	u8  ver, hdr, cnt, len; +	u16 data; +	int ret, i; + +	ret = nouveau_subdev_create_(parent, engine, oclass, 0, "VOLT", +				     "voltage", length, pobject); +	volt = *pobject; +	if (ret) +		return ret; + +	volt->get = nouveau_volt_get; +	volt->set = nouveau_volt_set; +	volt->set_id = nouveau_volt_set_id; + +	data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info); +	if (data && info.vidmask && info.base && info.step) { +		for (i = 0; i < info.vidmask + 1; i++) { +			if (info.base >= info.min && +			    info.base <= info.max) { +				volt->vid[volt->vid_nr].uv = info.base; +				volt->vid[volt->vid_nr].vid = i; +				volt->vid_nr++; +			} +			info.base += info.step; +		} +		volt->vid_mask = info.vidmask; +	} else +	if (data && info.vidmask) { +		for (i = 0; i < cnt; i++) { +			data = nvbios_volt_entry_parse(bios, i, &ver, &hdr, +						      &ivid); +			if (data) { +				volt->vid[volt->vid_nr].uv = ivid.voltage; +				volt->vid[volt->vid_nr].vid = ivid.vid; +				volt->vid_nr++; +			} +		} +		volt->vid_mask = info.vidmask; +	} + +	if (volt->vid_nr) { +		for (i = 0; i < volt->vid_nr; i++) { +			nv_debug(volt, "VID %02x: %duv\n", +				 volt->vid[i].vid, volt->vid[i].uv); +		} + +		/*XXX: this is an assumption.. there probably exists boards +		 * out there with i2c-connected voltage controllers too.. +		 */ +		ret = nouveau_voltgpio_init(volt); +		if (ret == 0) { +			volt->vid_get = nouveau_voltgpio_get; +			volt->vid_set = nouveau_voltgpio_set; +		} +	} + +	return ret; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/volt/gpio.c b/drivers/gpu/drm/nouveau/core/subdev/volt/gpio.c new file mode 100644 index 00000000000..755fa91bcd0 --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/volt/gpio.c @@ -0,0 +1,96 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/volt.h> +#include <subdev/gpio.h> +#include <subdev/bios/gpio.h> + +static const u8 tags[] = { +	DCB_GPIO_VID0, DCB_GPIO_VID1, DCB_GPIO_VID2, DCB_GPIO_VID3, +	DCB_GPIO_VID4, DCB_GPIO_VID5, DCB_GPIO_VID6, DCB_GPIO_VID7, +}; + +int +nouveau_voltgpio_get(struct nouveau_volt *volt) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(volt); +	u8 vid = 0; +	int i; + +	for (i = 0; i < ARRAY_SIZE(tags); i++) { +		if (volt->vid_mask & (1 << i)) { +			int ret = gpio->get(gpio, 0, tags[i], 0xff); +			if (ret < 0) +				return ret; +			vid |= ret << i; +		} +	} + +	return vid; +} + +int +nouveau_voltgpio_set(struct nouveau_volt *volt, u8 vid) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(volt); +	int i; + +	for (i = 0; i < ARRAY_SIZE(tags); i++, vid >>= 1) { +		if (volt->vid_mask & (1 << i)) { +			int ret = gpio->set(gpio, 0, tags[i], 0xff, vid & 1); +			if (ret < 0) +				return ret; +		} +	} + +	return 0; +} + +int +nouveau_voltgpio_init(struct nouveau_volt *volt) +{ +	struct nouveau_gpio *gpio = nouveau_gpio(volt); +	struct dcb_gpio_func func; +	int i; + +	/* check we have gpio function info for each vid bit.  on some +	 * boards (ie. nvs295) the vid mask has more bits than there +	 * are valid gpio functions... from traces, nvidia appear to +	 * just touch the existing ones, so let's mask off the invalid +	 * bits and continue with life +	 */ +	for (i = 0; i < ARRAY_SIZE(tags); i++) { +		if (volt->vid_mask & (1 << i)) { +			int ret = gpio->find(gpio, 0, tags[i], 0xff, &func); +			if (ret) { +				if (ret != -ENOENT) +					return ret; +				nv_debug(volt, "VID bit %d has no GPIO\n", i); +				volt->vid_mask &= ~(1 << i); +			} +		} +	} + +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/core/subdev/volt/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/volt/nv40.c new file mode 100644 index 00000000000..87d5358376a --- /dev/null +++ b/drivers/gpu/drm/nouveau/core/subdev/volt/nv40.c @@ -0,0 +1,56 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include <subdev/volt.h> + +struct nv40_volt_priv { +	struct nouveau_volt base; +}; + +static int +nv40_volt_ctor(struct nouveau_object *parent, struct nouveau_object *engine, +	       struct nouveau_oclass *oclass, void *data, u32 size, +	       struct nouveau_object **pobject) +{ +	struct nv40_volt_priv *priv; +	int ret; + +	ret = nouveau_volt_create(parent, engine, oclass, &priv); +	*pobject = nv_object(priv); +	if (ret) +		return ret; + +	return 0; +} + +struct nouveau_oclass +nv40_volt_oclass = { +	.handle = NV_SUBDEV(VOLT, 0x40), +	.ofuncs = &(struct nouveau_ofuncs) { +		.ctor = nv40_volt_ctor, +		.dtor = _nouveau_volt_dtor, +		.init = _nouveau_volt_init, +		.fini = _nouveau_volt_fini, +	}, +}; diff --git a/drivers/gpu/drm/nouveau/dispnv04/Makefile b/drivers/gpu/drm/nouveau/dispnv04/Makefile index ea3f5b8a0f9..424a489d0f0 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/Makefile +++ b/drivers/gpu/drm/nouveau/dispnv04/Makefile @@ -5,6 +5,7 @@ nouveau-y += dispnv04/dac.o  nouveau-y += dispnv04/dfp.o  nouveau-y += dispnv04/disp.o  nouveau-y += dispnv04/hw.o +nouveau-y += dispnv04/overlay.o  nouveau-y += dispnv04/tvmodesnv17.o  nouveau-y += dispnv04/tvnv04.o  nouveau-y += dispnv04/tvnv17.o diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c index 2e70462883e..2a15b98b4d2 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/arb.c +++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c @@ -210,8 +210,8 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,  	sim_data.nvclk_khz = NVClk;  	sim_data.bpp = bpp;  	sim_data.two_heads = nv_two_heads(dev); -	if ((dev->pci_device & 0xffff) == 0x01a0 /*CHIPSET_NFORCE*/ || -	    (dev->pci_device & 0xffff) == 0x01f0 /*CHIPSET_NFORCE2*/) { +	if ((dev->pdev->device & 0xffff) == 0x01a0 /*CHIPSET_NFORCE*/ || +	    (dev->pdev->device & 0xffff) == 0x01f0 /*CHIPSET_NFORCE2*/) {  		uint32_t type;  		pci_read_config_dword(pci_get_bus_and_slot(0, 1), 0x7c, &type); @@ -256,8 +256,8 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm  	if (nv_device(drm->device)->card_type < NV_20)  		nv04_update_arb(dev, vclk, bpp, burst, lwm); -	else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || -		 (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { +	else if ((dev->pdev->device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || +		 (dev->pdev->device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) {  		*burst = 128;  		*lwm = 0x0480;  	} else diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index d4fbf11360f..41be3424c90 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -239,7 +239,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)  	struct drm_device *dev = crtc->dev;  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);  	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; -	struct drm_framebuffer *fb = crtc->fb; +	struct drm_framebuffer *fb = crtc->primary->fb;  	/* Calculate our timings */  	int horizDisplay	= (mode->crtc_hdisplay >> 3)		- 1; @@ -326,8 +326,6 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)  			regp->MiscOutReg = 0x23;	/* +hsync +vsync */  	} -	regp->MiscOutReg |= (mode->clock_index & 0x03) << 2; -  	/*  	 * Time Sequencer  	 */ @@ -576,7 +574,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)  		regp->CRTC[NV_CIO_CRE_86] = 0x1;  	} -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->fb->depth + 1) / 8; +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (crtc->primary->fb->depth + 1) / 8;  	/* Enable slaved mode (called MODE_TV in nv4ref.h) */  	if (lvds_output || tmds_output || tv_output)  		regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7); @@ -590,7 +588,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)  	regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |  				NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |  				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; -	if (crtc->fb->depth == 16) +	if (crtc->primary->fb->depth == 16)  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;  	if (nv_device(drm->device)->chipset >= 0x11)  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; @@ -611,7 +609,7 @@ static int  nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)  {  	struct nv04_display *disp = nv04_display(crtc->dev); -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); +	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);  	int ret; @@ -810,7 +808,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,  	 * mark the lut values as dirty by setting depth==0, and it'll be  	 * uploaded on the first mode_set_base()  	 */ -	if (!nv_crtc->base.fb) { +	if (!nv_crtc->base.primary->fb) {  		nv_crtc->lut.depth = 0;  		return;  	} @@ -834,7 +832,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,  	NV_DEBUG(drm, "index %d\n", nv_crtc->index);  	/* no fb bound */ -	if (!atomic && !crtc->fb) { +	if (!atomic && !crtc->primary->fb) {  		NV_DEBUG(drm, "No FB bound\n");  		return 0;  	} @@ -846,8 +844,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,  		drm_fb = passed_fb;  		fb = nouveau_framebuffer(passed_fb);  	} else { -		drm_fb = crtc->fb; -		fb = nouveau_framebuffer(crtc->fb); +		drm_fb = crtc->primary->fb; +		fb = nouveau_framebuffer(crtc->primary->fb);  	}  	nv_crtc->fb.offset = fb->nvbo->bo.offset; @@ -859,9 +857,9 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,  	/* Update the framebuffer format. */  	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] &= ~3; -	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->fb->depth + 1) / 8; +	regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (crtc->primary->fb->depth + 1) / 8;  	regp->ramdac_gen_ctrl &= ~NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; -	if (crtc->fb->depth == 16) +	if (crtc->primary->fb->depth == 16)  		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;  	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_PIXEL_INDEX);  	NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_GENERAL_CONTROL, @@ -1050,7 +1048,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set)  	/* get a pm reference here */  	ret = pm_runtime_get_sync(dev->dev); -	if (ret < 0) +	if (ret < 0 && ret != -EACCES)  		return ret;  	ret = drm_crtc_helper_set_config(set); diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c index 434b920f6bd..a96dda48718 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dac.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -414,7 +414,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON);  	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", -		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nouveau_encoder_connector_get(nv_encoder)->base.name,  		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  } diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index 93dd23ff009..e57babb206d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -415,7 +415,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,  	/* Output property. */  	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) ||  	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO && -	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { +	     encoder->crtc->primary->fb->depth > connector->display_info.bpc * 3)) {  		if (nv_device(drm->device)->chipset == 0x11)  			regp->dither = savep->dither | 0x00010000;  		else { @@ -477,7 +477,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON);  	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", -		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nouveau_encoder_connector_get(nv_encoder)->base.name,  		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  } @@ -490,10 +490,10 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)  	/* BIOS scripts usually take care of the backlight, thanks  	 * Apple for your consistency.  	 */ -	if (dev->pci_device == 0x0174 || dev->pci_device == 0x0179 || -	    dev->pci_device == 0x0189 || dev->pci_device == 0x0329) { +	if (dev->pdev->device == 0x0174 || dev->pdev->device == 0x0179 || +	    dev->pdev->device == 0x0189 || dev->pdev->device == 0x0329) {  		if (mode == DRM_MODE_DPMS_ON) { -			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); +			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 1 << 31);  			nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1);  		} else {  			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); @@ -625,13 +625,15 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);  	struct nouveau_i2c_port *port = i2c->find(i2c, 2); -	struct i2c_board_info info[] = { +	struct nouveau_i2c_board_info info[] = {  		{ -			.type = "sil164", -			.addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38), -			.platform_data = &(struct sil164_encoder_params) { -				SIL164_INPUT_EDGE_RISING -			} +		    { +		        .type = "sil164", +		        .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38), +		        .platform_data = &(struct sil164_encoder_params) { +		            SIL164_INPUT_EDGE_RISING +		         } +		    }, 0  		},  		{ }  	}; @@ -641,12 +643,12 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder)  	    get_tmds_slave(encoder))  		return; -	type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); +	type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL, NULL);  	if (type < 0)  		return;  	drm_i2c_encoder_init(dev, to_encoder_slave(encoder), -			     &port->adapter, &info[type]); +			     &port->adapter, &info[type].dev);  }  static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 4908d3fd048..4342fdaee70 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -77,11 +77,6 @@ nv04_display_create(struct drm_device *dev)  	nouveau_hw_save_vga_fonts(dev, 1); -	ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000, -				 NV04_DISP_CLASS, NULL, 0, &disp->core); -	if (ret) -		return ret; -  	nv04_crtc_create(dev, 0);  	if (nv_two_heads(dev))  		nv04_crtc_create(dev, 1); @@ -120,7 +115,7 @@ nv04_display_create(struct drm_device *dev)  				 &dev->mode_config.connector_list, head) {  		if (!connector->encoder_ids[0]) {  			NV_WARN(drm, "%s has no encoders, removing\n", -				drm_get_connector_name(connector)); +				connector->name);  			connector->funcs->destroy(connector);  		}  	} @@ -140,6 +135,8 @@ nv04_display_create(struct drm_device *dev)  		func->save(encoder);  	} +	nouveau_overlay_init(dev); +  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index 9928187f0a7..4245fc3dab7 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -80,7 +80,6 @@ struct nv04_display {  	struct nv04_mode_state saved_reg;  	uint32_t saved_vga_font[4][16384];  	uint32_t dac_users[4]; -	struct nouveau_object *core;  	struct nouveau_bo *image[2];  }; @@ -123,11 +122,14 @@ int nv04_tv_create(struct drm_connector *, struct dcb_output *);  /* nv17_tv.c */  int nv17_tv_create(struct drm_connector *, struct dcb_output *); +/* overlay.c */ +void nouveau_overlay_init(struct drm_device *dev); +  static inline bool  nv_two_heads(struct drm_device *dev)  {  	struct nouveau_drm *drm = nouveau_drm(dev); -	const int impl = dev->pci_device & 0x0ff0; +	const int impl = dev->pdev->device & 0x0ff0;  	if (nv_device(drm->device)->card_type >= NV_10 && impl != 0x0100 &&  	    impl != 0x0150 && impl != 0x01a0 && impl != 0x0200) @@ -139,14 +141,14 @@ nv_two_heads(struct drm_device *dev)  static inline bool  nv_gf4_disp_arch(struct drm_device *dev)  { -	return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110; +	return nv_two_heads(dev) && (dev->pdev->device & 0x0ff0) != 0x0110;  }  static inline bool  nv_two_reg_pll(struct drm_device *dev)  {  	struct nouveau_drm *drm = nouveau_drm(dev); -	const int impl = dev->pci_device & 0x0ff0; +	const int impl = dev->pdev->device & 0x0ff0;  	if (impl == 0x0310 || impl == 0x0340 || nv_device(drm->device)->card_type >= NV_40)  		return true; diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c index 973056b8620..aca76af115b 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/hw.c +++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c @@ -27,6 +27,7 @@  #include "hw.h"  #include <subdev/bios/pll.h> +#include <subdev/fb.h>  #include <subdev/clock.h>  #include <subdev/timer.h> @@ -220,7 +221,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)  	int ret;  	if (plltype == PLL_MEMORY && -	    (dev->pci_device & 0x0ff0) == CHIPSET_NFORCE) { +	    (dev->pdev->device & 0x0ff0) == CHIPSET_NFORCE) {  		uint32_t mpllP;  		pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP); @@ -230,7 +231,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)  		return 400000 / mpllP;  	} else  	if (plltype == PLL_MEMORY && -	    (dev->pci_device & 0xff0) == CHIPSET_NFORCE2) { +	    (dev->pdev->device & 0xff0) == CHIPSET_NFORCE2) {  		uint32_t clock;  		pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock); @@ -664,6 +665,7 @@ nv_load_state_ext(struct drm_device *dev, int head,  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_device *device = nv_device(drm->device);  	struct nouveau_timer *ptimer = nouveau_timer(device); +	struct nouveau_fb *pfb = nouveau_fb(device);  	struct nv04_crtc_reg *regp = &state->crtc_reg[head];  	uint32_t reg900;  	int i; @@ -680,10 +682,10 @@ nv_load_state_ext(struct drm_device *dev, int head,  		nv_wr32(device, NV_PVIDEO_INTR_EN, 0);  		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0);  		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0); -		nv_wr32(device, NV_PVIDEO_LIMIT(0), 0); //drm->fb_available_size - 1); -		nv_wr32(device, NV_PVIDEO_LIMIT(1), 0); //drm->fb_available_size - 1); -		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //drm->fb_available_size - 1); -		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //drm->fb_available_size - 1); +		nv_wr32(device, NV_PVIDEO_LIMIT(0), pfb->ram->size - 1); +		nv_wr32(device, NV_PVIDEO_LIMIT(1), pfb->ram->size - 1); +		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), pfb->ram->size - 1); +		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), pfb->ram->size - 1);  		nv_wr32(device, NV_PBUS_POWERCTRL_2, 0);  		NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); @@ -740,7 +742,7 @@ nv_load_state_ext(struct drm_device *dev, int head,  	}  	/* NV11 and NV20 stop at 0x52. */  	if (nv_gf4_disp_arch(dev)) { -		if (nv_device(drm->device)->card_type == NV_10) { +		if (nv_device(drm->device)->card_type < NV_20) {  			/* Not waiting for vertical retrace before modifying  			   CRE_53/CRE_54 causes lockups. */  			nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c new file mode 100644 index 00000000000..ab03f7719d2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c @@ -0,0 +1,497 @@ +/* + * Copyright 2013 Ilia Mirkin + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Implementation based on the pre-KMS implementation in xf86-video-nouveau, + * written by Arthur Huillet. + */ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_fourcc.h> + +#include "nouveau_drm.h" + +#include "nouveau_bo.h" +#include "nouveau_connector.h" +#include "nouveau_display.h" +#include "nvreg.h" + + +struct nouveau_plane { +	struct drm_plane base; +	bool flip; +	struct nouveau_bo *cur; + +	struct { +		struct drm_property *colorkey; +		struct drm_property *contrast; +		struct drm_property *brightness; +		struct drm_property *hue; +		struct drm_property *saturation; +		struct drm_property *iturbt_709; +	} props; + +	int colorkey; +	int contrast; +	int brightness; +	int hue; +	int saturation; +	int iturbt_709; + +	void (*set_params)(struct nouveau_plane *); +}; + +static uint32_t formats[] = { +	DRM_FORMAT_YUYV, +	DRM_FORMAT_UYVY, +	DRM_FORMAT_NV12, +}; + +/* Sine can be approximated with + * http://en.wikipedia.org/wiki/Bhaskara_I's_sine_approximation_formula + * sin(x degrees) ~= 4 x (180 - x) / (40500 - x (180 - x) ) + * Note that this only works for the range [0, 180]. + * Also note that sin(x) == -sin(x - 180) + */ +static inline int +sin_mul(int degrees, int factor) +{ +	if (degrees > 180) { +		degrees -= 180; +		factor *= -1; +	} +	return factor * 4 * degrees * (180 - degrees) / +		(40500 - degrees * (180 - degrees)); +} + +/* cos(x) = sin(x + 90) */ +static inline int +cos_mul(int degrees, int factor) +{ +	return sin_mul((degrees + 90) % 360, factor); +} + +static int +nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, +		  struct drm_framebuffer *fb, int crtc_x, int crtc_y, +		  unsigned int crtc_w, unsigned int crtc_h, +		  uint32_t src_x, uint32_t src_y, +		  uint32_t src_w, uint32_t src_h) +{ +	struct nouveau_device *dev = nouveau_dev(plane->dev); +	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); +	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); +	struct nouveau_bo *cur = nv_plane->cur; +	bool flip = nv_plane->flip; +	int soff = NV_PCRTC0_SIZE * nv_crtc->index; +	int soff2 = NV_PCRTC0_SIZE * !nv_crtc->index; +	int format, ret; + +	/* Source parameters given in 16.16 fixed point, ignore fractional. */ +	src_x >>= 16; +	src_y >>= 16; +	src_w >>= 16; +	src_h >>= 16; + +	format = ALIGN(src_w * 4, 0x100); + +	if (format > 0xffff) +		return -ERANGE; + +	if (dev->chipset >= 0x30) { +		if (crtc_w < (src_w >> 1) || crtc_h < (src_h >> 1)) +			return -ERANGE; +	} else { +		if (crtc_w < (src_w >> 3) || crtc_h < (src_h >> 3)) +			return -ERANGE; +	} + +	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); +	if (ret) +		return ret; + +	nv_plane->cur = nv_fb->nvbo; + +	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff, NV_CRTC_FSEL_OVERLAY, NV_CRTC_FSEL_OVERLAY); +	nv_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0); + +	nv_wr32(dev, NV_PVIDEO_BASE(flip), 0); +	nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nv_fb->nvbo->bo.offset); +	nv_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w); +	nv_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x); +	nv_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w); +	nv_wr32(dev, NV_PVIDEO_DT_DY(flip), (src_h << 20) / crtc_h); +	nv_wr32(dev, NV_PVIDEO_POINT_OUT(flip), crtc_y << 16 | crtc_x); +	nv_wr32(dev, NV_PVIDEO_SIZE_OUT(flip), crtc_h << 16 | crtc_w); + +	if (fb->pixel_format != DRM_FORMAT_UYVY) +		format |= NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8; +	if (fb->pixel_format == DRM_FORMAT_NV12) +		format |= NV_PVIDEO_FORMAT_PLANAR; +	if (nv_plane->iturbt_709) +		format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; +	if (nv_plane->colorkey & (1 << 24)) +		format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; + +	if (fb->pixel_format == DRM_FORMAT_NV12) { +		nv_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0); +		nv_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip), +			nv_fb->nvbo->bo.offset + fb->offsets[1]); +	} +	nv_wr32(dev, NV_PVIDEO_FORMAT(flip), format); +	nv_wr32(dev, NV_PVIDEO_STOP, 0); +	/* TODO: wait for vblank? */ +	nv_wr32(dev, NV_PVIDEO_BUFFER, flip ? 0x10 : 0x1); +	nv_plane->flip = !flip; + +	if (cur) +		nouveau_bo_unpin(cur); + +	return 0; +} + +static int +nv10_disable_plane(struct drm_plane *plane) +{ +	struct nouveau_device *dev = nouveau_dev(plane->dev); +	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + +	nv_wr32(dev, NV_PVIDEO_STOP, 1); +	if (nv_plane->cur) { +		nouveau_bo_unpin(nv_plane->cur); +		nv_plane->cur = NULL; +	} + +	return 0; +} + +static void +nv_destroy_plane(struct drm_plane *plane) +{ +	plane->funcs->disable_plane(plane); +	drm_plane_cleanup(plane); +	kfree(plane); +} + +static void +nv10_set_params(struct nouveau_plane *plane) +{ +	struct nouveau_device *dev = nouveau_dev(plane->base.dev); +	u32 luma = (plane->brightness - 512) << 16 | plane->contrast; +	u32 chroma = ((sin_mul(plane->hue, plane->saturation) & 0xffff) << 16) | +		(cos_mul(plane->hue, plane->saturation) & 0xffff); +	u32 format = 0; + +	nv_wr32(dev, NV_PVIDEO_LUMINANCE(0), luma); +	nv_wr32(dev, NV_PVIDEO_LUMINANCE(1), luma); +	nv_wr32(dev, NV_PVIDEO_CHROMINANCE(0), chroma); +	nv_wr32(dev, NV_PVIDEO_CHROMINANCE(1), chroma); +	nv_wr32(dev, NV_PVIDEO_COLOR_KEY, plane->colorkey & 0xffffff); + +	if (plane->cur) { +		if (plane->iturbt_709) +			format |= NV_PVIDEO_FORMAT_MATRIX_ITURBT709; +		if (plane->colorkey & (1 << 24)) +			format |= NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY; +		nv_mask(dev, NV_PVIDEO_FORMAT(plane->flip), +			NV_PVIDEO_FORMAT_MATRIX_ITURBT709 | +			NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY, +			format); +	} +} + +static int +nv_set_property(struct drm_plane *plane, +		struct drm_property *property, +		uint64_t value) +{ +	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + +	if (property == nv_plane->props.colorkey) +		nv_plane->colorkey = value; +	else if (property == nv_plane->props.contrast) +		nv_plane->contrast = value; +	else if (property == nv_plane->props.brightness) +		nv_plane->brightness = value; +	else if (property == nv_plane->props.hue) +		nv_plane->hue = value; +	else if (property == nv_plane->props.saturation) +		nv_plane->saturation = value; +	else if (property == nv_plane->props.iturbt_709) +		nv_plane->iturbt_709 = value; +	else +		return -EINVAL; + +	if (nv_plane->set_params) +		nv_plane->set_params(nv_plane); +	return 0; +} + +static const struct drm_plane_funcs nv10_plane_funcs = { +	.update_plane = nv10_update_plane, +	.disable_plane = nv10_disable_plane, +	.set_property = nv_set_property, +	.destroy = nv_destroy_plane, +}; + +static void +nv10_overlay_init(struct drm_device *device) +{ +	struct nouveau_device *dev = nouveau_dev(device); +	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); +	int num_formats = ARRAY_SIZE(formats); +	int ret; + +	if (!plane) +		return; + +	switch (dev->chipset) { +	case 0x10: +	case 0x11: +	case 0x15: +	case 0x1a: +	case 0x20: +		num_formats = 2; +		break; +	} + +	ret = drm_plane_init(device, &plane->base, 3 /* both crtc's */, +			     &nv10_plane_funcs, +			     formats, num_formats, false); +	if (ret) +		goto err; + +	/* Set up the plane properties */ +	plane->props.colorkey = drm_property_create_range( +			device, 0, "colorkey", 0, 0x01ffffff); +	plane->props.contrast = drm_property_create_range( +			device, 0, "contrast", 0, 8192 - 1); +	plane->props.brightness = drm_property_create_range( +			device, 0, "brightness", 0, 1024); +	plane->props.hue = drm_property_create_range( +			device, 0, "hue", 0, 359); +	plane->props.saturation = drm_property_create_range( +			device, 0, "saturation", 0, 8192 - 1); +	plane->props.iturbt_709 = drm_property_create_range( +			device, 0, "iturbt_709", 0, 1); +	if (!plane->props.colorkey || +	    !plane->props.contrast || +	    !plane->props.brightness || +	    !plane->props.hue || +	    !plane->props.saturation || +	    !plane->props.iturbt_709) +		goto cleanup; + +	plane->colorkey = 0; +	drm_object_attach_property(&plane->base.base, +				   plane->props.colorkey, plane->colorkey); + +	plane->contrast = 0x1000; +	drm_object_attach_property(&plane->base.base, +				   plane->props.contrast, plane->contrast); + +	plane->brightness = 512; +	drm_object_attach_property(&plane->base.base, +				   plane->props.brightness, plane->brightness); + +	plane->hue = 0; +	drm_object_attach_property(&plane->base.base, +				   plane->props.hue, plane->hue); + +	plane->saturation = 0x1000; +	drm_object_attach_property(&plane->base.base, +				   plane->props.saturation, plane->saturation); + +	plane->iturbt_709 = 0; +	drm_object_attach_property(&plane->base.base, +				   plane->props.iturbt_709, plane->iturbt_709); + +	plane->set_params = nv10_set_params; +	nv10_set_params(plane); +	nv10_disable_plane(&plane->base); +	return; +cleanup: +	drm_plane_cleanup(&plane->base); +err: +	kfree(plane); +	nv_error(dev, "Failed to create plane\n"); +} + +static int +nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, +		  struct drm_framebuffer *fb, int crtc_x, int crtc_y, +		  unsigned int crtc_w, unsigned int crtc_h, +		  uint32_t src_x, uint32_t src_y, +		  uint32_t src_w, uint32_t src_h) +{ +	struct nouveau_device *dev = nouveau_dev(plane->dev); +	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; +	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); +	struct nouveau_bo *cur = nv_plane->cur; +	uint32_t overlay = 1; +	int brightness = (nv_plane->brightness - 512) * 62 / 512; +	int pitch, ret, i; + +	/* Source parameters given in 16.16 fixed point, ignore fractional. */ +	src_x >>= 16; +	src_y >>= 16; +	src_w >>= 16; +	src_h >>= 16; + +	pitch = ALIGN(src_w * 4, 0x100); + +	if (pitch > 0xffff) +		return -ERANGE; + +	/* TODO: Compute an offset? Not sure how to do this for YUYV. */ +	if (src_x != 0 || src_y != 0) +		return -ERANGE; + +	if (crtc_w < src_w || crtc_h < src_h) +		return -ERANGE; + +	ret = nouveau_bo_pin(nv_fb->nvbo, TTM_PL_FLAG_VRAM); +	if (ret) +		return ret; + +	nv_plane->cur = nv_fb->nvbo; + +	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0); +	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0); +	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0); + +	for (i = 0; i < 2; i++) { +		nv_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i, +			nv_fb->nvbo->bo.offset); +		nv_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i, pitch); +		nv_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0); +	} +	nv_wr32(dev, NV_PVIDEO_WINDOW_START, crtc_y << 16 | crtc_x); +	nv_wr32(dev, NV_PVIDEO_WINDOW_SIZE, crtc_h << 16 | crtc_w); +	nv_wr32(dev, NV_PVIDEO_STEP_SIZE, +		(uint32_t)(((src_h - 1) << 11) / (crtc_h - 1)) << 16 | (uint32_t)(((src_w - 1) << 11) / (crtc_w - 1))); + +	/* It should be possible to convert hue/contrast to this */ +	nv_wr32(dev, NV_PVIDEO_RED_CSC_OFFSET, 0x69 - brightness); +	nv_wr32(dev, NV_PVIDEO_GREEN_CSC_OFFSET, 0x3e + brightness); +	nv_wr32(dev, NV_PVIDEO_BLUE_CSC_OFFSET, 0x89 - brightness); +	nv_wr32(dev, NV_PVIDEO_CSC_ADJUST, 0); + +	nv_wr32(dev, NV_PVIDEO_CONTROL_Y, 0x001); /* (BLUR_ON, LINE_HALF) */ +	nv_wr32(dev, NV_PVIDEO_CONTROL_X, 0x111); /* (WEIGHT_HEAVY, SHARPENING_ON, SMOOTHING_ON) */ + +	nv_wr32(dev, NV_PVIDEO_FIFO_BURST_LENGTH, 0x03); +	nv_wr32(dev, NV_PVIDEO_FIFO_THRES_SIZE, 0x38); + +	nv_wr32(dev, NV_PVIDEO_KEY, nv_plane->colorkey); + +	if (nv_plane->colorkey & (1 << 24)) +		overlay |= 0x10; +	if (fb->pixel_format == DRM_FORMAT_YUYV) +		overlay |= 0x100; + +	nv_wr32(dev, NV_PVIDEO_OVERLAY, overlay); + +	nv_wr32(dev, NV_PVIDEO_SU_STATE, nv_rd32(dev, NV_PVIDEO_SU_STATE) ^ (1 << 16)); + +	if (cur) +		nouveau_bo_unpin(cur); + +	return 0; +} + +static int +nv04_disable_plane(struct drm_plane *plane) +{ +	struct nouveau_device *dev = nouveau_dev(plane->dev); +	struct nouveau_plane *nv_plane = (struct nouveau_plane *)plane; + +	nv_mask(dev, NV_PVIDEO_OVERLAY, 1, 0); +	nv_wr32(dev, NV_PVIDEO_OE_STATE, 0); +	nv_wr32(dev, NV_PVIDEO_SU_STATE, 0); +	nv_wr32(dev, NV_PVIDEO_RM_STATE, 0); +	if (nv_plane->cur) { +		nouveau_bo_unpin(nv_plane->cur); +		nv_plane->cur = NULL; +	} + +	return 0; +} + +static const struct drm_plane_funcs nv04_plane_funcs = { +	.update_plane = nv04_update_plane, +	.disable_plane = nv04_disable_plane, +	.set_property = nv_set_property, +	.destroy = nv_destroy_plane, +}; + +static void +nv04_overlay_init(struct drm_device *device) +{ +	struct nouveau_device *dev = nouveau_dev(device); +	struct nouveau_plane *plane = kzalloc(sizeof(struct nouveau_plane), GFP_KERNEL); +	int ret; + +	if (!plane) +		return; + +	ret = drm_plane_init(device, &plane->base, 1 /* single crtc */, +			     &nv04_plane_funcs, +			     formats, 2, false); +	if (ret) +		goto err; + +	/* Set up the plane properties */ +	plane->props.colorkey = drm_property_create_range( +			device, 0, "colorkey", 0, 0x01ffffff); +	plane->props.brightness = drm_property_create_range( +			device, 0, "brightness", 0, 1024); +	if (!plane->props.colorkey || +	    !plane->props.brightness) +		goto cleanup; + +	plane->colorkey = 0; +	drm_object_attach_property(&plane->base.base, +				   plane->props.colorkey, plane->colorkey); + +	plane->brightness = 512; +	drm_object_attach_property(&plane->base.base, +				   plane->props.brightness, plane->brightness); + +	nv04_disable_plane(&plane->base); +	return; +cleanup: +	drm_plane_cleanup(&plane->base); +err: +	kfree(plane); +	nv_error(dev, "Failed to create plane\n"); +} + +void +nouveau_overlay_init(struct drm_device *device) +{ +	struct nouveau_device *dev = nouveau_dev(device); +	if (dev->chipset < 0x10) +		nv04_overlay_init(device); +	else if (dev->chipset <= 0x40) +		nv10_overlay_init(device); +} diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index bf13db4e863..8667620b703 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -37,15 +37,18 @@  #include <subdev/i2c.h> -static struct i2c_board_info nv04_tv_encoder_info[] = { +static struct nouveau_i2c_board_info nv04_tv_encoder_info[] = {  	{ -		I2C_BOARD_INFO("ch7006", 0x75), -		.platform_data = &(struct ch7006_encoder_params) { -			CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, -			0, 0, 0, -			CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, -			CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC -		} +		{ +			I2C_BOARD_INFO("ch7006", 0x75), +			.platform_data = &(struct ch7006_encoder_params) { +				CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, +				0, 0, 0, +				CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, +				CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC +			} +		}, +		0  	},  	{ }  }; @@ -56,7 +59,7 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index)  	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);  	return i2c->identify(i2c, i2c_index, "TV encoder", -			     nv04_tv_encoder_info, NULL); +			     nv04_tv_encoder_info, NULL, NULL);  } @@ -168,7 +171,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON);  	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", -		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +		 nouveau_encoder_connector_get(nv_encoder)->base.name, +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_tv_destroy(struct drm_encoder *encoder) @@ -229,7 +233,8 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)  	/* Run the slave-specific initialization */  	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), -				   &port->adapter, &nv04_tv_encoder_info[type]); +				   &port->adapter, +				   &nv04_tv_encoder_info[type].dev);  	if (ret < 0)  		goto fail_cleanup; diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index acef48f4a4e..195bd8e86c6 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -612,8 +612,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON);  	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name( -			&nouveau_encoder_connector_get(nv_encoder)->base), +		nouveau_encoder_connector_get(nv_encoder)->base.name,  		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  } diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 8f467e7bfd1..b13f441c643 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -87,6 +87,7 @@ nouveau_abi16_swclass(struct nouveau_drm *drm)  	case NV_04:  		return 0x006e;  	case NV_10: +	case NV_11:  	case NV_20:  	case NV_30:  	case NV_40: @@ -96,6 +97,7 @@ nouveau_abi16_swclass(struct nouveau_drm *drm)  	case NV_C0:  	case NV_D0:  	case NV_E0: +	case GM100:  		return 0x906e;  	} @@ -130,7 +132,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,  	if (chan->ntfy) {  		nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma);  		nouveau_bo_unpin(chan->ntfy); -		drm_gem_object_unreference_unlocked(chan->ntfy->gem); +		drm_gem_object_unreference_unlocked(&chan->ntfy->gem);  	}  	if (chan->heap.block_size) @@ -138,7 +140,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,  	/* destroy channel object, all children will be killed too */  	if (chan->chan) { -		abi16->handles &= ~(1 << (chan->chan->handle & 0xffff)); +		abi16->handles &= ~(1ULL << (chan->chan->handle & 0xffff));  		nouveau_channel_del(&chan->chan);  	} @@ -178,12 +180,21 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)  		getparam->value = device->chipset;  		break;  	case NOUVEAU_GETPARAM_PCI_VENDOR: -		getparam->value = dev->pci_vendor; +		if (nv_device_is_pci(device)) +			getparam->value = dev->pdev->vendor; +		else +			getparam->value = 0;  		break;  	case NOUVEAU_GETPARAM_PCI_DEVICE: -		getparam->value = dev->pci_device; +		if (nv_device_is_pci(device)) +			getparam->value = dev->pdev->device; +		else +			getparam->value = 0;  		break;  	case NOUVEAU_GETPARAM_BUS_TYPE: +		if (!nv_device_is_pci(device)) +			getparam->value = 3; +		else  		if (drm_pci_device_is_agp(dev))  			getparam->value = 0;  		else @@ -269,8 +280,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)  		return nouveau_abi16_put(abi16, -EINVAL);  	/* allocate "abi16 channel" data and make up a handle for it */ -	init->channel = ffsll(~abi16->handles); -	if (!init->channel--) +	init->channel = __ffs64(~abi16->handles); +	if (~abi16->handles == 0)  		return nouveau_abi16_put(abi16, -ENOSPC);  	chan = kzalloc(sizeof(*chan), GFP_KERNEL); @@ -279,7 +290,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)  	INIT_LIST_HEAD(&chan->notifiers);  	list_add(&chan->head, &abi16->channels); -	abi16->handles |= (1 << init->channel); +	abi16->handles |= (1ULL << init->channel);  	/* create channel object and initialise dma and fence management */  	ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | @@ -297,7 +308,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)  	else  		init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART; -	if (device->card_type < NV_C0) { +	if (device->card_type < NV_10) {  		init->subchan[0].handle = 0x00000000;  		init->subchan[0].grclass = 0x0000;  		init->subchan[1].handle = NvSw; @@ -320,7 +331,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)  			goto done;  	} -	ret = drm_gem_handle_create(file_priv, chan->ntfy->gem, +	ret = drm_gem_handle_create(file_priv, &chan->ntfy->gem,  				    &init->notifier_handle);  	if (ret)  		goto done; @@ -446,6 +457,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)  	if (ret)  		goto done; +	info->offset = ntfy->node->offset; +  done:  	if (ret)  		nouveau_abi16_ntfy_fini(chan, ntfy); diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index dd7d2e18271..279206997e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -1,15 +1,10 @@  #include <linux/pci.h>  #include <linux/acpi.h>  #include <linux/slab.h> -#include <acpi/acpi_drivers.h> -#include <acpi/acpi_bus.h> -#include <acpi/video.h> -#include <acpi/acpi.h>  #include <linux/mxm-wmi.h> -  #include <linux/vga_switcheroo.h> -  #include <drm/drm_edid.h> +#include <acpi/video.h>  #include "nouveau_drm.h"  #include "nouveau_acpi.h" @@ -51,6 +46,7 @@ static struct nouveau_dsm_priv {  	bool dsm_detected;  	bool optimus_detected;  	acpi_handle dhandle; +	acpi_handle other_handle;  	acpi_handle rom_handle;  } nouveau_dsm_priv; @@ -65,6 +61,7 @@ bool nouveau_is_v1_dsm(void) {  #define NOUVEAU_DSM_HAS_MUX 0x1  #define NOUVEAU_DSM_HAS_OPT 0x2 +#ifdef CONFIG_VGA_SWITCHEROO  static const char nouveau_dsm_muid[] = {  	0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,  	0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, @@ -77,124 +74,89 @@ static const char nouveau_op_dsm_muid[] = {  static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t *result)  { -	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; -	struct acpi_object_list input; -	union acpi_object params[4]; +	int i;  	union acpi_object *obj; -	int i, err;  	char args_buff[4]; +	union acpi_object argv4 = { +		.buffer.type = ACPI_TYPE_BUFFER, +		.buffer.length = 4, +		.buffer.pointer = args_buff +	}; -	input.count = 4; -	input.pointer = params; -	params[0].type = ACPI_TYPE_BUFFER; -	params[0].buffer.length = sizeof(nouveau_op_dsm_muid); -	params[0].buffer.pointer = (char *)nouveau_op_dsm_muid; -	params[1].type = ACPI_TYPE_INTEGER; -	params[1].integer.value = 0x00000100; -	params[2].type = ACPI_TYPE_INTEGER; -	params[2].integer.value = func; -	params[3].type = ACPI_TYPE_BUFFER; -	params[3].buffer.length = 4;  	/* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */  	for (i = 0; i < 4; i++)  		args_buff[i] = (arg >> i * 8) & 0xFF; -	params[3].buffer.pointer = args_buff; - -	err = acpi_evaluate_object(handle, "_DSM", &input, &output); -	if (err) { -		printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); -		return err; -	} -	obj = (union acpi_object *)output.pointer; - -	if (obj->type == ACPI_TYPE_INTEGER) -		if (obj->integer.value == 0x80000002) { -			return -ENODEV; -		} - -	if (obj->type == ACPI_TYPE_BUFFER) { -		if (obj->buffer.length == 4 && result) { -			*result = 0; +	*result = 0; +	obj = acpi_evaluate_dsm_typed(handle, nouveau_op_dsm_muid, 0x00000100, +				      func, &argv4, ACPI_TYPE_BUFFER); +	if (!obj) { +		acpi_handle_info(handle, "failed to evaluate _DSM\n"); +		return AE_ERROR; +	} else { +		if (obj->buffer.length == 4) {  			*result |= obj->buffer.pointer[0];  			*result |= (obj->buffer.pointer[1] << 8);  			*result |= (obj->buffer.pointer[2] << 16);  			*result |= (obj->buffer.pointer[3] << 24);  		} +		ACPI_FREE(obj);  	} -	kfree(output.pointer);  	return 0;  } -static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) +/* + * On some platforms, _DSM(nouveau_op_dsm_muid, func0) has special + * requirements on the fourth parameter, so a private implementation + * instead of using acpi_check_dsm(). + */ +static int nouveau_check_optimus_dsm(acpi_handle handle)  { -	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; -	struct acpi_object_list input; -	union acpi_object params[4]; -	union acpi_object *obj; -	int err; - -	input.count = 4; -	input.pointer = params; -	params[0].type = ACPI_TYPE_BUFFER; -	params[0].buffer.length = sizeof(nouveau_dsm_muid); -	params[0].buffer.pointer = (char *)nouveau_dsm_muid; -	params[1].type = ACPI_TYPE_INTEGER; -	params[1].integer.value = 0x00000102; -	params[2].type = ACPI_TYPE_INTEGER; -	params[2].integer.value = func; -	params[3].type = ACPI_TYPE_INTEGER; -	params[3].integer.value = arg; - -	err = acpi_evaluate_object(handle, "_DSM", &input, &output); -	if (err) { -		printk(KERN_INFO "failed to evaluate _DSM: %d\n", err); -		return err; -	} +	int result; -	obj = (union acpi_object *)output.pointer; - -	if (obj->type == ACPI_TYPE_INTEGER) -		if (obj->integer.value == 0x80000002) -			return -ENODEV; - -	if (obj->type == ACPI_TYPE_BUFFER) { -		if (obj->buffer.length == 4 && result) { -			*result = 0; -			*result |= obj->buffer.pointer[0]; -			*result |= (obj->buffer.pointer[1] << 8); -			*result |= (obj->buffer.pointer[2] << 16); -			*result |= (obj->buffer.pointer[3] << 24); -		} -	} +	/* +	 * Function 0 returns a Buffer containing available functions. +	 * The args parameter is ignored for function 0, so just put 0 in it +	 */ +	if (nouveau_optimus_dsm(handle, 0, 0, &result)) +		return 0; -	kfree(output.pointer); -	return 0; +	/* +	 * ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. +	 * If the n-th bit is enabled, function n is supported +	 */ +	return result & 1 && result & (1 << NOUVEAU_DSM_OPTIMUS_CAPS);  } -/* Returns 1 if a DSM function is usable and 0 otherwise */ -static int nouveau_test_dsm(acpi_handle test_handle, -	int (*dsm_func)(acpi_handle, int, int, uint32_t *), -	int sfnc) +static int nouveau_dsm(acpi_handle handle, int func, int arg)  { -	u32 result = 0; - -	/* Function 0 returns a Buffer containing available functions. The args -	 * parameter is ignored for function 0, so just put 0 in it */ -	if (dsm_func(test_handle, 0, 0, &result)) -		return 0; +	int ret = 0; +	union acpi_object *obj; +	union acpi_object argv4 = { +		.integer.type = ACPI_TYPE_INTEGER, +		.integer.value = arg, +	}; + +	obj = acpi_evaluate_dsm_typed(handle, nouveau_dsm_muid, 0x00000102, +				      func, &argv4, ACPI_TYPE_INTEGER); +	if (!obj) { +		acpi_handle_info(handle, "failed to evaluate _DSM\n"); +		return AE_ERROR; +	} else { +		if (obj->integer.value == 0x80000002) +			ret = -ENODEV; +		ACPI_FREE(obj); +	} -	/* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If -	 * the n-th bit is enabled, function n is supported */ -	return result & 1 && result & (1 << sfnc); +	return ret;  }  static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id)  {  	mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0);  	mxm_wmi_call_mxds(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); -	return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id, NULL); +	return nouveau_dsm(handle, NOUVEAU_DSM_LED, mux_id);  }  static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switcheroo_state state) @@ -204,7 +166,7 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero  		arg = NOUVEAU_DSM_POWER_SPEED;  	else  		arg = NOUVEAU_DSM_POWER_STAMINA; -	nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg, NULL); +	nouveau_dsm(handle, NOUVEAU_DSM_POWER, arg);  	return 0;  } @@ -253,24 +215,22 @@ static struct vga_switcheroo_handler nouveau_dsm_handler = {  static int nouveau_dsm_pci_probe(struct pci_dev *pdev)  { -	acpi_handle dhandle, nvidia_handle; -	acpi_status status; +	acpi_handle dhandle;  	int retval = 0; -	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); +	dhandle = ACPI_HANDLE(&pdev->dev);  	if (!dhandle)  		return false; -	status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle); -	if (ACPI_FAILURE(status)) { +	if (!acpi_has_method(dhandle, "_DSM")) { +		nouveau_dsm_priv.other_handle = dhandle;  		return false;  	} - -	if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) +	if (acpi_check_dsm(dhandle, nouveau_dsm_muid, 0x00000102, +			   1 << NOUVEAU_DSM_POWER))  		retval |= NOUVEAU_DSM_HAS_MUX; -	if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, -		NOUVEAU_DSM_OPTIMUS_CAPS)) +	if (nouveau_check_optimus_dsm(dhandle))  		retval |= NOUVEAU_DSM_HAS_OPT;  	if (retval & NOUVEAU_DSM_HAS_OPT) { @@ -317,6 +277,16 @@ static bool nouveau_dsm_detect(void)  			has_optimus = 1;  	} +	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_3D << 8, pdev)) != NULL) { +		vga_count++; + +		retval = nouveau_dsm_pci_probe(pdev); +		if (retval & NOUVEAU_DSM_HAS_MUX) +			has_dsm |= 1; +		if (retval & NOUVEAU_DSM_HAS_OPT) +			has_optimus = 1; +	} +  	/* find the optimus DSM or the old v1 DSM */  	if (has_optimus == 1) {  		acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, @@ -331,6 +301,16 @@ static bool nouveau_dsm_detect(void)  		printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",  			acpi_method_name);  		nouveau_dsm_priv.dsm_detected = true; +		/* +		 * On some systems hotplug events are generated for the device +		 * being switched off when _DSM is executed.  They cause ACPI +		 * hotplug to trigger and attempt to remove the device from +		 * the system, which causes it to break down.  Prevent that from +		 * happening by setting the no_hotplug flag for the involved +		 * ACPI device objects. +		 */ +		acpi_bus_no_hotplug(nouveau_dsm_priv.dhandle); +		acpi_bus_no_hotplug(nouveau_dsm_priv.other_handle);  		ret = true;  	} @@ -369,6 +349,11 @@ void nouveau_unregister_dsm_handler(void)  	if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)  		vga_switcheroo_unregister_handler();  } +#else +void nouveau_register_dsm_handler(void) {} +void nouveau_unregister_dsm_handler(void) {} +void nouveau_switcheroo_optimus_dsm(void) {} +#endif  /* retrieve the ROM in 4k blocks */  static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios, @@ -404,10 +389,7 @@ bool nouveau_acpi_rom_supported(struct pci_dev *pdev)  	acpi_status status;  	acpi_handle dhandle, rom_handle; -	if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected) -		return false; - -	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); +	dhandle = ACPI_HANDLE(&pdev->dev);  	if (!dhandle)  		return false; @@ -441,7 +423,7 @@ nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)  		return NULL;  	} -	handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); +	handle = ACPI_HANDLE(&dev->pdev->dev);  	if (!handle)  		return NULL; diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c index 6e7a55f93a8..51666daddb9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_agp.c +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c @@ -11,10 +11,28 @@ MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)");  static int nouveau_agpmode = -1;  module_param_named(agpmode, nouveau_agpmode, int, 0400); +struct nouveau_agpmode_quirk { +	u16 hostbridge_vendor; +	u16 hostbridge_device; +	u16 chip_vendor; +	u16 chip_device; +	int mode; +}; + +static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = { +	/* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo #20341 */ +	{ PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, + +	{}, +}; +  static unsigned long -get_agp_mode(struct nouveau_drm *drm, unsigned long mode) +get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info)  {  	struct nouveau_device *device = nv_device(drm->device); +	struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list; +	int agpmode = nouveau_agpmode; +	unsigned long mode = info->mode;  	/*  	 * FW seems to be broken on nv18, it makes the card lock up @@ -24,11 +42,27 @@ get_agp_mode(struct nouveau_drm *drm, unsigned long mode)  		mode &= ~PCI_AGP_COMMAND_FW;  	/* +	 * Go through the quirks list and adjust the agpmode accordingly. +	 */ +	while (agpmode == -1 && quirk->hostbridge_vendor) { +		if (info->id_vendor == quirk->hostbridge_vendor && +		    info->id_device == quirk->hostbridge_device && +		    device->pdev->vendor == quirk->chip_vendor && +		    device->pdev->device == quirk->chip_device) { +			agpmode = quirk->mode; +			nv_info(device, "Forcing agp mode to %dX. Use agpmode to override.\n", +				agpmode); +			break; +		} +		++quirk; +	} + +	/*  	 * AGP mode set in the command line.  	 */ -	if (nouveau_agpmode > 0) { +	if (agpmode > 0) {  		bool agpv3 = mode & 0x8; -		int rate = agpv3 ? nouveau_agpmode / 4 : nouveau_agpmode; +		int rate = agpv3 ? agpmode / 4 : agpmode;  		mode = (mode & ~0x7) | (rate & 0x7);  	} @@ -41,7 +75,7 @@ nouveau_agp_enabled(struct nouveau_drm *drm)  {  	struct drm_device *dev = drm->dev; -	if (!drm_pci_device_is_agp(dev) || !dev->agp) +	if (!dev->pdev || !drm_pci_device_is_agp(dev) || !dev->agp)  		return false;  	if (drm->agp.stat == UNKNOWN) { @@ -90,7 +124,7 @@ nouveau_agp_reset(struct nouveau_drm *drm)  		if (ret)  			return; -		mode.mode  = get_agp_mode(drm, info.mode); +		mode.mode  = get_agp_mode(drm, &info);  		mode.mode &= ~PCI_AGP_COMMAND_FW;  		ret = drm_agp_enable(dev, mode); @@ -139,7 +173,7 @@ nouveau_agp_init(struct nouveau_drm *drm)  	}  	/* see agp.h for the AGPSTAT_* modes available */ -	mode.mode = get_agp_mode(drm, info.mode); +	mode.mode = get_agp_mode(drm, &info);  	ret = drm_agp_enable(dev, mode);  	if (ret) { diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 2ffad2176b7..2c1e4aad7da 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -31,7 +31,6 @@   */  #include <linux/backlight.h> -#include <linux/acpi.h>  #include "nouveau_drm.h"  #include "nouveau_reg.h" @@ -82,7 +81,7 @@ nv40_backlight_init(struct drm_connector *connector)  	memset(&props, 0, sizeof(struct backlight_properties));  	props.type = BACKLIGHT_RAW;  	props.max_brightness = 31; -	bd = backlight_device_register("nv_backlight", &connector->kdev, drm, +	bd = backlight_device_register("nv_backlight", connector->kdev, drm,  				       &nv40_bl_ops, &props);  	if (IS_ERR(bd))  		return PTR_ERR(bd); @@ -204,7 +203,7 @@ nv50_backlight_init(struct drm_connector *connector)  	memset(&props, 0, sizeof(struct backlight_properties));  	props.type = BACKLIGHT_RAW;  	props.max_brightness = 100; -	bd = backlight_device_register("nv_backlight", &connector->kdev, +	bd = backlight_device_register("nv_backlight", connector->kdev,  				       nv_encoder, ops, &props);  	if (IS_ERR(bd))  		return PTR_ERR(bd); @@ -222,14 +221,6 @@ nouveau_backlight_init(struct drm_device *dev)  	struct nouveau_device *device = nv_device(drm->device);  	struct drm_connector *connector; -#ifdef CONFIG_ACPI -	if (acpi_video_backlight_support()) { -		NV_INFO(drm, "ACPI backlight interface available, " -			     "not registering our own\n"); -		return 0; -	} -#endif -  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {  		if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&  		    connector->connector_type != DRM_MODE_CONNECTOR_eDP) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 3e7287675ec..8268a4ccac1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -127,8 +127,8 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_outp  #ifdef __powerpc__  	/* Powerbook specific quirks */  	if (script == LVDS_RESET && -	    (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || -	     dev->pci_device == 0x0329)) +	    (dev->pdev->device == 0x0179 || dev->pdev->device == 0x0189 || +	     dev->pdev->device == 0x0329))  		nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);  #endif @@ -1474,9 +1474,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,  		case 0:  			entry->dpconf.link_bw = 162000;  			break; -		default: +		case 1:  			entry->dpconf.link_bw = 270000;  			break; +		default: +			entry->dpconf.link_bw = 540000; +			break;  		}  		switch ((conf & 0x0f000000) >> 24) {  		case 0xf: @@ -2069,6 +2072,10 @@ nouveau_bios_init(struct drm_device *dev)  	struct nvbios *bios = &drm->vbios;  	int ret; +	/* only relevant for PCI devices */ +	if (!dev->pdev) +		return 0; +  	if (!NVInitVBIOS(dev))  		return -ENODEV; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 755c38d0627..b6dc85c614b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -98,12 +98,7 @@ nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,  	if (tile) {  		spin_lock(&drm->tile.lock); -		if (fence) { -			/* Mark it as pending. */ -			tile->fence = fence; -			nouveau_fence_ref(fence); -		} - +		tile->fence = nouveau_fence_ref(fence);  		tile->used = false;  		spin_unlock(&drm->tile.lock);  	} @@ -146,7 +141,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)  	struct drm_device *dev = drm->dev;  	struct nouveau_bo *nvbo = nouveau_bo(bo); -	if (unlikely(nvbo->gem)) +	if (unlikely(nvbo->gem.filp))  		DRM_ERROR("bo %p still attached to GEM object\n", bo);  	WARN_ON(nvbo->pin_refcnt > 0);  	nv10_bo_put_tile_region(dev, nvbo->tile, NULL); @@ -269,7 +264,8 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)  	struct nouveau_fb *pfb = nouveau_fb(drm->device);  	u32 vram_pages = pfb->ram->size >> PAGE_SHIFT; -	if (nv_device(drm->device)->card_type == NV_10 && +	if ((nv_device(drm->device)->card_type == NV_10 || +	     nv_device(drm->device)->card_type == NV_11) &&  	    nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&  	    nvbo->bo.mem.num_pages < vram_pages / 4) {  		/* @@ -564,28 +560,6 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)  } -/* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access - * TTM_PL_{VRAM,TT} directly. - */ - -static int -nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, -			      struct nouveau_bo *nvbo, bool evict, -			      bool no_wait_gpu, struct ttm_mem_reg *new_mem) -{ -	struct nouveau_fence *fence = NULL; -	int ret; - -	ret = nouveau_fence_new(chan, false, &fence); -	if (ret) -		return ret; - -	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, evict, -					no_wait_gpu, new_mem); -	nouveau_fence_unref(&fence); -	return ret; -} -  static int  nve0_bo_move_init(struct nouveau_channel *chan, u32 handle)  { @@ -802,25 +776,25 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,  		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)  {  	struct nouveau_mem *node = old_mem->mm_node; -	struct nouveau_bo *nvbo = nouveau_bo(bo);  	u64 length = (new_mem->num_pages << PAGE_SHIFT);  	u64 src_offset = node->vma[0].offset;  	u64 dst_offset = node->vma[1].offset; +	int src_tiled = !!node->memtype; +	int dst_tiled = !!((struct nouveau_mem *)new_mem->mm_node)->memtype;  	int ret;  	while (length) {  		u32 amount, stride, height; +		ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled)); +		if (ret) +			return ret; +  		amount  = min(length, (u64)(4 * 1024 * 1024));  		stride  = 16 * 4;  		height  = amount / stride; -		if (old_mem->mem_type == TTM_PL_VRAM && -		    nouveau_bo_tile_layout(nvbo)) { -			ret = RING_SPACE(chan, 8); -			if (ret) -				return ret; - +		if (src_tiled) {  			BEGIN_NV04(chan, NvSubCopy, 0x0200, 7);  			OUT_RING  (chan, 0);  			OUT_RING  (chan, 0); @@ -830,19 +804,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,  			OUT_RING  (chan, 0);  			OUT_RING  (chan, 0);  		} else { -			ret = RING_SPACE(chan, 2); -			if (ret) -				return ret; -  			BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);  			OUT_RING  (chan, 1);  		} -		if (new_mem->mem_type == TTM_PL_VRAM && -		    nouveau_bo_tile_layout(nvbo)) { -			ret = RING_SPACE(chan, 8); -			if (ret) -				return ret; - +		if (dst_tiled) {  			BEGIN_NV04(chan, NvSubCopy, 0x021c, 7);  			OUT_RING  (chan, 0);  			OUT_RING  (chan, 0); @@ -852,18 +817,10 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,  			OUT_RING  (chan, 0);  			OUT_RING  (chan, 0);  		} else { -			ret = RING_SPACE(chan, 2); -			if (ret) -				return ret; -  			BEGIN_NV04(chan, NvSubCopy, 0x021c, 1);  			OUT_RING  (chan, 1);  		} -		ret = RING_SPACE(chan, 14); -		if (ret) -			return ret; -  		BEGIN_NV04(chan, NvSubCopy, 0x0238, 2);  		OUT_RING  (chan, upper_32_bits(src_offset));  		OUT_RING  (chan, upper_32_bits(dst_offset)); @@ -957,23 +914,28 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,  }  static int -nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo, -		   struct ttm_mem_reg *mem, struct nouveau_vma *vma) +nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo, +		     struct ttm_mem_reg *mem)  { -	struct nouveau_mem *node = mem->mm_node; +	struct nouveau_mem *old_node = bo->mem.mm_node; +	struct nouveau_mem *new_node = mem->mm_node; +	u64 size = (u64)mem->num_pages << PAGE_SHIFT;  	int ret; -	ret = nouveau_vm_get(nv_client(chan->cli)->vm, mem->num_pages << -			     PAGE_SHIFT, node->page_shift, -			     NV_MEM_ACCESS_RW, vma); +	ret = nouveau_vm_get(nv_client(drm)->vm, size, old_node->page_shift, +			     NV_MEM_ACCESS_RW, &old_node->vma[0]);  	if (ret)  		return ret; -	if (mem->mem_type == TTM_PL_VRAM) -		nouveau_vm_map(vma, node); -	else -		nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node); +	ret = nouveau_vm_get(nv_client(drm)->vm, size, new_node->page_shift, +			     NV_MEM_ACCESS_RW, &old_node->vma[1]); +	if (ret) { +		nouveau_vm_put(&old_node->vma[0]); +		return ret; +	} +	nouveau_vm_map(&old_node->vma[0], old_node); +	nouveau_vm_map(&old_node->vma[1], new_node);  	return 0;  } @@ -982,36 +944,35 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,  		     bool no_wait_gpu, struct ttm_mem_reg *new_mem)  {  	struct nouveau_drm *drm = nouveau_bdev(bo->bdev); -	struct nouveau_channel *chan = chan = drm->ttm.chan; -	struct nouveau_bo *nvbo = nouveau_bo(bo); -	struct ttm_mem_reg *old_mem = &bo->mem; +	struct nouveau_channel *chan = drm->ttm.chan; +	struct nouveau_fence *fence;  	int ret; -	mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING); -  	/* create temporary vmas for the transfer and attach them to the  	 * old nouveau_mem node, these will get cleaned up after ttm has  	 * destroyed the ttm_mem_reg  	 */  	if (nv_device(drm->device)->card_type >= NV_50) { -		struct nouveau_mem *node = old_mem->mm_node; - -		ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]); -		if (ret) -			goto out; - -		ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]); +		ret = nouveau_bo_move_prep(drm, bo, new_mem);  		if (ret) -			goto out; +			return ret;  	} -	ret = drm->ttm.move(chan, bo, &bo->mem, new_mem); +	mutex_lock_nested(&chan->cli->mutex, SINGLE_DEPTH_NESTING); +	ret = nouveau_fence_sync(bo->sync_obj, chan);  	if (ret == 0) { -		ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict, -						    no_wait_gpu, new_mem); +		ret = drm->ttm.move(chan, bo, &bo->mem, new_mem); +		if (ret == 0) { +			ret = nouveau_fence_new(chan, false, &fence); +			if (ret == 0) { +				ret = ttm_bo_move_accel_cleanup(bo, fence, +								evict, +								no_wait_gpu, +								new_mem); +				nouveau_fence_unref(&fence); +			} +		}  	} - -out:  	mutex_unlock(&chan->cli->mutex);  	return ret;  } @@ -1151,19 +1112,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)  		return;  	list_for_each_entry(vma, &nvbo->vma_list, head) { -		if (new_mem && new_mem->mem_type == TTM_PL_VRAM) { +		if (new_mem && new_mem->mem_type != TTM_PL_SYSTEM && +			      (new_mem->mem_type == TTM_PL_VRAM || +			       nvbo->page_shift != vma->vm->vmm->lpg_shift)) {  			nouveau_vm_map(vma, new_mem->mm_node); -		} else -		if (new_mem && new_mem->mem_type == TTM_PL_TT && -		    nvbo->page_shift == vma->vm->vmm->spg_shift) { -			if (((struct nouveau_mem *)new_mem->mm_node)->sg) -				nouveau_vm_map_sg_table(vma, 0, new_mem-> -						  num_pages << PAGE_SHIFT, -						  new_mem->mm_node); -			else -				nouveau_vm_map_sg(vma, 0, new_mem-> -						  num_pages << PAGE_SHIFT, -						  new_mem->mm_node);  		} else {  			nouveau_vm_unmap(vma);  		} @@ -1228,28 +1180,27 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,  		goto out;  	} -	/* CPU copy if we have no accelerated method available */ -	if (!drm->ttm.move) { -		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem); -		goto out; -	} -  	/* Hardware assisted copy. */ -	if (new_mem->mem_type == TTM_PL_SYSTEM) -		ret = nouveau_bo_move_flipd(bo, evict, intr, -					    no_wait_gpu, new_mem); -	else if (old_mem->mem_type == TTM_PL_SYSTEM) -		ret = nouveau_bo_move_flips(bo, evict, intr, -					    no_wait_gpu, new_mem); -	else -		ret = nouveau_bo_move_m2mf(bo, evict, intr, -					   no_wait_gpu, new_mem); - -	if (!ret) -		goto out; +	if (drm->ttm.move) { +		if (new_mem->mem_type == TTM_PL_SYSTEM) +			ret = nouveau_bo_move_flipd(bo, evict, intr, +						    no_wait_gpu, new_mem); +		else if (old_mem->mem_type == TTM_PL_SYSTEM) +			ret = nouveau_bo_move_flips(bo, evict, intr, +						    no_wait_gpu, new_mem); +		else +			ret = nouveau_bo_move_m2mf(bo, evict, intr, +						   no_wait_gpu, new_mem); +		if (!ret) +			goto out; +	}  	/* Fallback to software copy. */ -	ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem); +	spin_lock(&bo->bdev->fence_lock); +	ret = ttm_bo_wait(bo, true, intr, no_wait_gpu); +	spin_unlock(&bo->bdev->fence_lock); +	if (ret == 0) +		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);  out:  	if (nv_device(drm->device)->card_type < NV_50) { @@ -1267,7 +1218,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)  {  	struct nouveau_bo *nvbo = nouveau_bo(bo); -	return drm_vma_node_verify_access(&nvbo->gem->vma_node, filp); +	return drm_vma_node_verify_access(&nvbo->gem.vma_node, filp);  }  static int @@ -1275,6 +1226,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)  {  	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];  	struct nouveau_drm *drm = nouveau_bdev(bdev); +	struct nouveau_mem *node = mem->mm_node;  	struct drm_device *dev = drm->dev;  	int ret; @@ -1297,14 +1249,16 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)  			mem->bus.is_iomem = !dev->agp->cant_use_aperture;  		}  #endif -		break; +		if (nv_device(drm->device)->card_type < NV_50 || !node->memtype) +			/* untiled */ +			break; +		/* fallthrough, tiled memory */  	case TTM_PL_VRAM:  		mem->bus.offset = mem->start << PAGE_SHIFT; -		mem->bus.base = pci_resource_start(dev->pdev, 1); +		mem->bus.base = nv_device_resource_start(nouveau_dev(dev), 1);  		mem->bus.is_iomem = true;  		if (nv_device(drm->device)->card_type >= NV_50) {  			struct nouveau_bar *bar = nouveau_bar(drm->device); -			struct nouveau_mem *node = mem->mm_node;  			ret = bar->umap(bar, node, NV_MEM_ACCESS_RW,  					&node->bar_vma); @@ -1339,7 +1293,8 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)  	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);  	struct nouveau_bo *nvbo = nouveau_bo(bo);  	struct nouveau_device *device = nv_device(drm->device); -	u32 mappable = pci_resource_len(device->pdev, 1) >> PAGE_SHIFT; +	u32 mappable = nv_device_resource_len(device, 1) >> PAGE_SHIFT; +	int ret;  	/* as long as the bo isn't in vram, and isn't tiled, we've got  	 * nothing to do here. @@ -1348,10 +1303,20 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)  		if (nv_device(drm->device)->card_type < NV_50 ||  		    !nouveau_bo_tile_layout(nvbo))  			return 0; + +		if (bo->mem.mem_type == TTM_PL_SYSTEM) { +			nouveau_bo_placement_set(nvbo, TTM_PL_TT, 0); + +			ret = nouveau_bo_validate(nvbo, false, false); +			if (ret) +				return ret; +		} +		return 0;  	}  	/* make sure bo is in mappable vram */ -	if (bo->mem.start + bo->mem.num_pages < mappable) +	if (nv_device(drm->device)->card_type >= NV_50 || +	    bo->mem.start + bo->mem.num_pages < mappable)  		return 0; @@ -1366,6 +1331,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)  {  	struct ttm_dma_tt *ttm_dma = (void *)ttm;  	struct nouveau_drm *drm; +	struct nouveau_device *device;  	struct drm_device *dev;  	unsigned i;  	int r; @@ -1383,6 +1349,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)  	}  	drm = nouveau_bdev(ttm->bdev); +	device = nv_device(drm->device);  	dev = drm->dev;  #if __OS_HAS_AGP @@ -1403,13 +1370,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)  	}  	for (i = 0; i < ttm->num_pages; i++) { -		ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], -						   0, PAGE_SIZE, -						   PCI_DMA_BIDIRECTIONAL); -		if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) { +		ttm_dma->dma_address[i] = nv_device_map_page(device, +							     ttm->pages[i]); +		if (!ttm_dma->dma_address[i]) {  			while (--i) { -				pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], -					       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +				nv_device_unmap_page(device, +						     ttm_dma->dma_address[i]);  				ttm_dma->dma_address[i] = 0;  			}  			ttm_pool_unpopulate(ttm); @@ -1424,6 +1390,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)  {  	struct ttm_dma_tt *ttm_dma = (void *)ttm;  	struct nouveau_drm *drm; +	struct nouveau_device *device;  	struct drm_device *dev;  	unsigned i;  	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -1432,6 +1399,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)  		return;  	drm = nouveau_bdev(ttm->bdev); +	device = nv_device(drm->device);  	dev = drm->dev;  #if __OS_HAS_AGP @@ -1450,8 +1418,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)  	for (i = 0; i < ttm->num_pages; i++) {  		if (ttm_dma->dma_address[i]) { -			pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], -				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); +			nv_device_unmap_page(device, ttm_dma->dma_address[i]);  		}  	} @@ -1461,14 +1428,12 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)  void  nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence)  { +	struct nouveau_fence *new_fence = nouveau_fence_ref(fence);  	struct nouveau_fence *old_fence = NULL; -	if (likely(fence)) -		nouveau_fence_ref(fence); -  	spin_lock(&nvbo->bo.bdev->fence_lock);  	old_fence = nvbo->bo.sync_obj; -	nvbo->bo.sync_obj = fence; +	nvbo->bo.sync_obj = new_fence;  	spin_unlock(&nvbo->bo.bdev->fence_lock);  	nouveau_fence_unref(&old_fence); @@ -1541,7 +1506,6 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,  		   struct nouveau_vma *vma)  {  	const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT; -	struct nouveau_mem *node = nvbo->bo.mem.mm_node;  	int ret;  	ret = nouveau_vm_get(vm, size, nvbo->page_shift, @@ -1549,14 +1513,10 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,  	if (ret)  		return ret; -	if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) +	if ( nvbo->bo.mem.mem_type != TTM_PL_SYSTEM && +	    (nvbo->bo.mem.mem_type == TTM_PL_VRAM || +	     nvbo->page_shift != vma->vm->vmm->lpg_shift))  		nouveau_vm_map(vma, nvbo->bo.mem.mm_node); -	else if (nvbo->bo.mem.mem_type == TTM_PL_TT) { -		if (node->sg) -			nouveau_vm_map_sg_table(vma, 0, size, node); -		else -			nouveau_vm_map_sg(vma, 0, size, node); -	}  	list_add_tail(&vma->head, &nvbo->vma_list);  	vma->refcount = 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index 653dbbbd4fa..ff17c1f432f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -27,7 +27,10 @@ struct nouveau_bo {  	u32 tile_flags;  	struct nouveau_drm_tile *tile; -	struct drm_gem_object *gem; +	/* Only valid if allocated via nouveau_gem_new() and iff you hold a +	 * gem reference to it! For debugging, use gem.filp != NULL to test +	 * whether it is valid. */ +	struct drm_gem_object gem;  	/* protect by the ttm reservation lock */  	int pin_refcnt; diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index e84f4c32331..ccb6b452d6d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -154,7 +154,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli,  			 * nfi why this exists, it came from the -nv ddx.  			 */  			args.flags = NV_DMA_TARGET_PCI | NV_DMA_ACCESS_RDWR; -			args.start = pci_resource_start(device->pdev, 1); +			args.start = nv_device_resource_start(device, 1);  			args.limit = args.start + limit;  		} else {  			args.flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR; @@ -346,22 +346,17 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)  	for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)  		OUT_RING(chan, 0x00000000); -	/* allocate software object class (used for fences on <= nv05, and -	 * to signal flip completion), bind it to a subchannel. -	 */ -	if ((device->card_type < NV_E0) || gart /* nve0: want_nvsw */) { +	/* allocate software object class (used for fences on <= nv05) */ +	if (device->card_type < NV_10) {  		ret = nouveau_object_new(nv_object(client), chan->handle, -					 NvSw, nouveau_abi16_swclass(chan->drm), -					 NULL, 0, &object); +					 NvSw, 0x006e, NULL, 0, &object);  		if (ret)  			return ret;  		swch = (void *)object->parent;  		swch->flip = nouveau_flip_complete;  		swch->flip_data = chan; -	} -	if (device->card_type < NV_C0) {  		ret = RING_SPACE(chan, 2);  		if (ret)  			return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index c5b36f9e9a1..1fa222e8f00 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -44,6 +44,7 @@  #include <subdev/i2c.h>  #include <subdev/gpio.h> +#include <engine/disp.h>  MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");  static int nouveau_tv_disable = 0; @@ -75,7 +76,8 @@ find_encoder(struct drm_connector *connector, int type)  			continue;  		nv_encoder = nouveau_encoder(obj_to_encoder(obj)); -		if (type == DCB_OUTPUT_ANY || nv_encoder->dcb->type == type) +		if (type == DCB_OUTPUT_ANY || +		    (nv_encoder->dcb && nv_encoder->dcb->type == type))  			return nv_encoder;  	} @@ -100,21 +102,24 @@ static void  nouveau_connector_destroy(struct drm_connector *connector)  {  	struct nouveau_connector *nv_connector = nouveau_connector(connector); +	nouveau_event_ref(NULL, &nv_connector->hpd);  	kfree(nv_connector->edid);  	drm_sysfs_connector_remove(connector);  	drm_connector_cleanup(connector); +	if (nv_connector->aux.transfer) +		drm_dp_aux_unregister(&nv_connector->aux);  	kfree(connector);  } -static struct nouveau_i2c_port * -nouveau_connector_ddc_detect(struct drm_connector *connector, -			     struct nouveau_encoder **pnv_encoder) +static struct nouveau_encoder * +nouveau_connector_ddc_detect(struct drm_connector *connector)  {  	struct drm_device *dev = connector->dev;  	struct nouveau_connector *nv_connector = nouveau_connector(connector);  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); -	struct nouveau_i2c_port *port = NULL; +	struct nouveau_encoder *nv_encoder; +	struct drm_mode_object *obj;  	int i, panel = -ENODEV;  	/* eDP panels need powering on by us (if the VBIOS doesn't default it @@ -129,13 +134,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,  		}  	} -	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { -		struct nouveau_encoder *nv_encoder; -		struct drm_mode_object *obj; -		int id; - -		id = connector->encoder_ids[i]; -		if (!id) +	for (i = 0; nv_encoder = NULL, i < DRM_CONNECTOR_MAX_ENCODER; i++) { +		int id = connector->encoder_ids[i]; +		if (id == 0)  			break;  		obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); @@ -143,22 +144,24 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,  			continue;  		nv_encoder = nouveau_encoder(obj_to_encoder(obj)); -		port = nv_encoder->i2c; -		if (port && nv_probe_i2c(port, 0x50)) { -			*pnv_encoder = nv_encoder; -			break; +		if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { +			int ret = nouveau_dp_detect(nv_encoder); +			if (ret == 0) +				break; +		} else +		if (nv_encoder->i2c) { +			if (nv_probe_i2c(nv_encoder->i2c, 0x50)) +				break;  		} - -		port = NULL;  	}  	/* eDP panel not detected, restore panel power GPIO to previous  	 * state to avoid confusing the SOR for other output types.  	 */ -	if (!port && panel == 0) +	if (!nv_encoder && panel == 0)  		gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); -	return port; +	return nv_encoder;  }  static struct nouveau_encoder * @@ -214,9 +217,10 @@ nouveau_connector_set_encoder(struct drm_connector *connector,  	} else {  		connector->doublescan_allowed = true;  		if (nv_device(drm->device)->card_type == NV_20 || -		   (nv_device(drm->device)->card_type == NV_10 && -		    (dev->pci_device & 0x0ff0) != 0x0100 && -		    (dev->pci_device & 0x0ff0) != 0x0150)) +		    ((nv_device(drm->device)->card_type == NV_10 || +		      nv_device(drm->device)->card_type == NV_11) && +		     (dev->pdev->device & 0x0ff0) != 0x0100 && +		     (dev->pdev->device & 0x0ff0) != 0x0150))  			/* HW is broken */  			connector->interlace_allowed = false;  		else @@ -253,28 +257,20 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)  	}  	ret = pm_runtime_get_sync(connector->dev->dev); -	if (ret < 0) +	if (ret < 0 && ret != -EACCES)  		return conn_status; -	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); -	if (i2c) { +	nv_encoder = nouveau_connector_ddc_detect(connector); +	if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {  		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);  		drm_mode_connector_update_edid_property(connector,  							nv_connector->edid);  		if (!nv_connector->edid) {  			NV_ERROR(drm, "DDC responded, but no EDID for %s\n", -				 drm_get_connector_name(connector)); +				 connector->name);  			goto detect_analog;  		} -		if (nv_encoder->dcb->type == DCB_OUTPUT_DP && -		    !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { -			NV_ERROR(drm, "Detected %s, but failed init\n", -				 drm_get_connector_name(connector)); -			conn_status = connector_status_disconnected; -			goto out; -		} -  		/* Override encoder type for DVI-I based on whether EDID  		 * says the display is digital or analog, both use the  		 * same i2c channel so the value returned from ddc_detect @@ -435,7 +431,7 @@ nouveau_connector_force(struct drm_connector *connector)  	nv_encoder = find_encoder(connector, type);  	if (!nv_encoder) {  		NV_ERROR(drm, "can't find encoder to force %s on!\n", -			 drm_get_connector_name(connector)); +			 connector->name);  		connector->status = connector_status_disconnected;  		return;  	} @@ -910,34 +906,103 @@ nouveau_connector_funcs_lvds = {  };  static void +nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) +{ +	struct nouveau_encoder *nv_encoder = NULL; + +	if (connector->encoder) +		nv_encoder = nouveau_encoder(connector->encoder); +	if (nv_encoder && nv_encoder->dcb && +	    nv_encoder->dcb->type == DCB_OUTPUT_DP) { +		if (mode == DRM_MODE_DPMS_ON) { +			u8 data = DP_SET_POWER_D0; +			nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1); +			usleep_range(1000, 2000); +		} else { +			u8 data = DP_SET_POWER_D3; +			nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1); +		} +	} + +	drm_helper_connector_dpms(connector, mode); +} + +static const struct drm_connector_funcs +nouveau_connector_funcs_dp = { +	.dpms = nouveau_connector_dp_dpms, +	.save = NULL, +	.restore = NULL, +	.detect = nouveau_connector_detect, +	.destroy = nouveau_connector_destroy, +	.fill_modes = drm_helper_probe_single_connector_modes, +	.set_property = nouveau_connector_set_property, +	.force = nouveau_connector_force +}; + +static void  nouveau_connector_hotplug_work(struct work_struct *work)  {  	struct nouveau_connector *nv_connector = -		container_of(work, struct nouveau_connector, hpd_work); +		container_of(work, typeof(*nv_connector), work);  	struct drm_connector *connector = &nv_connector->base; -	struct drm_device *dev = connector->dev; -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); -	bool plugged = gpio->get(gpio, 0, nv_connector->hpd.func, 0xff); +	struct nouveau_drm *drm = nouveau_drm(connector->dev); +	const char *name = connector->name; -	NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", -		 drm_get_connector_name(connector)); +	if (nv_connector->status & NVKM_HPD_IRQ) { +	} else { +		bool plugged = (nv_connector->status != NVKM_HPD_UNPLUG); -	if (plugged) -		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); -	else -		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); +		NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); + +		if (plugged) +			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); +		else +			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); +		drm_helper_hpd_irq_event(connector->dev); +	} -	drm_helper_hpd_irq_event(dev); +	nouveau_event_get(nv_connector->hpd);  }  static int -nouveau_connector_hotplug(struct nouveau_eventh *event, int index) +nouveau_connector_hotplug(void *data, u32 type, int index) +{ +	struct nouveau_connector *nv_connector = data; +	nv_connector->status = type; +	schedule_work(&nv_connector->work); +	return NVKM_EVENT_DROP; +} + +static ssize_t +nouveau_connector_aux_xfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)  {  	struct nouveau_connector *nv_connector = -		container_of(event, struct nouveau_connector, hpd_func); -	schedule_work(&nv_connector->hpd_work); -	return NVKM_EVENT_KEEP; +		container_of(aux, typeof(*nv_connector), aux); +	struct nouveau_encoder *nv_encoder; +	struct nouveau_i2c_port *port; +	int ret; + +	nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); +	if (!nv_encoder || !(port = nv_encoder->i2c)) +		return -ENODEV; +	if (WARN_ON(msg->size > 16)) +		return -E2BIG; +	if (msg->size == 0) +		return msg->size; + +	ret = nouveau_i2c(port)->acquire(port, 0); +	if (ret) +		return ret; + +	ret = port->func->aux(port, false, msg->request, msg->address, +			      msg->buffer, msg->size); +	nouveau_i2c(port)->release(port); +	if (ret >= 0) { +		msg->reply = ret; +		return msg->size; +	} + +	return ret;  }  static int @@ -959,7 +1024,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)  	case DCB_CONNECTOR_DP       : return DRM_MODE_CONNECTOR_DisplayPort;  	case DCB_CONNECTOR_eDP      : return DRM_MODE_CONNECTOR_eDP;  	case DCB_CONNECTOR_HDMI_0   : -	case DCB_CONNECTOR_HDMI_1   : return DRM_MODE_CONNECTOR_HDMIA; +	case DCB_CONNECTOR_HDMI_1   : +	case DCB_CONNECTOR_HDMI_C   : return DRM_MODE_CONNECTOR_HDMIA;  	default:  		break;  	} @@ -972,9 +1038,9 @@ nouveau_connector_create(struct drm_device *dev, int index)  {  	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;  	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);  	struct nouveau_display *disp = nouveau_display(dev);  	struct nouveau_connector *nv_connector = NULL; +	struct nouveau_disp *pdisp = nouveau_disp(drm->device);  	struct drm_connector *connector;  	int type, ret = 0;  	bool dummy; @@ -990,27 +1056,15 @@ nouveau_connector_create(struct drm_device *dev, int index)  		return ERR_PTR(-ENOMEM);  	connector = &nv_connector->base; -	INIT_WORK(&nv_connector->hpd_work, nouveau_connector_hotplug_work);  	nv_connector->index = index;  	/* attempt to parse vbios connector type and hotplug gpio */  	nv_connector->dcb = olddcb_conn(dev, index);  	if (nv_connector->dcb) { -		static const u8 hpd[16] = { -			0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, -			0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, -		}; -  		u32 entry = ROM16(nv_connector->dcb[0]);  		if (olddcb_conntab(dev)[3] >= 4)  			entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; -		ret = gpio->find(gpio, 0, hpd[ffs((entry & 0x07033000) >> 12)], -				 DCB_GPIO_UNUSED, &nv_connector->hpd); -		nv_connector->hpd_func.func = nouveau_connector_hotplug; -		if (ret) -			nv_connector->hpd.func = DCB_GPIO_UNUSED; -  		nv_connector->type = nv_connector->dcb[0];  		if (drm_conntype_from_dcb(nv_connector->type) ==  					  DRM_MODE_CONNECTOR_Unknown) { @@ -1032,7 +1086,6 @@ nouveau_connector_create(struct drm_device *dev, int index)  		}  	} else {  		nv_connector->type = DCB_CONNECTOR_NONE; -		nv_connector->hpd.func = DCB_GPIO_UNUSED;  	}  	/* no vbios data, or an unknown dcb connector type - attempt to @@ -1072,8 +1125,8 @@ nouveau_connector_create(struct drm_device *dev, int index)  		}  	} -	type = drm_conntype_from_dcb(nv_connector->type); -	if (type == DRM_MODE_CONNECTOR_LVDS) { +	switch ((type = drm_conntype_from_dcb(nv_connector->type))) { +	case DRM_MODE_CONNECTOR_LVDS:  		ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy);  		if (ret) {  			NV_ERROR(drm, "Error parsing LVDS table, disabling\n"); @@ -1082,8 +1135,23 @@ nouveau_connector_create(struct drm_device *dev, int index)  		}  		funcs = &nouveau_connector_funcs_lvds; -	} else { +		break; +	case DRM_MODE_CONNECTOR_DisplayPort: +	case DRM_MODE_CONNECTOR_eDP: +		nv_connector->aux.dev = dev->dev; +		nv_connector->aux.transfer = nouveau_connector_aux_xfer; +		ret = drm_dp_aux_register(&nv_connector->aux); +		if (ret) { +			NV_ERROR(drm, "failed to register aux channel\n"); +			kfree(nv_connector); +			return ERR_PTR(ret); +		} + +		funcs = &nouveau_connector_funcs_dp; +		break; +	default:  		funcs = &nouveau_connector_funcs; +		break;  	}  	/* defaults, will get overridden in detect() */ @@ -1158,10 +1226,16 @@ nouveau_connector_create(struct drm_device *dev, int index)  		break;  	} -	connector->polled = DRM_CONNECTOR_POLL_CONNECT; -	if (nv_connector->hpd.func != DCB_GPIO_UNUSED) +	ret = nouveau_event_new(pdisp->hpd, NVKM_HPD, index, +				nouveau_connector_hotplug, +				nv_connector, &nv_connector->hpd); +	if (ret) +		connector->polled = DRM_CONNECTOR_POLL_CONNECT; +	else  		connector->polled = DRM_CONNECTOR_POLL_HPD; +	INIT_WORK(&nv_connector->work, nouveau_connector_hotplug_work); +  	drm_sysfs_connector_add(connector);  	return connector;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index 6e399aad491..8861b6c579a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -28,12 +28,12 @@  #define __NOUVEAU_CONNECTOR_H__  #include <drm/drm_edid.h> +#include <drm/drm_dp_helper.h>  #include "nouveau_crtc.h"  #include <core/event.h>  #include <subdev/bios.h> -#include <subdev/bios/gpio.h>  struct nouveau_i2c_port; @@ -67,9 +67,11 @@ struct nouveau_connector {  	u8 index;  	u8 *dcb; -	struct dcb_gpio_func hpd; -	struct work_struct hpd_work; -	struct nouveau_eventh hpd_func; +	struct nouveau_eventh *hpd; +	u32 status; +	struct work_struct work; + +	struct drm_dp_aux aux;  	int dithering_mode;  	int dithering_depth; @@ -107,7 +109,4 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)  struct drm_connector *  nouveau_connector_create(struct drm_device *, int index); -int -nouveau_connector_bpp(struct drm_connector *); -  #endif /* __NOUVEAU_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index d1e5890784d..a0534489d23 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -74,7 +74,7 @@ struct nouveau_crtc {  static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc)  { -	return container_of(crtc, struct nouveau_crtc, base); +	return crtc ? container_of(crtc, struct nouveau_crtc, base) : NULL;  }  static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d2712e6e5d3..47ad74255bf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -26,7 +26,6 @@  #include <drm/drmP.h>  #include <drm/drm_crtc_helper.h> -#include <drm/ttm/ttm_execbuf_util.h>  #include "nouveau_fbcon.h"  #include "dispnv04/hw.h" @@ -38,19 +37,172 @@  #include "nouveau_fence.h" -#include <subdev/bios/gpio.h> -#include <subdev/gpio.h>  #include <engine/disp.h>  #include <core/class.h> +static int +nouveau_display_vblank_handler(void *data, u32 type, int head) +{ +	struct nouveau_drm *drm = data; +	drm_handle_vblank(drm->dev, head); +	return NVKM_EVENT_KEEP; +} + +int +nouveau_display_vblank_enable(struct drm_device *dev, int head) +{ +	struct nouveau_display *disp = nouveau_display(dev); +	if (disp) { +		nouveau_event_get(disp->vblank[head]); +		return 0; +	} +	return -EIO; +} + +void +nouveau_display_vblank_disable(struct drm_device *dev, int head) +{ +	struct nouveau_display *disp = nouveau_display(dev); +	if (disp) +		nouveau_event_put(disp->vblank[head]); +} + +static inline int +calc(int blanks, int blanke, int total, int line) +{ +	if (blanke >= blanks) { +		if (line >= blanks) +			line -= total; +	} else { +		if (line >= blanks) +			line -= total; +		line -= blanke + 1; +	} +	return line; +} + +int +nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, +				ktime_t *stime, ktime_t *etime) +{ +	const u32 mthd = NV04_DISP_SCANOUTPOS + nouveau_crtc(crtc)->index; +	struct nouveau_display *disp = nouveau_display(crtc->dev); +	struct nv04_display_scanoutpos args; +	int ret, retry = 1; + +	do { +		ret = nv_exec(disp->core, mthd, &args, sizeof(args)); +		if (ret != 0) +			return 0; + +		if (args.vline) { +			ret |= DRM_SCANOUTPOS_ACCURATE; +			ret |= DRM_SCANOUTPOS_VALID; +			break; +		} + +		if (retry) ndelay(crtc->linedur_ns); +	} while (retry--); + +	*hpos = args.hline; +	*vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline); +	if (stime) *stime = ns_to_ktime(args.time[0]); +	if (etime) *etime = ns_to_ktime(args.time[1]); + +	if (*vpos < 0) +		ret |= DRM_SCANOUTPOS_INVBL; +	return ret; +} + +int +nouveau_display_scanoutpos(struct drm_device *dev, int head, unsigned int flags, +			   int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) +{ +	struct drm_crtc *crtc; + +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +		if (nouveau_crtc(crtc)->index == head) { +			return nouveau_display_scanoutpos_head(crtc, vpos, hpos, +							       stime, etime); +		} +	} + +	return 0; +} + +int +nouveau_display_vblstamp(struct drm_device *dev, int head, int *max_error, +			 struct timeval *time, unsigned flags) +{ +	struct drm_crtc *crtc; + +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +		if (nouveau_crtc(crtc)->index == head) { +			return drm_calc_vbltimestamp_from_scanoutpos(dev, +					head, max_error, time, flags, crtc, +					&crtc->hwmode); +		} +	} + +	return -EINVAL; +} + +static void +nouveau_display_vblank_fini(struct drm_device *dev) +{ +	struct nouveau_display *disp = nouveau_display(dev); +	int i; + +	drm_vblank_cleanup(dev); + +	if (disp->vblank) { +		for (i = 0; i < dev->mode_config.num_crtc; i++) +			nouveau_event_ref(NULL, &disp->vblank[i]); +		kfree(disp->vblank); +		disp->vblank = NULL; +	} +} + +static int +nouveau_display_vblank_init(struct drm_device *dev) +{ +	struct nouveau_display *disp = nouveau_display(dev); +	struct nouveau_drm *drm = nouveau_drm(dev); +	struct nouveau_disp *pdisp = nouveau_disp(drm->device); +	int ret, i; + +	disp->vblank = kzalloc(dev->mode_config.num_crtc * +			       sizeof(*disp->vblank), GFP_KERNEL); +	if (!disp->vblank) +		return -ENOMEM; + +	for (i = 0; i < dev->mode_config.num_crtc; i++) { +		ret = nouveau_event_new(pdisp->vblank, 1, i, +					nouveau_display_vblank_handler, +					drm, &disp->vblank[i]); +		if (ret) { +			nouveau_display_vblank_fini(dev); +			return ret; +		} +	} + +	ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +	if (ret) { +		nouveau_display_vblank_fini(dev); +		return ret; +	} + +	return 0; +} +  static void  nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)  {  	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);  	if (fb->nvbo) -		drm_gem_object_unreference_unlocked(fb->nvbo->gem); +		drm_gem_object_unreference_unlocked(&fb->nvbo->gem);  	drm_framebuffer_cleanup(drm_fb);  	kfree(fb); @@ -63,7 +215,7 @@ nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb,  {  	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); -	return drm_gem_handle_create(file_priv, fb->nvbo->gem, handle); +	return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle);  }  static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { @@ -227,9 +379,7 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {  int  nouveau_display_init(struct drm_device *dev)  { -	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_display *disp = nouveau_display(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);  	struct drm_connector *connector;  	int ret; @@ -243,10 +393,7 @@ nouveau_display_init(struct drm_device *dev)  	/* enable hotplug interrupts */  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {  		struct nouveau_connector *conn = nouveau_connector(connector); -		if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) { -			nouveau_event_get(gpio->events, conn->hpd.line, -					 &conn->hpd_func); -		} +		if (conn->hpd) nouveau_event_get(conn->hpd);  	}  	return ret; @@ -255,18 +402,13 @@ nouveau_display_init(struct drm_device *dev)  void  nouveau_display_fini(struct drm_device *dev)  { -	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_display *disp = nouveau_display(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);  	struct drm_connector *connector;  	/* disable hotplug interrupts */  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {  		struct nouveau_connector *conn = nouveau_connector(connector); -		if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) { -			nouveau_event_put(gpio->events, conn->hpd.line, -					 &conn->hpd_func); -		} +		if (conn->hpd) nouveau_event_put(conn->hpd);  	}  	drm_kms_helper_poll_disable(dev); @@ -277,8 +419,8 @@ int  nouveau_display_create(struct drm_device *dev)  {  	struct nouveau_drm *drm = nouveau_drm(dev); +	struct nouveau_device *device = nouveau_dev(dev);  	struct nouveau_display *disp; -	u32 pclass = dev->pdev->class >> 8;  	int ret, gen;  	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -318,7 +460,7 @@ nouveau_display_create(struct drm_device *dev)  	}  	dev->mode_config.funcs = &nouveau_mode_config_funcs; -	dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); +	dev->mode_config.fb_base = nv_device_resource_start(device, 1);  	dev->mode_config.min_width = 0;  	dev->mode_config.min_height = 0; @@ -337,32 +479,55 @@ nouveau_display_create(struct drm_device *dev)  	dev->mode_config.preferred_depth = 24;  	dev->mode_config.prefer_shadow = 1; +	if (nv_device(drm->device)->chipset < 0x11) +		dev->mode_config.async_page_flip = false; +	else +		dev->mode_config.async_page_flip = true; +  	drm_kms_helper_poll_init(dev);  	drm_kms_helper_poll_disable(dev); -	if (nouveau_modeset == 1 || -	    (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { -		if (drm->vbios.dcb.entries) { -			if (nv_device(drm->device)->card_type < NV_50) +	if (drm->vbios.dcb.entries) { +		static const u16 oclass[] = { +			GM107_DISP_CLASS, +			NVF0_DISP_CLASS, +			NVE0_DISP_CLASS, +			NVD0_DISP_CLASS, +			NVA3_DISP_CLASS, +			NV94_DISP_CLASS, +			NVA0_DISP_CLASS, +			NV84_DISP_CLASS, +			NV50_DISP_CLASS, +			NV04_DISP_CLASS, +		}; +		int i; + +		for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) { +			ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, +						 NVDRM_DISPLAY, oclass[i], +						 NULL, 0, &disp->core); +		} + +		if (ret == 0) { +			if (nv_mclass(disp->core) < NV50_DISP_CLASS)  				ret = nv04_display_create(dev);  			else  				ret = nv50_display_create(dev); -		} else { -			ret = 0;  		} +	} else { +		ret = 0; +	} -		if (ret) -			goto disp_create_err; - -		if (dev->mode_config.num_crtc) { -			ret = drm_vblank_init(dev, dev->mode_config.num_crtc); -			if (ret) -				goto vblank_err; -		} +	if (ret) +		goto disp_create_err; -		nouveau_backlight_init(dev); +	if (dev->mode_config.num_crtc) { +		ret = nouveau_display_vblank_init(dev); +		if (ret) +			goto vblank_err;  	} +	nouveau_backlight_init(dev);  	return 0;  vblank_err: @@ -377,9 +542,10 @@ void  nouveau_display_destroy(struct drm_device *dev)  {  	struct nouveau_display *disp = nouveau_display(dev); +	struct nouveau_drm *drm = nouveau_drm(dev);  	nouveau_backlight_exit(dev); -	drm_vblank_cleanup(dev); +	nouveau_display_vblank_fini(dev);  	drm_kms_helper_poll_fini(dev);  	drm_mode_config_cleanup(dev); @@ -387,6 +553,8 @@ nouveau_display_destroy(struct drm_device *dev)  	if (disp->dtor)  		disp->dtor(dev); +	nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_DISPLAY); +  	nouveau_drm(dev)->display = NULL;  	kfree(disp);  } @@ -399,11 +567,11 @@ nouveau_display_suspend(struct drm_device *dev)  	nouveau_display_fini(dev); -	NV_SUSPEND(drm, "unpinning framebuffer(s)...\n"); +	NV_INFO(drm, "unpinning framebuffer(s)...\n");  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  		struct nouveau_framebuffer *nouveau_fb; -		nouveau_fb = nouveau_framebuffer(crtc->fb); +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);  		if (!nouveau_fb || !nouveau_fb->nvbo)  			continue; @@ -430,7 +598,7 @@ nouveau_display_repin(struct drm_device *dev)  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  		struct nouveau_framebuffer *nouveau_fb; -		nouveau_fb = nouveau_framebuffer(crtc->fb); +		nouveau_fb = nouveau_framebuffer(crtc->primary->fb);  		if (!nouveau_fb || !nouveau_fb->nvbo)  			continue; @@ -497,19 +665,15 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,  		goto fail;  	/* Emit the pageflip */ -	ret = RING_SPACE(chan, 3); +	ret = RING_SPACE(chan, 2);  	if (ret)  		goto fail; -	if (nv_device(drm->device)->card_type < NV_C0) { +	if (nv_device(drm->device)->card_type < NV_C0)  		BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); -		OUT_RING  (chan, 0x00000000); -		OUT_RING  (chan, 0x00000000); -	} else { -		BEGIN_NVC0(chan, 0, NV10_SUBCHAN_REF_CNT, 1); -		OUT_RING  (chan, 0); -		BEGIN_IMC0(chan, 0, NVSW_SUBCHAN_PAGE_FLIP, 0x0000); -	} +	else +		BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1); +	OUT_RING  (chan, 0x00000000);  	FIRE_RING (chan);  	ret = nouveau_fence_new(chan, false, pfence); @@ -526,22 +690,16 @@ fail:  int  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, -		       struct drm_pending_vblank_event *event, -		       uint32_t page_flip_flags) +		       struct drm_pending_vblank_event *event, u32 flags)  { +	const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;  	struct drm_device *dev = crtc->dev;  	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; +	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->primary->fb)->nvbo;  	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;  	struct nouveau_page_flip_state *s; -	struct nouveau_channel *chan = NULL; +	struct nouveau_channel *chan = drm->channel;  	struct nouveau_fence *fence; -	struct ttm_validate_buffer resv[2] = { -		{ .bo = &old_bo->bo }, -		{ .bo = &new_bo->bo }, -	}; -	struct ww_acquire_ctx ticket; -	LIST_HEAD(res);  	int ret;  	if (!drm->channel) @@ -551,26 +709,24 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,  	if (!s)  		return -ENOMEM; -	/* Choose the channel the flip will be handled in */ -	spin_lock(&old_bo->bo.bdev->fence_lock); -	fence = new_bo->bo.sync_obj; -	if (fence) -		chan = fence->channel; -	if (!chan) -		chan = drm->channel; -	spin_unlock(&old_bo->bo.bdev->fence_lock); -  	if (new_bo != old_bo) {  		ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM);  		if (ret)  			goto fail_free; - -		list_add(&resv[1].head, &res);  	} -	list_add(&resv[0].head, &res);  	mutex_lock(&chan->cli->mutex); -	ret = ttm_eu_reserve_buffers(&ticket, &res); + +	/* synchronise rendering channel with the kernel's channel */ +	spin_lock(&new_bo->bo.bdev->fence_lock); +	fence = nouveau_fence_ref(new_bo->bo.sync_obj); +	spin_unlock(&new_bo->bo.bdev->fence_lock); +	ret = nouveau_fence_sync(fence, chan); +	nouveau_fence_unref(&fence); +	if (ret) +		goto fail_unpin; + +	ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);  	if (ret)  		goto fail_unpin; @@ -580,32 +736,54 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,  		  fb->bits_per_pixel, fb->pitches[0], crtc->x, crtc->y,  		  new_bo->bo.offset }; +	/* Keep vblanks on during flip, for the target crtc of this flip */ +	drm_vblank_get(dev, nouveau_crtc(crtc)->index); +  	/* Emit a page flip */  	if (nv_device(drm->device)->card_type >= NV_50) { -		ret = nv50_display_flip_next(crtc, fb, chan, 0); +		ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);  		if (ret)  			goto fail_unreserve;  	} else {  		struct nv04_display *dispnv04 = nv04_display(dev); -		nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]); +		int head = nouveau_crtc(crtc)->index; + +		if (swap_interval) { +			ret = RING_SPACE(chan, 8); +			if (ret) +				goto fail_unreserve; + +			BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1); +			OUT_RING  (chan, 0); +			BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1); +			OUT_RING  (chan, head); +			BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1); +			OUT_RING  (chan, 0); +			BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1); +			OUT_RING  (chan, 0); +		} + +		nouveau_bo_ref(new_bo, &dispnv04->image[head]);  	}  	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); -	mutex_unlock(&chan->cli->mutex);  	if (ret)  		goto fail_unreserve; +	mutex_unlock(&chan->cli->mutex);  	/* Update the crtc struct and cleanup */ -	crtc->fb = fb; +	crtc->primary->fb = fb; -	ttm_eu_fence_buffer_objects(&ticket, &res, fence); +	nouveau_bo_fence(old_bo, fence); +	ttm_bo_unreserve(&old_bo->bo);  	if (old_bo != new_bo)  		nouveau_bo_unpin(old_bo);  	nouveau_fence_unref(&fence);  	return 0;  fail_unreserve: -	ttm_eu_backoff_reservation(&ticket, &res); +	drm_vblank_put(dev, nouveau_crtc(crtc)->index); +	ttm_bo_unreserve(&old_bo->bo);  fail_unpin:  	mutex_unlock(&chan->cli->mutex);  	if (old_bo != new_bo) @@ -624,6 +802,7 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,  	struct drm_device *dev = drm->dev;  	struct nouveau_page_flip_state *s;  	unsigned long flags; +	int crtcid = -1;  	spin_lock_irqsave(&dev->event_lock, flags); @@ -634,8 +813,16 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,  	}  	s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head); -	if (s->event) -		drm_send_vblank_event(dev, -1, s->event); +	if (s->event) { +		/* Vblank timestamps/counts are only correct on >= NV-50 */ +		if (nv_device(drm->device)->card_type >= NV_50) +			crtcid = s->crtc; + +		drm_send_vblank_event(dev, crtcid, s->event); +	} + +	/* Give up ownership of vblank for page-flipped crtc */ +	drm_vblank_put(dev, s->crtc);  	list_del(&s->head);  	if (ps) @@ -679,8 +866,8 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,  	if (ret)  		return ret; -	ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle); -	drm_gem_object_unreference_unlocked(bo->gem); +	ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); +	drm_gem_object_unreference_unlocked(&bo->gem);  	return ret;  } @@ -693,7 +880,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv,  	gem = drm_gem_object_lookup(dev, file_priv, handle);  	if (gem) { -		struct nouveau_bo *bo = gem->driver_private; +		struct nouveau_bo *bo = nouveau_gem_object(gem);  		*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);  		drm_gem_object_unreference_unlocked(gem);  		return 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 025c66f8e0e..a71cf77e55b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -36,6 +36,9 @@ struct nouveau_display {  	int  (*init)(struct drm_device *);  	void (*fini)(struct drm_device *); +	struct nouveau_object *core; +	struct nouveau_eventh **vblank; +  	struct drm_property *dithering_mode;  	struct drm_property *dithering_depth;  	struct drm_property *underscan_property; @@ -59,6 +62,12 @@ void nouveau_display_fini(struct drm_device *dev);  int  nouveau_display_suspend(struct drm_device *dev);  void nouveau_display_repin(struct drm_device *dev);  void nouveau_display_resume(struct drm_device *dev); +int  nouveau_display_vblank_enable(struct drm_device *, int); +void nouveau_display_vblank_disable(struct drm_device *, int); +int  nouveau_display_scanoutpos(struct drm_device *, int, unsigned int, +				int *, int *, ktime_t *, ktime_t *); +int  nouveau_display_vblstamp(struct drm_device *, int, int *, +			      struct timeval *, unsigned);  int  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,  			    struct drm_pending_vblank_event *event, diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 40f91e1e584..c177272152e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -100,7 +100,7 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,  	chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max; -	DRM_MEMORYBARRIER(); +	mb();  	/* Flush writes. */  	nouveau_bo_rd32(pb, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index 690d5930ce3..dc0e0c5cadb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -51,9 +51,11 @@ enum {  	NvSubCtxSurf2D  = 0,  	NvSubSw		= 1,  	NvSubImageBlit  = 2, -	NvSub2D		= 3,  	NvSubGdiRect    = 3, -	NvSubCopy	= 4, + +	NvSub2D		= 3, /* DO NOT CHANGE - hardcoded for kepler gr fifo */ +	NvSubCopy	= 4, /* DO NOT CHANGE - hardcoded for kepler gr fifo */ +	FermiSw		= 5, /* DO NOT CHANGE (well.. 6/7 will work...) */  };  /* Object handles. */ @@ -153,7 +155,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data)  }  #define WRITE_PUT(val) do {                                                    \ -	DRM_MEMORYBARRIER();                                                   \ +	mb();                                                   \  	nouveau_bo_rd32(chan->push.buffer, 0);                                 \  	nv_wo32(chan->object, chan->user_put, ((val) << 2) + chan->push.vma.offset);  \  } while (0) @@ -194,7 +196,6 @@ WIND_RING(struct nouveau_channel *chan)  #define NV84_SUBCHAN_UEVENT                                          0x00000020  #define NV84_SUBCHAN_WRCACHE_FLUSH                                   0x00000024  #define NV10_SUBCHAN_REF_CNT                                         0x00000050 -#define NVSW_SUBCHAN_PAGE_FLIP                                       0x00000054  #define NV11_SUBCHAN_DMA_SEMAPHORE                                   0x00000060  #define NV11_SUBCHAN_SEMAPHORE_OFFSET                                0x00000064  #define NV11_SUBCHAN_SEMAPHORE_ACQUIRE                               0x00000068 diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 36fd2250056..5675ffc175a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -55,11 +55,10 @@ nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,  } -bool -nouveau_dp_detect(struct drm_encoder *encoder) +int +nouveau_dp_detect(struct nouveau_encoder *nv_encoder)  { -	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -	struct drm_device *dev = encoder->dev; +	struct drm_device *dev = nv_encoder->base.base.dev;  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_i2c_port *auxch;  	u8 *dpcd = nv_encoder->dp.dpcd; @@ -67,11 +66,11 @@ nouveau_dp_detect(struct drm_encoder *encoder)  	auxch = nv_encoder->i2c;  	if (!auxch) -		return false; +		return -ENODEV;  	ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8);  	if (ret) -		return false; +		return ret;  	nv_encoder->dp.link_bw = 27000 * dpcd[1];  	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; @@ -91,6 +90,5 @@ nouveau_dp_detect(struct drm_encoder *encoder)  		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);  	nouveau_dp_probe_oui(dev, auxch, dpcd); - -	return true; +	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index e893c536240..5425ffe3931 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -33,10 +33,12 @@  #include <core/client.h>  #include <core/gpuobj.h>  #include <core/class.h> +#include <core/option.h>  #include <engine/device.h>  #include <engine/disp.h>  #include <engine/fifo.h> +#include <engine/software.h>  #include <subdev/vm.h> @@ -46,7 +48,8 @@  #include "nouveau_gem.h"  #include "nouveau_agp.h"  #include "nouveau_vga.h" -#include "nouveau_pm.h" +#include "nouveau_sysfs.h" +#include "nouveau_hwmon.h"  #include "nouveau_acpi.h"  #include "nouveau_bios.h"  #include "nouveau_ioctl.h" @@ -78,59 +81,39 @@ module_param_named(runpm, nouveau_runtime_pm, int, 0400);  static struct drm_driver driver; -static int -nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head) -{ -	struct nouveau_drm *drm = -		container_of(event, struct nouveau_drm, vblank[head]); -	drm_handle_vblank(drm->dev, head); -	return NVKM_EVENT_KEEP; -} - -static int -nouveau_drm_vblank_enable(struct drm_device *dev, int head) +static u64 +nouveau_pci_name(struct pci_dev *pdev)  { -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_disp *pdisp = nouveau_disp(drm->device); - -	if (WARN_ON_ONCE(head > ARRAY_SIZE(drm->vblank))) -		return -EIO; -	WARN_ON_ONCE(drm->vblank[head].func); -	drm->vblank[head].func = nouveau_drm_vblank_handler; -	nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]); -	return 0; +	u64 name = (u64)pci_domain_nr(pdev->bus) << 32; +	name |= pdev->bus->number << 16; +	name |= PCI_SLOT(pdev->devfn) << 8; +	return name | PCI_FUNC(pdev->devfn);  } -static void -nouveau_drm_vblank_disable(struct drm_device *dev, int head) +static u64 +nouveau_platform_name(struct platform_device *platformdev)  { -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_disp *pdisp = nouveau_disp(drm->device); -	if (drm->vblank[head].func) -		nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]); -	else -		WARN_ON_ONCE(1); -	drm->vblank[head].func = NULL; +	return platformdev->id;  }  static u64 -nouveau_name(struct pci_dev *pdev) +nouveau_name(struct drm_device *dev)  { -	u64 name = (u64)pci_domain_nr(pdev->bus) << 32; -	name |= pdev->bus->number << 16; -	name |= PCI_SLOT(pdev->devfn) << 8; -	return name | PCI_FUNC(pdev->devfn); +	if (dev->pdev) +		return nouveau_pci_name(dev->pdev); +	else +		return nouveau_platform_name(dev->platformdev);  }  static int -nouveau_cli_create(struct pci_dev *pdev, const char *name, +nouveau_cli_create(u64 name, const char *sname,  		   int size, void **pcli)  {  	struct nouveau_cli *cli;  	int ret;  	*pcli = NULL; -	ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, +	ret = nouveau_client_create_(sname, name, nouveau_config,  				     nouveau_debug, size, pcli);  	cli = *pcli;  	if (ret) { @@ -177,7 +160,8 @@ nouveau_accel_init(struct nouveau_drm *drm)  	/* initialise synchronisation routines */  	if      (device->card_type < NV_10) ret = nv04_fence_create(drm); -	else if (device->chipset   <  0x17) ret = nv10_fence_create(drm); +	else if (device->card_type < NV_11 || +		 device->chipset   <  0x17) ret = nv10_fence_create(drm);  	else if (device->card_type < NV_50) ret = nv17_fence_create(drm);  	else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);  	else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); @@ -224,6 +208,32 @@ nouveau_accel_init(struct nouveau_drm *drm)  		return;  	} +	ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW, +				 nouveau_abi16_swclass(drm), NULL, 0, &object); +	if (ret == 0) { +		struct nouveau_software_chan *swch = (void *)object->parent; +		ret = RING_SPACE(drm->channel, 2); +		if (ret == 0) { +			if (device->card_type < NV_C0) { +				BEGIN_NV04(drm->channel, NvSubSw, 0, 1); +				OUT_RING  (drm->channel, NVDRM_NVSW); +			} else +			if (device->card_type < NV_E0) { +				BEGIN_NVC0(drm->channel, FermiSw, 0, 1); +				OUT_RING  (drm->channel, 0x001f0000); +			} +		} +		swch = (void *)object->parent; +		swch->flip = nouveau_flip_complete; +		swch->flip_data = drm->channel; +	} + +	if (ret) { +		NV_ERROR(drm, "failed to allocate software object, %d\n", ret); +		nouveau_accel_fini(drm); +		return; +	} +  	if (device->card_type < NV_C0) {  		ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0,  					&drm->notify); @@ -287,7 +297,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,  	remove_conflicting_framebuffers(aper, "nouveaufb", boot);  	kfree(aper); -	ret = nouveau_device_create(pdev, nouveau_name(pdev), pci_name(pdev), +	ret = nouveau_device_create(pdev, NOUVEAU_BUS_PCI, +				    nouveau_pci_name(pdev), pci_name(pdev),  				    nouveau_config, nouveau_debug, &device);  	if (ret)  		return ret; @@ -306,22 +317,27 @@ static int nouveau_drm_probe(struct pci_dev *pdev,  #define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403  static void -nouveau_get_hdmi_dev(struct drm_device *dev) +nouveau_get_hdmi_dev(struct nouveau_drm *drm)  { -	struct nouveau_drm *drm = dev->dev_private; -	struct pci_dev *pdev = dev->pdev; +	struct pci_dev *pdev = drm->dev->pdev; + +	if (!pdev) { +		DRM_INFO("not a PCI device; no HDMI\n"); +		drm->hdmi_device = NULL; +		return; +	}  	/* subfunction one is a hdmi audio device? */  	drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,  						PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));  	if (!drm->hdmi_device) { -		DRM_INFO("hdmi device  not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1); +		NV_DEBUG(drm, "hdmi device not found %d %d %d\n", pdev->bus->number, PCI_SLOT(pdev->devfn), 1);  		return;  	}  	if ((drm->hdmi_device->class >> 8) != PCI_CLASS_MULTIMEDIA_HD_AUDIO) { -		DRM_INFO("possible hdmi device  not audio %d\n", drm->hdmi_device->class); +		NV_DEBUG(drm, "possible hdmi device not audio %d\n", drm->hdmi_device->class);  		pci_dev_put(drm->hdmi_device);  		drm->hdmi_device = NULL;  		return; @@ -336,22 +352,24 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)  	struct nouveau_drm *drm;  	int ret; -	ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); +	ret = nouveau_cli_create(nouveau_name(dev), "DRM", sizeof(*drm), +				 (void **)&drm);  	if (ret)  		return ret;  	dev->dev_private = drm;  	drm->dev = dev; +	nouveau_client(drm)->debug = nouveau_dbgopt(nouveau_debug, "DRM");  	INIT_LIST_HEAD(&drm->clients);  	spin_lock_init(&drm->tile.lock); -	nouveau_get_hdmi_dev(dev); +	nouveau_get_hdmi_dev(drm);  	/* make sure AGP controller is in a consistent state before we  	 * (possibly) execute vbios init tables (see nouveau_agp.h)  	 */ -	if (drm_pci_device_is_agp(dev) && dev->agp) { +	if (pdev && drm_pci_device_is_agp(dev) && dev->agp) {  		/* dummy device object, doesn't init anything, but allows  		 * agp code access to registers  		 */ @@ -382,6 +400,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)  	if (ret)  		goto fail_device; +	dev->irq_enabled = true; +  	/* workaround an odd issue on nvc1 by disabling the device's  	 * nosnoop capability.  hopefully won't cause issues until a  	 * better fix is found - assuming there is one... @@ -418,8 +438,8 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)  			goto fail_dispinit;  	} -	nouveau_pm_init(dev); - +	nouveau_sysfs_init(dev); +	nouveau_hwmon_init(dev);  	nouveau_accel_init(drm);  	nouveau_fbcon_init(dev); @@ -455,8 +475,8 @@ nouveau_drm_unload(struct drm_device *dev)  	pm_runtime_get_sync(dev->dev);  	nouveau_fbcon_fini(dev);  	nouveau_accel_fini(drm); - -	nouveau_pm_fini(dev); +	nouveau_hwmon_fini(dev); +	nouveau_sysfs_fini(dev);  	if (dev->mode_config.num_crtc)  		nouveau_display_fini(dev); @@ -481,6 +501,7 @@ nouveau_drm_remove(struct pci_dev *pdev)  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_object *device; +	dev->irq_enabled = false;  	device = drm->client.base.device;  	drm_put_dev(dev); @@ -489,39 +510,41 @@ nouveau_drm_remove(struct pci_dev *pdev)  }  static int -nouveau_do_suspend(struct drm_device *dev) +nouveau_do_suspend(struct drm_device *dev, bool runtime)  {  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_cli *cli;  	int ret; -	if (dev->mode_config.num_crtc) { -		NV_SUSPEND(drm, "suspending display...\n"); +	if (dev->mode_config.num_crtc && !runtime) { +		NV_INFO(drm, "suspending display...\n");  		ret = nouveau_display_suspend(dev);  		if (ret)  			return ret;  	} -	NV_SUSPEND(drm, "evicting buffers...\n"); +	NV_INFO(drm, "evicting buffers...\n");  	ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); -	NV_SUSPEND(drm, "waiting for kernel channels to go idle...\n"); +	NV_INFO(drm, "waiting for kernel channels to go idle...\n");  	if (drm->cechan) {  		ret = nouveau_channel_idle(drm->cechan);  		if (ret) -			return ret; +			goto fail_display;  	}  	if (drm->channel) {  		ret = nouveau_channel_idle(drm->channel);  		if (ret) -			return ret; +			goto fail_display;  	} -	NV_SUSPEND(drm, "suspending client object trees...\n"); +	NV_INFO(drm, "suspending client object trees...\n");  	if (drm->fence && nouveau_fence(drm)->suspend) { -		if (!nouveau_fence(drm)->suspend(drm)) -			return -ENOMEM; +		if (!nouveau_fence(drm)->suspend(drm)) { +			ret = -ENOMEM; +			goto fail_display; +		}  	}  	list_for_each_entry(cli, &drm->clients, head) { @@ -530,7 +553,7 @@ nouveau_do_suspend(struct drm_device *dev)  			goto fail_client;  	} -	NV_SUSPEND(drm, "suspending kernel object tree...\n"); +	NV_INFO(drm, "suspending kernel object tree...\n");  	ret = nouveau_client_fini(&drm->client.base, true);  	if (ret)  		goto fail_client; @@ -543,8 +566,12 @@ fail_client:  		nouveau_client_init(&cli->base);  	} +	if (drm->fence && nouveau_fence(drm)->resume) +		nouveau_fence(drm)->resume(drm); + +fail_display:  	if (dev->mode_config.num_crtc) { -		NV_SUSPEND(drm, "resuming display...\n"); +		NV_INFO(drm, "resuming display...\n");  		nouveau_display_resume(dev);  	}  	return ret; @@ -563,16 +590,13 @@ int nouveau_pmops_suspend(struct device *dev)  	if (drm_dev->mode_config.num_crtc)  		nouveau_fbcon_set_suspend(drm_dev, 1); -	nv_suspend_set_printk_level(NV_DBG_INFO); -	ret = nouveau_do_suspend(drm_dev); +	ret = nouveau_do_suspend(drm_dev, false);  	if (ret)  		return ret;  	pci_save_state(pdev);  	pci_disable_device(pdev);  	pci_set_power_state(pdev, PCI_D3hot); -	nv_suspend_set_printk_level(NV_DBG_DEBUG); -  	return 0;  } @@ -582,15 +606,15 @@ nouveau_do_resume(struct drm_device *dev)  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_cli *cli; -	NV_SUSPEND(drm, "re-enabling device...\n"); +	NV_INFO(drm, "re-enabling device...\n");  	nouveau_agp_reset(drm); -	NV_SUSPEND(drm, "resuming kernel object tree...\n"); +	NV_INFO(drm, "resuming kernel object tree...\n");  	nouveau_client_init(&drm->client.base);  	nouveau_agp_init(drm); -	NV_SUSPEND(drm, "resuming client object trees...\n"); +	NV_INFO(drm, "resuming client object trees...\n");  	if (drm->fence && nouveau_fence(drm)->resume)  		nouveau_fence(drm)->resume(drm); @@ -599,10 +623,9 @@ nouveau_do_resume(struct drm_device *dev)  	}  	nouveau_run_vbios_init(dev); -	nouveau_pm_resume(dev);  	if (dev->mode_config.num_crtc) { -		NV_SUSPEND(drm, "resuming display...\n"); +		NV_INFO(drm, "resuming display...\n");  		nouveau_display_repin(dev);  	} @@ -626,19 +649,15 @@ int nouveau_pmops_resume(struct device *dev)  		return ret;  	pci_set_master(pdev); -	nv_suspend_set_printk_level(NV_DBG_INFO);  	ret = nouveau_do_resume(drm_dev); -	if (ret) { -		nv_suspend_set_printk_level(NV_DBG_DEBUG); +	if (ret)  		return ret; -	} -	if (drm_dev->mode_config.num_crtc) -		nouveau_fbcon_set_suspend(drm_dev, 0); -	nouveau_fbcon_zfill_all(drm_dev); -	if (drm_dev->mode_config.num_crtc) +	if (drm_dev->mode_config.num_crtc) {  		nouveau_display_resume(drm_dev); -	nv_suspend_set_printk_level(NV_DBG_DEBUG); +		nouveau_fbcon_set_suspend(drm_dev, 0); +	} +  	return 0;  } @@ -648,12 +667,10 @@ static int nouveau_pmops_freeze(struct device *dev)  	struct drm_device *drm_dev = pci_get_drvdata(pdev);  	int ret; -	nv_suspend_set_printk_level(NV_DBG_INFO);  	if (drm_dev->mode_config.num_crtc)  		nouveau_fbcon_set_suspend(drm_dev, 1); -	ret = nouveau_do_suspend(drm_dev); -	nv_suspend_set_printk_level(NV_DBG_DEBUG); +	ret = nouveau_do_suspend(drm_dev, false);  	return ret;  } @@ -663,18 +680,15 @@ static int nouveau_pmops_thaw(struct device *dev)  	struct drm_device *drm_dev = pci_get_drvdata(pdev);  	int ret; -	nv_suspend_set_printk_level(NV_DBG_INFO);  	ret = nouveau_do_resume(drm_dev); -	if (ret) { -		nv_suspend_set_printk_level(NV_DBG_DEBUG); +	if (ret)  		return ret; -	} -	if (drm_dev->mode_config.num_crtc) -		nouveau_fbcon_set_suspend(drm_dev, 0); -	nouveau_fbcon_zfill_all(drm_dev); -	if (drm_dev->mode_config.num_crtc) + +	if (drm_dev->mode_config.num_crtc) {  		nouveau_display_resume(drm_dev); -	nv_suspend_set_printk_level(NV_DBG_DEBUG); +		nouveau_fbcon_set_suspend(drm_dev, 0); +	} +  	return 0;  } @@ -682,7 +696,6 @@ static int nouveau_pmops_thaw(struct device *dev)  static int  nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)  { -	struct pci_dev *pdev = dev->pdev;  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_cli *cli;  	char name[32], tmpname[TASK_COMM_LEN]; @@ -690,13 +703,15 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)  	/* need to bring up power immediately if opening device */  	ret = pm_runtime_get_sync(dev->dev); -	if (ret < 0) +	if (ret < 0 && ret != -EACCES)  		return ret;  	get_task_comm(tmpname, current);  	snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); -	ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); +	ret = nouveau_cli_create(nouveau_name(dev), name, sizeof(*cli), +			(void **)&cli); +  	if (ret)  		goto out_suspend; @@ -773,7 +788,7 @@ long nouveau_drm_ioctl(struct file *filp,  	dev = file_priv->minor->dev;  	ret = pm_runtime_get_sync(dev->dev); -	if (ret < 0) +	if (ret < 0 && ret != -EACCES)  		return ret;  	ret = drm_ioctl(filp, cmd, arg); @@ -816,8 +831,10 @@ driver = {  #endif  	.get_vblank_counter = drm_vblank_count, -	.enable_vblank = nouveau_drm_vblank_enable, -	.disable_vblank = nouveau_drm_vblank_disable, +	.enable_vblank = nouveau_display_vblank_enable, +	.disable_vblank = nouveau_display_vblank_disable, +	.get_scanout_position = nouveau_display_scanoutpos, +	.get_vblank_timestamp = nouveau_display_vblstamp,  	.ioctls = nouveau_ioctls,  	.num_ioctls = ARRAY_SIZE(nouveau_ioctls), @@ -834,7 +851,6 @@ driver = {  	.gem_prime_vmap = nouveau_gem_prime_vmap,  	.gem_prime_vunmap = nouveau_gem_prime_vunmap, -	.gem_init_object = nouveau_gem_object_new,  	.gem_free_object = nouveau_gem_object_del,  	.gem_open_object = nouveau_gem_object_open,  	.gem_close_object = nouveau_gem_object_close, @@ -876,13 +892,23 @@ static int nouveau_pmops_runtime_suspend(struct device *dev)  	struct drm_device *drm_dev = pci_get_drvdata(pdev);  	int ret; -	if (nouveau_runtime_pm == 0) -		return -EINVAL; +	if (nouveau_runtime_pm == 0) { +		pm_runtime_forbid(dev); +		return -EBUSY; +	} +	/* are we optimus enabled? */ +	if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { +		DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); +		pm_runtime_forbid(dev); +		return -EBUSY; +	} + +	nv_debug_level(SILENT);  	drm_kms_helper_poll_disable(drm_dev);  	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);  	nouveau_switcheroo_optimus_dsm(); -	ret = nouveau_do_suspend(drm_dev); +	ret = nouveau_do_suspend(drm_dev, true);  	pci_save_state(pdev);  	pci_disable_device(pdev);  	pci_set_power_state(pdev, PCI_D3cold); @@ -908,13 +934,12 @@ static int nouveau_pmops_runtime_resume(struct device *dev)  	pci_set_master(pdev);  	ret = nouveau_do_resume(drm_dev); -	if (drm_dev->mode_config.num_crtc) -		nouveau_display_resume(drm_dev);  	drm_kms_helper_poll_enable(drm_dev);  	/* do magic */  	nv_mask(device, 0x88488, (1 << 25), (1 << 25));  	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);  	drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; +	nv_debug_level(NORMAL);  	return ret;  } @@ -925,12 +950,15 @@ static int nouveau_pmops_runtime_idle(struct device *dev)  	struct nouveau_drm *drm = nouveau_drm(drm_dev);  	struct drm_crtc *crtc; -	if (nouveau_runtime_pm == 0) +	if (nouveau_runtime_pm == 0) { +		pm_runtime_forbid(dev);  		return -EBUSY; +	}  	/* are we optimus enabled? */  	if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) {  		DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); +		pm_runtime_forbid(dev);  		return -EBUSY;  	} @@ -976,6 +1004,25 @@ nouveau_drm_pci_driver = {  	.driver.pm = &nouveau_pm_ops,  }; +int nouveau_drm_platform_probe(struct platform_device *pdev) +{ +	struct nouveau_device *device; +	int ret; + +	ret = nouveau_device_create(pdev, NOUVEAU_BUS_PLATFORM, +				    nouveau_platform_name(pdev), +				    dev_name(&pdev->dev), nouveau_config, +				    nouveau_debug, &device); + +	ret = drm_platform_init(&driver, pdev); +	if (ret) { +		nouveau_object_ref(NULL, (struct nouveau_object **)&device); +		return ret; +	} + +	return ret; +} +  static int __init  nouveau_drm_init(void)  { diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 994fd6ec373..7efbafaf7c1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -51,10 +51,13 @@ struct nouveau_drm_tile {  };  enum nouveau_drm_handle { -	NVDRM_CLIENT = 0xffffffff, -	NVDRM_DEVICE = 0xdddddddd, -	NVDRM_PUSH   = 0xbbbb0000, /* |= client chid */ -	NVDRM_CHAN   = 0xcccc0000, /* |= client chid */ +	NVDRM_CLIENT  = 0xffffffff, +	NVDRM_DEVICE  = 0xdddddddd, +	NVDRM_CONTROL = 0xdddddddc, +	NVDRM_DISPLAY = 0xd1500000, +	NVDRM_PUSH    = 0xbbbb0000, /* |= client chid */ +	NVDRM_CHAN    = 0xcccc0000, /* |= client chid */ +	NVDRM_NVSW    = 0x55550000,  };  struct nouveau_cli { @@ -127,10 +130,10 @@ struct nouveau_drm {  	struct nvbios vbios;  	struct nouveau_display *display;  	struct backlight_device *backlight; -	struct nouveau_eventh vblank[4];  	/* power management */ -	struct nouveau_pm *pm; +	struct nouveau_hwmon *hwmon; +	struct nouveau_sysfs *sysfs;  	/* display power reference */  	bool have_disp_power_ref; @@ -154,15 +157,11 @@ nouveau_dev(struct drm_device *dev)  int nouveau_pmops_suspend(struct device *);  int nouveau_pmops_resume(struct device *); -#define NV_SUSPEND(cli, fmt, args...) nv_suspend((cli), fmt, ##args)  #define NV_FATAL(cli, fmt, args...) nv_fatal((cli), fmt, ##args)  #define NV_ERROR(cli, fmt, args...) nv_error((cli), fmt, ##args)  #define NV_WARN(cli, fmt, args...) nv_warn((cli), fmt, ##args)  #define NV_INFO(cli, fmt, args...) nv_info((cli), fmt, ##args) -#define NV_DEBUG(cli, fmt, args...) do {                                       \ -	if (drm_debug & DRM_UT_DRIVER)                                         \ -		nv_info((cli), fmt, ##args);                                   \ -} while (0) +#define NV_DEBUG(cli, fmt, args...) nv_debug((cli), fmt, ##args)  extern int nouveau_modeset; diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 24660c0f713..5f0e37fc284 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -46,6 +46,7 @@ struct nouveau_encoder {  	/* different to drm_encoder.crtc, this reflects what's  	 * actually programmed on the hw, not the proposed crtc */  	struct drm_crtc *crtc; +	u32 ctrl;  	struct drm_display_mode mode;  	int last_dpms; @@ -84,9 +85,7 @@ get_slave_funcs(struct drm_encoder *enc)  }  /* nouveau_dp.c */ -bool nouveau_dp_detect(struct drm_encoder *); -void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, -		     struct nouveau_object *); +int nouveau_dp_detect(struct nouveau_encoder *);  struct nouveau_connector *  nouveau_encoder_connector_get(struct nouveau_encoder *encoder); diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 8f6d63d7edd..191665ee7f5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -420,7 +420,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)  		nouveau_bo_unmap(nouveau_fb->nvbo);  		nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);  		nouveau_bo_unpin(nouveau_fb->nvbo); -		drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); +		drm_gem_object_unreference_unlocked(&nouveau_fb->nvbo->gem);  		nouveau_fb->nvbo = NULL;  	}  	drm_fb_helper_fini(&fbcon->helper); @@ -454,7 +454,8 @@ nouveau_fbcon_init(struct drm_device *dev)  	int preferred_bpp;  	int ret; -	if (!dev->mode_config.num_crtc) +	if (!dev->mode_config.num_crtc || +	    (dev->pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)  		return 0;  	fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); @@ -502,34 +503,38 @@ nouveau_fbcon_fini(struct drm_device *dev)  	drm->fbcon = NULL;  } -void nouveau_fbcon_save_disable_accel(struct drm_device *dev) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); - -	drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; -	drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; -} - -void nouveau_fbcon_restore_accel(struct drm_device *dev) +void +nouveau_fbcon_save_disable_accel(struct drm_device *dev)  {  	struct nouveau_drm *drm = nouveau_drm(dev); -	drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; +	if (drm->fbcon) { +		drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; +		drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; +	}  } -void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) +void +nouveau_fbcon_restore_accel(struct drm_device *dev)  {  	struct nouveau_drm *drm = nouveau_drm(dev); -	console_lock(); -	if (state == 0) -		nouveau_fbcon_save_disable_accel(dev); -	fb_set_suspend(drm->fbcon->helper.fbdev, state); -	if (state == 1) -		nouveau_fbcon_restore_accel(dev); -	console_unlock(); +	if (drm->fbcon) { +		drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; +	}  } -void nouveau_fbcon_zfill_all(struct drm_device *dev) +void +nouveau_fbcon_set_suspend(struct drm_device *dev, int state)  {  	struct nouveau_drm *drm = nouveau_drm(dev); -	nouveau_fbcon_zfill(dev, drm->fbcon); +	if (drm->fbcon) { +		console_lock(); +		if (state == 1) +			nouveau_fbcon_save_disable_accel(dev); +		fb_set_suspend(drm->fbcon->helper.fbdev, state); +		if (state == 0) { +			nouveau_fbcon_restore_accel(dev); +			nouveau_fbcon_zfill(dev, drm->fbcon); +		} +		console_unlock(); +	}  } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index fdfc0c94fbc..fcff797d208 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -61,7 +61,6 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info);  int nouveau_fbcon_init(struct drm_device *dev);  void nouveau_fbcon_fini(struct drm_device *dev);  void nouveau_fbcon_set_suspend(struct drm_device *dev, int state); -void nouveau_fbcon_zfill_all(struct drm_device *dev);  void nouveau_fbcon_save_disable_accel(struct drm_device *dev);  void nouveau_fbcon_restore_accel(struct drm_device *dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index be3149932c2..ab5ea3b0d66 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -143,7 +143,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)  	int ret;  	fence->channel  = chan; -	fence->timeout  = jiffies + (15 * DRM_HZ); +	fence->timeout  = jiffies + (15 * HZ);  	fence->sequence = ++fctx->sequence;  	ret = fctx->emit(fence); @@ -165,17 +165,11 @@ nouveau_fence_done(struct nouveau_fence *fence)  	return !fence->channel;  } -struct nouveau_fence_uevent { -	struct nouveau_eventh handler; -	struct nouveau_fence_priv *priv; -}; -  static int -nouveau_fence_wait_uevent_handler(struct nouveau_eventh *event, int index) +nouveau_fence_wait_uevent_handler(void *data, u32 type, int index)  { -	struct nouveau_fence_uevent *uevent = -		container_of(event, struct nouveau_fence_uevent, handler); -	wake_up_all(&uevent->priv->waiting); +	struct nouveau_fence_priv *priv = data; +	wake_up_all(&priv->waiting);  	return NVKM_EVENT_KEEP;  } @@ -186,13 +180,16 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)  	struct nouveau_channel *chan = fence->channel;  	struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device);  	struct nouveau_fence_priv *priv = chan->drm->fence; -	struct nouveau_fence_uevent uevent = { -		.handler.func = nouveau_fence_wait_uevent_handler, -		.priv = priv, -	}; +	struct nouveau_eventh *handler;  	int ret = 0; -	nouveau_event_get(pfifo->uevent, 0, &uevent.handler); +	ret = nouveau_event_new(pfifo->uevent, 1, 0, +				nouveau_fence_wait_uevent_handler, +				priv, &handler); +	if (ret) +		return ret; + +	nouveau_event_get(handler);  	if (fence->timeout) {  		unsigned long timeout = fence->timeout - jiffies; @@ -224,7 +221,7 @@ nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr)  		}  	} -	nouveau_event_put(pfifo->uevent, 0, &uevent.handler); +	nouveau_event_ref(NULL, &handler);  	if (unlikely(ret < 0))  		return ret; @@ -309,7 +306,8 @@ nouveau_fence_unref(struct nouveau_fence **pfence)  struct nouveau_fence *  nouveau_fence_ref(struct nouveau_fence *fence)  { -	kref_get(&fence->kref); +	if (fence) +		kref_get(&fence->kref);  	return fence;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index f32b71238c0..c90c0dc0afe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -34,29 +34,20 @@  #include "nouveau_ttm.h"  #include "nouveau_gem.h" -int -nouveau_gem_object_new(struct drm_gem_object *gem) -{ -	return 0; -} -  void  nouveau_gem_object_del(struct drm_gem_object *gem)  { -	struct nouveau_bo *nvbo = gem->driver_private; +	struct nouveau_bo *nvbo = nouveau_gem_object(gem);  	struct ttm_buffer_object *bo = &nvbo->bo; -	if (!nvbo) -		return; -	nvbo->gem = NULL; -  	if (gem->import_attach)  		drm_prime_gem_destroy(gem, nvbo->bo.sg); -	ttm_bo_unref(&bo); -  	drm_gem_object_release(gem); -	kfree(gem); + +	/* reset filp so nouveau_bo_del_ttm() can test for it */ +	gem->filp = NULL; +	ttm_bo_unref(&bo);  }  int @@ -115,8 +106,7 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma)  	if (mapped) {  		spin_lock(&nvbo->bo.bdev->fence_lock); -		if (nvbo->bo.sync_obj) -			fence = nouveau_fence_ref(nvbo->bo.sync_obj); +		fence = nouveau_fence_ref(nvbo->bo.sync_obj);  		spin_unlock(&nvbo->bo.bdev->fence_lock);  	} @@ -186,14 +176,15 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,  	if (nv_device(drm->device)->card_type >= NV_50)  		nvbo->valid_domains &= domain; -	nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); -	if (!nvbo->gem) { +	/* Initialize the embedded gem-object. We return a single gem-reference +	 * to the caller, instead of a normal nouveau_bo ttm reference. */ +	ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size); +	if (ret) {  		nouveau_bo_ref(NULL, pnvbo);  		return -ENOMEM;  	} -	nvbo->bo.persistent_swap_storage = nvbo->gem->filp; -	nvbo->gem->driver_private = nvbo; +	nvbo->bo.persistent_swap_storage = nvbo->gem.filp;  	return 0;  } @@ -237,8 +228,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,  	struct nouveau_bo *nvbo = NULL;  	int ret = 0; -	drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; -  	if (!pfb->memtype_valid(pfb, req->info.tile_flags)) {  		NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags);  		return -EINVAL; @@ -250,15 +239,15 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,  	if (ret)  		return ret; -	ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); +	ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle);  	if (ret == 0) { -		ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info); +		ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info);  		if (ret)  			drm_gem_handle_delete(file_priv, req->info.handle);  	}  	/* drop reference from allocate - handle holds it now */ -	drm_gem_object_unreference_unlocked(nvbo->gem); +	drm_gem_object_unreference_unlocked(&nvbo->gem);  	return ret;  } @@ -266,7 +255,7 @@ static int  nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,  		       uint32_t write_domains, uint32_t valid_domains)  { -	struct nouveau_bo *nvbo = gem->driver_private; +	struct nouveau_bo *nvbo = nouveau_gem_object(gem);  	struct ttm_buffer_object *bo = &nvbo->bo;  	uint32_t domains = valid_domains & nvbo->valid_domains &  		(write_domains ? write_domains : read_domains); @@ -317,7 +306,8 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence,  	list_for_each_safe(entry, tmp, list) {  		nvbo = list_entry(entry, struct nouveau_bo, entry); -		nouveau_bo_fence(nvbo, fence); +		if (likely(fence)) +			nouveau_bo_fence(nvbo, fence);  		if (unlikely(nvbo->validate_mapped)) {  			ttm_bo_kunmap(&nvbo->kmap); @@ -327,7 +317,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence,  		list_del(&nvbo->entry);  		nvbo->reserved_by = NULL;  		ttm_bo_unreserve_ticket(&nvbo->bo, ticket); -		drm_gem_object_unreference_unlocked(nvbo->gem); +		drm_gem_object_unreference_unlocked(&nvbo->gem);  	}  } @@ -376,7 +366,7 @@ retry:  			validate_fini(op, NULL);  			return -ENOENT;  		} -		nvbo = gem->driver_private; +		nvbo = nouveau_gem_object(gem);  		if (nvbo == res_bo) {  			res_bo = NULL;  			drm_gem_object_unreference_unlocked(gem); @@ -446,8 +436,7 @@ validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)  	int ret = 0;  	spin_lock(&nvbo->bo.bdev->fence_lock); -	if (nvbo->bo.sync_obj) -		fence = nouveau_fence_ref(nvbo->bo.sync_obj); +	fence = nouveau_fence_ref(nvbo->bo.sync_obj);  	spin_unlock(&nvbo->bo.bdev->fence_lock);  	if (fence) { @@ -472,13 +461,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,  	list_for_each_entry(nvbo, list, entry) {  		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; -		ret = validate_sync(chan, nvbo); -		if (unlikely(ret)) { -			NV_ERROR(cli, "fail pre-validate sync\n"); -			return ret; -		} - -		ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, +		ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains,  					     b->write_domains,  					     b->valid_domains);  		if (unlikely(ret)) { @@ -515,7 +498,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,  			b->presumed.valid = 0;  			relocs++; -			if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed, +			if (copy_to_user(&upbbo[nvbo->pbbo_index].presumed,  					     &b->presumed, sizeof(b->presumed)))  				return -EFAULT;  		} @@ -602,7 +585,7 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)  	if (!mem)  		return ERR_PTR(-ENOMEM); -	if (DRM_COPY_FROM_USER(mem, userptr, size)) { +	if (copy_from_user(mem, userptr, size)) {  		u_free(mem);  		return ERR_PTR(-EFAULT);  	} diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h index 502e4290aa8..7caca057bc3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.h +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h @@ -12,14 +12,13 @@  static inline struct nouveau_bo *  nouveau_gem_object(struct drm_gem_object *gem)  { -	return gem ? gem->driver_private : NULL; +	return gem ? container_of(gem, struct nouveau_bo, gem) : NULL;  }  /* nouveau_gem.c */  extern int nouveau_gem_new(struct drm_device *, int size, int align,  			   uint32_t domain, uint32_t tile_mode,  			   uint32_t tile_flags, struct nouveau_bo **); -extern int nouveau_gem_object_new(struct drm_gem_object *);  extern void nouveau_gem_object_del(struct drm_gem_object *);  extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *);  extern void nouveau_gem_object_close(struct drm_gem_object *, diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_hwmon.c index 936b442a6ab..19fd767bab1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.c @@ -32,369 +32,12 @@  #include <drm/drmP.h>  #include "nouveau_drm.h" -#include "nouveau_pm.h" +#include "nouveau_hwmon.h"  #include <subdev/gpio.h>  #include <subdev/timer.h>  #include <subdev/therm.h> -MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); -static char *nouveau_perflvl; -module_param_named(perflvl, nouveau_perflvl, charp, 0400); - -MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)"); -static int nouveau_perflvl_wr; -module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); - -static int -nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, -		       struct nouveau_pm_level *a, struct nouveau_pm_level *b) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_therm *therm = nouveau_therm(drm->device); -	int ret; - -	/*XXX: not on all boards, we should control based on temperature -	 *     on recent boards..  or maybe on some other factor we don't -	 *     know about? -	 */ -	if (therm && therm->fan_set && -		a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { -		ret = therm->fan_set(therm, perflvl->fanspeed); -		if (ret && ret != -ENODEV) { -			NV_ERROR(drm, "fanspeed set failed: %d\n", ret); -		} -	} - -	if (pm->voltage.supported && pm->voltage_set) { -		if (perflvl->volt_min && b->volt_min > a->volt_min) { -			ret = pm->voltage_set(dev, perflvl->volt_min); -			if (ret) { -				NV_ERROR(drm, "voltage set failed: %d\n", ret); -				return ret; -			} -		} -	} - -	return 0; -} - -static int -nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_pm *pm = nouveau_pm(dev); -	void *state; -	int ret; - -	if (perflvl == pm->cur) -		return 0; - -	ret = nouveau_pm_perflvl_aux(dev, perflvl, pm->cur, perflvl); -	if (ret) -		return ret; - -	state = pm->clocks_pre(dev, perflvl); -	if (IS_ERR(state)) { -		ret = PTR_ERR(state); -		goto error; -	} -	ret = pm->clocks_set(dev, state); -	if (ret) -		goto error; - -	ret = nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur); -	if (ret) -		return ret; - -	pm->cur = perflvl; -	return 0; - -error: -	/* restore the fan speed and voltage before leaving */ -	nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur); -	return ret; -} - -void -nouveau_pm_trigger(struct drm_device *dev) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_timer *ptimer = nouveau_timer(drm->device); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_profile *profile = NULL; -	struct nouveau_pm_level *perflvl = NULL; -	int ret; - -	/* select power profile based on current power source */ -	if (power_supply_is_system_supplied()) -		profile = pm->profile_ac; -	else -		profile = pm->profile_dc; - -	if (profile != pm->profile) { -		pm->profile->func->fini(pm->profile); -		pm->profile = profile; -		pm->profile->func->init(pm->profile); -	} - -	/* select performance level based on profile */ -	perflvl = profile->func->select(profile); - -	/* change perflvl, if necessary */ -	if (perflvl != pm->cur) { -		u64 time0 = ptimer->read(ptimer); - -		NV_INFO(drm, "setting performance level: %d", perflvl->id); -		ret = nouveau_pm_perflvl_set(dev, perflvl); -		if (ret) -			NV_INFO(drm, "> reclocking failed: %d\n\n", ret); - -		NV_INFO(drm, "> reclocking took %lluns\n\n", -			     ptimer->read(ptimer) - time0); -	} -} - -static struct nouveau_pm_profile * -profile_find(struct drm_device *dev, const char *string) -{ -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_profile *profile; - -	list_for_each_entry(profile, &pm->profiles, head) { -		if (!strncmp(profile->name, string, sizeof(profile->name))) -			return profile; -	} - -	return NULL; -} - -static int -nouveau_pm_profile_set(struct drm_device *dev, const char *profile) -{ -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_profile *ac = NULL, *dc = NULL; -	char string[16], *cur = string, *ptr; - -	/* safety precaution, for now */ -	if (nouveau_perflvl_wr != 7777) -		return -EPERM; - -	strncpy(string, profile, sizeof(string)); -	string[sizeof(string) - 1] = 0; -	if ((ptr = strchr(string, '\n'))) -		*ptr = '\0'; - -	ptr = strsep(&cur, ","); -	if (ptr) -		ac = profile_find(dev, ptr); - -	ptr = strsep(&cur, ","); -	if (ptr) -		dc = profile_find(dev, ptr); -	else -		dc = ac; - -	if (ac == NULL || dc == NULL) -		return -EINVAL; - -	pm->profile_ac = ac; -	pm->profile_dc = dc; -	nouveau_pm_trigger(dev); -	return 0; -} - -static void -nouveau_pm_static_dummy(struct nouveau_pm_profile *profile) -{ -} - -static struct nouveau_pm_level * -nouveau_pm_static_select(struct nouveau_pm_profile *profile) -{ -	return container_of(profile, struct nouveau_pm_level, profile); -} - -const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = { -	.destroy = nouveau_pm_static_dummy, -	.init = nouveau_pm_static_dummy, -	.fini = nouveau_pm_static_dummy, -	.select = nouveau_pm_static_select, -}; - -static int -nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_therm *therm = nouveau_therm(drm->device); -	int ret; - -	memset(perflvl, 0, sizeof(*perflvl)); - -	if (pm->clocks_get) { -		ret = pm->clocks_get(dev, perflvl); -		if (ret) -			return ret; -	} - -	if (pm->voltage.supported && pm->voltage_get) { -		ret = pm->voltage_get(dev); -		if (ret > 0) { -			perflvl->volt_min = ret; -			perflvl->volt_max = ret; -		} -	} - -	if (therm && therm->fan_get) { -		ret = therm->fan_get(therm); -		if (ret >= 0) -			perflvl->fanspeed = ret; -	} - -	nouveau_mem_timing_read(dev, &perflvl->timing); -	return 0; -} - -static void -nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) -{ -	char c[16], s[16], v[32], f[16], m[16]; - -	c[0] = '\0'; -	if (perflvl->core) -		snprintf(c, sizeof(c), " core %dMHz", perflvl->core / 1000); - -	s[0] = '\0'; -	if (perflvl->shader) -		snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); - -	m[0] = '\0'; -	if (perflvl->memory) -		snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000); - -	v[0] = '\0'; -	if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) { -		snprintf(v, sizeof(v), " voltage %dmV-%dmV", -			 perflvl->volt_min / 1000, perflvl->volt_max / 1000); -	} else -	if (perflvl->volt_min) { -		snprintf(v, sizeof(v), " voltage %dmV", -			 perflvl->volt_min / 1000); -	} - -	f[0] = '\0'; -	if (perflvl->fanspeed) -		snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed); - -	snprintf(ptr, len, "%s%s%s%s%s\n", c, s, m, v, f); -} - -static ssize_t -nouveau_pm_get_perflvl_info(struct device *d, -			    struct device_attribute *a, char *buf) -{ -	struct nouveau_pm_level *perflvl = -		container_of(a, struct nouveau_pm_level, dev_attr); -	char *ptr = buf; -	int len = PAGE_SIZE; - -	snprintf(ptr, len, "%d:", perflvl->id); -	ptr += strlen(buf); -	len -= strlen(buf); - -	nouveau_pm_perflvl_info(perflvl, ptr, len); -	return strlen(buf); -} - -static ssize_t -nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) -{ -	struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_level cur; -	int len = PAGE_SIZE, ret; -	char *ptr = buf; - -	snprintf(ptr, len, "profile: %s, %s\nc:", -		 pm->profile_ac->name, pm->profile_dc->name); -	ptr += strlen(buf); -	len -= strlen(buf); - -	ret = nouveau_pm_perflvl_get(dev, &cur); -	if (ret == 0) -		nouveau_pm_perflvl_info(&cur, ptr, len); -	return strlen(buf); -} - -static ssize_t -nouveau_pm_set_perflvl(struct device *d, struct device_attribute *a, -		       const char *buf, size_t count) -{ -	struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); -	int ret; - -	ret = nouveau_pm_profile_set(dev, buf); -	if (ret) -		return ret; -	return strlen(buf); -} - -static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR, -		   nouveau_pm_get_perflvl, nouveau_pm_set_perflvl); - -static int -nouveau_sysfs_init(struct drm_device *dev) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct device *d = &dev->pdev->dev; -	int ret, i; - -	ret = device_create_file(d, &dev_attr_performance_level); -	if (ret) -		return ret; - -	for (i = 0; i < pm->nr_perflvl; i++) { -		struct nouveau_pm_level *perflvl = &pm->perflvl[i]; - -		perflvl->dev_attr.attr.name = perflvl->name; -		perflvl->dev_attr.attr.mode = S_IRUGO; -		perflvl->dev_attr.show = nouveau_pm_get_perflvl_info; -		perflvl->dev_attr.store = NULL; -		sysfs_attr_init(&perflvl->dev_attr.attr); - -		ret = device_create_file(d, &perflvl->dev_attr); -		if (ret) { -			NV_ERROR(drm, "failed pervlvl %d sysfs: %d\n", -				 perflvl->id, i); -			perflvl->dev_attr.attr.name = NULL; -			nouveau_pm_fini(dev); -			return ret; -		} -	} - -	return 0; -} - -static void -nouveau_sysfs_fini(struct drm_device *dev) -{ -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct device *d = &dev->pdev->dev; -	int i; - -	device_remove_file(d, &dev_attr_performance_level); -	for (i = 0; i < pm->nr_perflvl; i++) { -		struct nouveau_pm_level *pl = &pm->perflvl[i]; - -		if (!pl->dev_attr.attr.name) -			break; - -		device_remove_file(d, &pl->dev_attr); -	} -} -  #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))  static ssize_t  nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) @@ -740,8 +383,9 @@ nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,  	long value;  	int ret; -	if (strict_strtol(buf, 10, &value) == -EINVAL) -		return -EINVAL; +	ret = kstrtol(buf, 10, &value); +	if (ret) +		return ret;  	ret = therm->attr_set(therm, NOUVEAU_THERM_ATTR_FAN_MODE, value);  	if (ret) @@ -778,9 +422,6 @@ nouveau_hwmon_set_pwm1(struct device *d, struct device_attribute *a,  	int ret = -ENODEV;  	long value; -	if (nouveau_perflvl_wr != 7777) -		return -EPERM; -  	if (kstrtol(buf, 10, &value) == -EINVAL)  		return -EINVAL; @@ -919,17 +560,21 @@ static const struct attribute_group hwmon_pwm_fan_attrgroup = {  };  #endif -static int +int  nouveau_hwmon_init(struct drm_device *dev)  { -	struct nouveau_pm *pm = nouveau_pm(dev); -  #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_therm *therm = nouveau_therm(drm->device); +	struct nouveau_hwmon *hwmon;  	struct device *hwmon_dev;  	int ret = 0; +	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL); +	if (!hwmon) +		return -ENOMEM; +	hwmon->dev = dev; +  	if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set)  		return -ENODEV; @@ -943,18 +588,14 @@ nouveau_hwmon_init(struct drm_device *dev)  	/* set the default attributes */  	ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup); -	if (ret) { -		if (ret) -			goto error; -	} +	if (ret) +		goto error;  	/* if the card has a working thermal sensor */  	if (therm->temp_get(therm) >= 0) {  		ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup); -		if (ret) { -			if (ret) -				goto error; -		} +		if (ret) +			goto error;  	}  	/* if the card has a pwm fan */ @@ -976,199 +617,36 @@ nouveau_hwmon_init(struct drm_device *dev)  			goto error;  	} -	pm->hwmon = hwmon_dev; +	hwmon->hwmon = hwmon_dev;  	return 0;  error:  	NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);  	hwmon_device_unregister(hwmon_dev); -	pm->hwmon = NULL; +	hwmon->hwmon = NULL;  	return ret;  #else -	pm->hwmon = NULL;  	return 0;  #endif  } -static void +void  nouveau_hwmon_fini(struct drm_device *dev)  {  #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) -	struct nouveau_pm *pm = nouveau_pm(dev); - -	if (pm->hwmon) { -		sysfs_remove_group(&pm->hwmon->kobj, &hwmon_default_attrgroup); -		sysfs_remove_group(&pm->hwmon->kobj, &hwmon_temp_attrgroup); -		sysfs_remove_group(&pm->hwmon->kobj, &hwmon_pwm_fan_attrgroup); -		sysfs_remove_group(&pm->hwmon->kobj, &hwmon_fan_rpm_attrgroup); +	struct nouveau_hwmon *hwmon = nouveau_hwmon(dev); -		hwmon_device_unregister(pm->hwmon); -	} -#endif -} - -#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) -static int -nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) -{ -	struct nouveau_pm *pm = container_of(nb, struct nouveau_pm, acpi_nb); -	struct nouveau_drm *drm = nouveau_drm(pm->dev); -	struct acpi_bus_event *entry = (struct acpi_bus_event *)data; - -	if (strcmp(entry->device_class, "ac_adapter") == 0) { -		bool ac = power_supply_is_system_supplied(); - -		NV_DEBUG(drm, "power supply changed: %s\n", ac ? "AC" : "DC"); -		nouveau_pm_trigger(pm->dev); -	} - -	return NOTIFY_OK; -} -#endif - -int -nouveau_pm_init(struct drm_device *dev) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_pm *pm; -	char info[256]; -	int ret, i; - -	pm = drm->pm = kzalloc(sizeof(*pm), GFP_KERNEL); -	if (!pm) -		return -ENOMEM; - -	pm->dev = dev; - -	if (device->card_type < NV_40) { -		pm->clocks_get = nv04_pm_clocks_get; -		pm->clocks_pre = nv04_pm_clocks_pre; -		pm->clocks_set = nv04_pm_clocks_set; -		if (nouveau_gpio(drm->device)) { -			pm->voltage_get = nouveau_voltage_gpio_get; -			pm->voltage_set = nouveau_voltage_gpio_set; -		} -	} else -	if (device->card_type < NV_50) { -		pm->clocks_get = nv40_pm_clocks_get; -		pm->clocks_pre = nv40_pm_clocks_pre; -		pm->clocks_set = nv40_pm_clocks_set; -		pm->voltage_get = nouveau_voltage_gpio_get; -		pm->voltage_set = nouveau_voltage_gpio_set; -	} else -	if (device->card_type < NV_C0) { -		if (device->chipset <  0xa3 || -		    device->chipset == 0xaa || -		    device->chipset == 0xac) { -			pm->clocks_get = nv50_pm_clocks_get; -			pm->clocks_pre = nv50_pm_clocks_pre; -			pm->clocks_set = nv50_pm_clocks_set; -		} else { -			pm->clocks_get = nva3_pm_clocks_get; -			pm->clocks_pre = nva3_pm_clocks_pre; -			pm->clocks_set = nva3_pm_clocks_set; -		} -		pm->voltage_get = nouveau_voltage_gpio_get; -		pm->voltage_set = nouveau_voltage_gpio_set; -	} else -	if (device->card_type < NV_E0) { -		pm->clocks_get = nvc0_pm_clocks_get; -		pm->clocks_pre = nvc0_pm_clocks_pre; -		pm->clocks_set = nvc0_pm_clocks_set; -		pm->voltage_get = nouveau_voltage_gpio_get; -		pm->voltage_set = nouveau_voltage_gpio_set; -	} - - -	/* parse aux tables from vbios */ -	nouveau_volt_init(dev); - -	INIT_LIST_HEAD(&pm->profiles); - -	/* determine current ("boot") performance level */ -	ret = nouveau_pm_perflvl_get(dev, &pm->boot); -	if (ret) { -		NV_ERROR(drm, "failed to determine boot perflvl\n"); -		return ret; -	} +	if (hwmon->hwmon) { +		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_default_attrgroup); +		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_temp_attrgroup); +		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_pwm_fan_attrgroup); +		sysfs_remove_group(&hwmon->hwmon->kobj, &hwmon_fan_rpm_attrgroup); -	strncpy(pm->boot.name, "boot", 4); -	strncpy(pm->boot.profile.name, "boot", 4); -	pm->boot.profile.func = &nouveau_pm_static_profile_func; - -	list_add(&pm->boot.profile.head, &pm->profiles); - -	pm->profile_ac = &pm->boot.profile; -	pm->profile_dc = &pm->boot.profile; -	pm->profile = &pm->boot.profile; -	pm->cur = &pm->boot; - -	/* add performance levels from vbios */ -	nouveau_perf_init(dev); - -	/* display available performance levels */ -	NV_INFO(drm, "%d available performance level(s)\n", pm->nr_perflvl); -	for (i = 0; i < pm->nr_perflvl; i++) { -		nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); -		NV_INFO(drm, "%d:%s", pm->perflvl[i].id, info); +		hwmon_device_unregister(hwmon->hwmon);  	} -	nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); -	NV_INFO(drm, "c:%s", info); - -	/* switch performance levels now if requested */ -	if (nouveau_perflvl != NULL) -		nouveau_pm_profile_set(dev, nouveau_perflvl); - -	nouveau_sysfs_init(dev); -	nouveau_hwmon_init(dev); -#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) -	pm->acpi_nb.notifier_call = nouveau_pm_acpi_event; -	register_acpi_notifier(&pm->acpi_nb); +	nouveau_drm(dev)->hwmon = NULL; +	kfree(hwmon);  #endif - -	return 0; -} - -void -nouveau_pm_fini(struct drm_device *dev) -{ -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_profile *profile, *tmp; - -	list_for_each_entry_safe(profile, tmp, &pm->profiles, head) { -		list_del(&profile->head); -		profile->func->destroy(profile); -	} - -	if (pm->cur != &pm->boot) -		nouveau_pm_perflvl_set(dev, &pm->boot); - -	nouveau_perf_fini(dev); -	nouveau_volt_fini(dev); - -#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) -	unregister_acpi_notifier(&pm->acpi_nb); -#endif -	nouveau_hwmon_fini(dev); -	nouveau_sysfs_fini(dev); - -	nouveau_drm(dev)->pm = NULL; -	kfree(pm); -} - -void -nouveau_pm_resume(struct drm_device *dev) -{ -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_level *perflvl; - -	if (!pm->cur || pm->cur == &pm->boot) -		return; - -	perflvl = pm->cur; -	pm->cur = &pm->boot; -	nouveau_pm_perflvl_set(dev, perflvl);  } diff --git a/drivers/gpu/drm/nouveau/nouveau_hwmon.h b/drivers/gpu/drm/nouveau/nouveau_hwmon.h new file mode 100644 index 00000000000..62ccbb39863 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_hwmon.h @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifndef __NOUVEAU_PM_H__ +#define __NOUVEAU_PM_H__ + +struct nouveau_hwmon { +	struct drm_device *dev; +	struct device *hwmon; +}; + +static inline struct nouveau_hwmon * +nouveau_hwmon(struct drm_device *dev) +{ +	return nouveau_drm(dev)->hwmon; +} + +/* nouveau_hwmon.c */ +int  nouveau_hwmon_init(struct drm_device *dev); +void nouveau_hwmon_fini(struct drm_device *dev); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_hwsq.h b/drivers/gpu/drm/nouveau/nouveau_hwsq.h deleted file mode 100644 index 697687593a8..00000000000 --- a/drivers/gpu/drm/nouveau/nouveau_hwsq.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#ifndef __NOUVEAU_HWSQ_H__ -#define __NOUVEAU_HWSQ_H__ - -struct hwsq_ucode { -	u8 data[0x200]; -	union { -		u8  *u08; -		u16 *u16; -		u32 *u32; -	} ptr; -	u16 len; - -	u32 reg; -	u32 val; -}; - -static inline void -hwsq_init(struct hwsq_ucode *hwsq) -{ -	hwsq->ptr.u08 = hwsq->data; -	hwsq->reg = 0xffffffff; -	hwsq->val = 0xffffffff; -} - -static inline void -hwsq_fini(struct hwsq_ucode *hwsq) -{ -	do { -		*hwsq->ptr.u08++ = 0x7f; -		hwsq->len = hwsq->ptr.u08 - hwsq->data; -	} while (hwsq->len & 3); -	hwsq->ptr.u08 = hwsq->data; -} - -static inline void -hwsq_usec(struct hwsq_ucode *hwsq, u8 usec) -{ -	u32 shift = 0; -	while (usec & ~3) { -		usec >>= 2; -		shift++; -	} - -	*hwsq->ptr.u08++ = (shift << 2) | usec; -} - -static inline void -hwsq_setf(struct hwsq_ucode *hwsq, u8 flag, int val) -{ -	flag += 0x80; -	if (val >= 0) -		flag += 0x20; -	if (val >= 1) -		flag += 0x20; -	*hwsq->ptr.u08++ = flag; -} - -static inline void -hwsq_op5f(struct hwsq_ucode *hwsq, u8 v0, u8 v1) -{ -	*hwsq->ptr.u08++ = 0x5f; -	*hwsq->ptr.u08++ = v0; -	*hwsq->ptr.u08++ = v1; -} - -static inline void -hwsq_wr32(struct hwsq_ucode *hwsq, u32 reg, u32 val) -{ -	if (val != hwsq->val) { -		if ((val & 0xffff0000) == (hwsq->val & 0xffff0000)) { -			*hwsq->ptr.u08++ = 0x42; -			*hwsq->ptr.u16++ = (val & 0x0000ffff); -		} else { -			*hwsq->ptr.u08++ = 0xe2; -			*hwsq->ptr.u32++ = val; -		} - -		hwsq->val = val; -	} - -	if ((reg & 0xffff0000) == (hwsq->reg & 0xffff0000)) { -		*hwsq->ptr.u08++ = 0x40; -		*hwsq->ptr.u16++ = (reg & 0x0000ffff); -	} else { -		*hwsq->ptr.u08++ = 0xe0; -		*hwsq->ptr.u32++ = reg; -	} -	hwsq->reg = reg; -} - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_ioc32.c b/drivers/gpu/drm/nouveau/nouveau_ioc32.c index c1a7e5a73a2..462679a8fec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ioc32.c +++ b/drivers/gpu/drm/nouveau/nouveau_ioc32.c @@ -57,7 +57,7 @@ long nouveau_compat_ioctl(struct file *filp, unsigned int cmd,  		return drm_compat_ioctl(filp, cmd, arg);  #if 0 -	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) +	if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls))  		fn = nouveau_compat_ioctls[nr - DRM_COMMAND_BASE];  #endif  	if (fn != NULL) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c deleted file mode 100644 index 4f6a572f225..00000000000 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved. - * Copyright 2005 Stephane Marchesin - * - * The Weather Channel (TM) funded Tungsten Graphics to develop the - * initial release of the Radeon 8500 driver under the XFree86 license. - * This notice must be preserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *    Ben Skeggs <bskeggs@redhat.com> - *    Roy Spliet <r.spliet@student.tudelft.nl> - */ - -#include "nouveau_drm.h" -#include "nouveau_pm.h" - -#include <subdev/fb.h> - -static int -nv40_mem_timing_calc(struct drm_device *dev, u32 freq, -		     struct nouveau_pm_tbl_entry *e, u8 len, -		     struct nouveau_pm_memtiming *boot, -		     struct nouveau_pm_memtiming *t) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); - -	t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); - -	/* XXX: I don't trust the -1's and +1's... they must come -	 *      from somewhere! */ -	t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 | -		    1 << 16 | -		    (e->tWTR + 2 + (t->tCWL - 1)) << 8 | -		    (e->tCL + 2 - (t->tCWL - 1)); - -	t->reg[2] = 0x20200000 | -		    ((t->tCWL - 1) << 24 | -		     e->tRRD << 16 | -		     e->tRCDWR << 8 | -		     e->tRCDRD); - -	NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x\n", t->id, -		 t->reg[0], t->reg[1], t->reg[2]); -	return 0; -} - -static int -nv50_mem_timing_calc(struct drm_device *dev, u32 freq, -		     struct nouveau_pm_tbl_entry *e, u8 len, -		     struct nouveau_pm_memtiming *boot, -		     struct nouveau_pm_memtiming *t) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct bit_entry P; -	uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; - -	if (bit_table(dev, 'P', &P)) -		return -EINVAL; - -	switch (min(len, (u8) 22)) { -	case 22: -		unk21 = e->tUNK_21; -	case 21: -		unk20 = e->tUNK_20; -	case 20: -		if (e->tCWL > 0) -			t->tCWL = e->tCWL; -	case 19: -		unk18 = e->tUNK_18; -		break; -	} - -	t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); - -	t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 | -				max(unk18, (u8) 1) << 16 | -				(e->tWTR + 2 + (t->tCWL - 1)) << 8; - -	t->reg[2] = ((t->tCWL - 1) << 24 | -		    e->tRRD << 16 | -		    e->tRCDWR << 8 | -		    e->tRCDRD); - -	t->reg[4] = e->tUNK_13 << 8  | e->tUNK_13; - -	t->reg[5] = (e->tRFC << 24 | max(e->tRCDRD, e->tRCDWR) << 16 | e->tRP); - -	t->reg[8] = boot->reg[8] & 0xffffff00; - -	if (P.version == 1) { -		t->reg[1] |= (e->tCL + 2 - (t->tCWL - 1)); - -		t->reg[3] = (0x14 + e->tCL) << 24 | -			    0x16 << 16 | -			    (e->tCL - 1) << 8 | -			    (e->tCL - 1); - -		t->reg[4] |= boot->reg[4] & 0xffff0000; - -		t->reg[6] = (0x33 - t->tCWL) << 16 | -			    t->tCWL << 8 | -			    (0x2e + e->tCL - t->tCWL); - -		t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; - -		/* XXX: P.version == 1 only has DDR2 and GDDR3? */ -		if (pfb->ram->type == NV_MEM_TYPE_DDR2) { -			t->reg[5] |= (e->tCL + 3) << 8; -			t->reg[6] |= (t->tCWL - 2) << 8; -			t->reg[8] |= (e->tCL - 4); -		} else { -			t->reg[5] |= (e->tCL + 2) << 8; -			t->reg[6] |= t->tCWL << 8; -			t->reg[8] |= (e->tCL - 2); -		} -	} else { -		t->reg[1] |= (5 + e->tCL - (t->tCWL)); - -		/* XXX: 0xb? 0x30? */ -		t->reg[3] = (0x30 + e->tCL) << 24 | -			    (boot->reg[3] & 0x00ff0000)| -			    (0xb + e->tCL) << 8 | -			    (e->tCL - 1); - -		t->reg[4] |= (unk20 << 24 | unk21 << 16); - -		/* XXX: +6? */ -		t->reg[5] |= (t->tCWL + 6) << 8; - -		t->reg[6] = (0x5a + e->tCL) << 16 | -			    (6 - e->tCL + t->tCWL) << 8 | -			    (0x50 + e->tCL - t->tCWL); - -		tmp7_3 = (boot->reg[7] & 0xff000000) >> 24; -		t->reg[7] = (tmp7_3 << 24) | -			    ((tmp7_3 - 6 + e->tCL) << 16) | -			    0x202; -	} - -	NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x %08x\n", t->id, -		 t->reg[0], t->reg[1], t->reg[2], t->reg[3]); -	NV_DEBUG(drm, "         230: %08x %08x %08x %08x\n", -		 t->reg[4], t->reg[5], t->reg[6], t->reg[7]); -	NV_DEBUG(drm, "         240: %08x\n", t->reg[8]); -	return 0; -} - -static int -nvc0_mem_timing_calc(struct drm_device *dev, u32 freq, -		     struct nouveau_pm_tbl_entry *e, u8 len, -		     struct nouveau_pm_memtiming *boot, -		     struct nouveau_pm_memtiming *t) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); - -	if (e->tCWL > 0) -		t->tCWL = e->tCWL; - -	t->reg[0] = (e->tRP << 24 | (e->tRAS & 0x7f) << 17 | -		     e->tRFC << 8 | e->tRC); - -	t->reg[1] = (boot->reg[1] & 0xff000000) | -		    (e->tRCDWR & 0x0f) << 20 | -		    (e->tRCDRD & 0x0f) << 14 | -		    (t->tCWL << 7) | -		    (e->tCL & 0x0f); - -	t->reg[2] = (boot->reg[2] & 0xff0000ff) | -		    e->tWR << 16 | e->tWTR << 8; - -	t->reg[3] = (e->tUNK_20 & 0x1f) << 9 | -		    (e->tUNK_21 & 0xf) << 5 | -		    (e->tUNK_13 & 0x1f); - -	t->reg[4] = (boot->reg[4] & 0xfff00fff) | -		    (e->tRRD&0x1f) << 15; - -	NV_DEBUG(drm, "Entry %d: 290: %08x %08x %08x %08x\n", t->id, -		 t->reg[0], t->reg[1], t->reg[2], t->reg[3]); -	NV_DEBUG(drm, "         2a0: %08x\n", t->reg[4]); -	return 0; -} - -/** - * MR generation methods - */ - -static int -nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, -		    struct nouveau_pm_tbl_entry *e, u8 len, -		    struct nouveau_pm_memtiming *boot, -		    struct nouveau_pm_memtiming *t) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); - -	t->drive_strength = 0; -	if (len < 15) { -		t->odt = boot->odt; -	} else { -		t->odt = e->RAM_FT1 & 0x07; -	} - -	if (e->tCL >= NV_MEM_CL_DDR2_MAX) { -		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); -		return -ERANGE; -	} - -	if (e->tWR >= NV_MEM_WR_DDR2_MAX) { -		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); -		return -ERANGE; -	} - -	if (t->odt > 3) { -		NV_WARN(drm, "(%u) Invalid odt value, assuming disabled: %x", -			t->id, t->odt); -		t->odt = 0; -	} - -	t->mr[0] = (boot->mr[0] & 0x100f) | -		   (e->tCL) << 4 | -		   (e->tWR - 1) << 9; -	t->mr[1] = (boot->mr[1] & 0x101fbb) | -		   (t->odt & 0x1) << 2 | -		   (t->odt & 0x2) << 5; - -	NV_DEBUG(drm, "(%u) MR: %08x", t->id, t->mr[0]); -	return 0; -} - -static const uint8_t nv_mem_wr_lut_ddr3[NV_MEM_WR_DDR3_MAX] = { -	0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0}; - -static int -nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, -		    struct nouveau_pm_tbl_entry *e, u8 len, -		    struct nouveau_pm_memtiming *boot, -		    struct nouveau_pm_memtiming *t) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	u8 cl = e->tCL - 4; - -	t->drive_strength = 0; -	if (len < 15) { -		t->odt = boot->odt; -	} else { -		t->odt = e->RAM_FT1 & 0x07; -	} - -	if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) { -		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); -		return -ERANGE; -	} - -	if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) { -		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); -		return -ERANGE; -	} - -	if (e->tCWL < 5) { -		NV_WARN(drm, "(%u) Invalid tCWL: %u", t->id, e->tCWL); -		return -ERANGE; -	} - -	t->mr[0] = (boot->mr[0] & 0x180b) | -		   /* CAS */ -		   (cl & 0x7) << 4 | -		   (cl & 0x8) >> 1 | -		   (nv_mem_wr_lut_ddr3[e->tWR]) << 9; -	t->mr[1] = (boot->mr[1] & 0x101dbb) | -		   (t->odt & 0x1) << 2 | -		   (t->odt & 0x2) << 5 | -		   (t->odt & 0x4) << 7; -	t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3; - -	NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]); -	return 0; -} - -static const uint8_t nv_mem_cl_lut_gddr3[NV_MEM_CL_GDDR3_MAX] = { -	0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11}; -static const uint8_t nv_mem_wr_lut_gddr3[NV_MEM_WR_GDDR3_MAX] = { -	0, 0, 0, 0, 0, 2, 3, 8, 9, 10, 11, 0, 0, 1, 1, 0, 3}; - -static int -nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, -		     struct nouveau_pm_tbl_entry *e, u8 len, -		     struct nouveau_pm_memtiming *boot, -		     struct nouveau_pm_memtiming *t) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); - -	if (len < 15) { -		t->drive_strength = boot->drive_strength; -		t->odt = boot->odt; -	} else { -		t->drive_strength = (e->RAM_FT1 & 0x30) >> 4; -		t->odt = e->RAM_FT1 & 0x07; -	} - -	if (e->tCL >= NV_MEM_CL_GDDR3_MAX) { -		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); -		return -ERANGE; -	} - -	if (e->tWR >= NV_MEM_WR_GDDR3_MAX) { -		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); -		return -ERANGE; -	} - -	if (t->odt > 3) { -		NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x", -			t->id, t->odt); -		t->odt = 0; -	} - -	t->mr[0] = (boot->mr[0] & 0xe0b) | -		   /* CAS */ -		   ((nv_mem_cl_lut_gddr3[e->tCL] & 0x7) << 4) | -		   ((nv_mem_cl_lut_gddr3[e->tCL] & 0x8) >> 2); -	t->mr[1] = (boot->mr[1] & 0x100f40) | t->drive_strength | -		   (t->odt << 2) | -		   (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4; -	t->mr[2] = boot->mr[2]; - -	NV_DEBUG(drm, "(%u) MR: %08x %08x %08x", t->id, -		      t->mr[0], t->mr[1], t->mr[2]); -	return 0; -} - -static int -nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, -		     struct nouveau_pm_tbl_entry *e, u8 len, -		     struct nouveau_pm_memtiming *boot, -		     struct nouveau_pm_memtiming *t) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); - -	if (len < 15) { -		t->drive_strength = boot->drive_strength; -		t->odt = boot->odt; -	} else { -		t->drive_strength = (e->RAM_FT1 & 0x30) >> 4; -		t->odt = e->RAM_FT1 & 0x03; -	} - -	if (e->tCL >= NV_MEM_CL_GDDR5_MAX) { -		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); -		return -ERANGE; -	} - -	if (e->tWR >= NV_MEM_WR_GDDR5_MAX) { -		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); -		return -ERANGE; -	} - -	if (t->odt > 3) { -		NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x", -			t->id, t->odt); -		t->odt = 0; -	} - -	t->mr[0] = (boot->mr[0] & 0x007) | -		   ((e->tCL - 5) << 3) | -		   ((e->tWR - 4) << 8); -	t->mr[1] = (boot->mr[1] & 0x1007f0) | -		   t->drive_strength | -		   (t->odt << 2); - -	NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]); -	return 0; -} - -int -nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, -			struct nouveau_pm_memtiming *t) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_memtiming *boot = &pm->boot.timing; -	struct nouveau_pm_tbl_entry *e; -	u8 ver, len, *ptr, *ramcfg; -	int ret; - -	ptr = nouveau_perf_timing(dev, freq, &ver, &len); -	if (!ptr || ptr[0] == 0x00) { -		*t = *boot; -		return 0; -	} -	e = (struct nouveau_pm_tbl_entry *)ptr; - -	t->tCWL = boot->tCWL; - -	switch (device->card_type) { -	case NV_40: -		ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t); -		break; -	case NV_50: -		ret = nv50_mem_timing_calc(dev, freq, e, len, boot, t); -		break; -	case NV_C0: -	case NV_D0: -		ret = nvc0_mem_timing_calc(dev, freq, e, len, boot, t); -		break; -	default: -		ret = -ENODEV; -		break; -	} - -	switch (pfb->ram->type * !ret) { -	case NV_MEM_TYPE_GDDR3: -		ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); -		break; -	case NV_MEM_TYPE_GDDR5: -		ret = nouveau_mem_gddr5_mr(dev, freq, e, len, boot, t); -		break; -	case NV_MEM_TYPE_DDR2: -		ret = nouveau_mem_ddr2_mr(dev, freq, e, len, boot, t); -		break; -	case NV_MEM_TYPE_DDR3: -		ret = nouveau_mem_ddr3_mr(dev, freq, e, len, boot, t); -		break; -	default: -		ret = -EINVAL; -		break; -	} - -	ramcfg = nouveau_perf_ramcfg(dev, freq, &ver, &len); -	if (ramcfg) { -		int dll_off; - -		if (ver == 0x00) -			dll_off = !!(ramcfg[3] & 0x04); -		else -			dll_off = !!(ramcfg[2] & 0x40); - -		switch (pfb->ram->type) { -		case NV_MEM_TYPE_GDDR3: -			t->mr[1] &= ~0x00000040; -			t->mr[1] |=  0x00000040 * dll_off; -			break; -		default: -			t->mr[1] &= ~0x00000001; -			t->mr[1] |=  0x00000001 * dll_off; -			break; -		} -	} - -	return ret; -} - -void -nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	u32 timing_base, timing_regs, mr_base; -	int i; - -	if (device->card_type >= 0xC0) { -		timing_base = 0x10f290; -		mr_base = 0x10f300; -	} else { -		timing_base = 0x100220; -		mr_base = 0x1002c0; -	} - -	t->id = -1; - -	switch (device->card_type) { -	case NV_50: -		timing_regs = 9; -		break; -	case NV_C0: -	case NV_D0: -		timing_regs = 5; -		break; -	case NV_30: -	case NV_40: -		timing_regs = 3; -		break; -	default: -		timing_regs = 0; -		return; -	} -	for(i = 0; i < timing_regs; i++) -		t->reg[i] = nv_rd32(device, timing_base + (0x04 * i)); - -	t->tCWL = 0; -	if (device->card_type < NV_C0) { -		t->tCWL = ((nv_rd32(device, 0x100228) & 0x0f000000) >> 24) + 1; -	} else if (device->card_type <= NV_D0) { -		t->tCWL = ((nv_rd32(device, 0x10f294) & 0x00000f80) >> 7); -	} - -	t->mr[0] = nv_rd32(device, mr_base); -	t->mr[1] = nv_rd32(device, mr_base + 0x04); -	t->mr[2] = nv_rd32(device, mr_base + 0x20); -	t->mr[3] = nv_rd32(device, mr_base + 0x24); - -	t->odt = 0; -	t->drive_strength = 0; - -	switch (pfb->ram->type) { -	case NV_MEM_TYPE_DDR3: -		t->odt |= (t->mr[1] & 0x200) >> 7; -	case NV_MEM_TYPE_DDR2: -		t->odt |= (t->mr[1] & 0x04) >> 2 | -			  (t->mr[1] & 0x40) >> 5; -		break; -	case NV_MEM_TYPE_GDDR3: -	case NV_MEM_TYPE_GDDR5: -		t->drive_strength = t->mr[1] & 0x03; -		t->odt = (t->mr[1] & 0x0c) >> 2; -		break; -	default: -		break; -	} -} - -int -nouveau_mem_exec(struct nouveau_mem_exec_func *exec, -		 struct nouveau_pm_level *perflvl) -{ -	struct nouveau_drm *drm = nouveau_drm(exec->dev); -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	struct nouveau_pm_memtiming *info = &perflvl->timing; -	u32 tMRD = 1000, tCKSRE = 0, tCKSRX = 0, tXS = 0, tDLLK = 0; -	u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; -	u32 mr1_dlloff; - -	switch (pfb->ram->type) { -	case NV_MEM_TYPE_DDR2: -		tDLLK = 2000; -		mr1_dlloff = 0x00000001; -		break; -	case NV_MEM_TYPE_DDR3: -		tDLLK = 12000; -		tCKSRE = 2000; -		tXS = 1000; -		mr1_dlloff = 0x00000001; -		break; -	case NV_MEM_TYPE_GDDR3: -		tDLLK = 40000; -		mr1_dlloff = 0x00000040; -		break; -	default: -		NV_ERROR(drm, "cannot reclock unsupported memtype\n"); -		return -ENODEV; -	} - -	/* fetch current MRs */ -	switch (pfb->ram->type) { -	case NV_MEM_TYPE_GDDR3: -	case NV_MEM_TYPE_DDR3: -		mr[2] = exec->mrg(exec, 2); -	default: -		mr[1] = exec->mrg(exec, 1); -		mr[0] = exec->mrg(exec, 0); -		break; -	} - -	/* DLL 'on' -> DLL 'off' mode, disable before entering self-refresh  */ -	if (!(mr[1] & mr1_dlloff) && (info->mr[1] & mr1_dlloff)) { -		exec->precharge(exec); -		exec->mrs (exec, 1, mr[1] | mr1_dlloff); -		exec->wait(exec, tMRD); -	} - -	/* enter self-refresh mode */ -	exec->precharge(exec); -	exec->refresh(exec); -	exec->refresh(exec); -	exec->refresh_auto(exec, false); -	exec->refresh_self(exec, true); -	exec->wait(exec, tCKSRE); - -	/* modify input clock frequency */ -	exec->clock_set(exec); - -	/* exit self-refresh mode */ -	exec->wait(exec, tCKSRX); -	exec->precharge(exec); -	exec->refresh_self(exec, false); -	exec->refresh_auto(exec, true); -	exec->wait(exec, tXS); -	exec->wait(exec, tXS); - -	/* update MRs */ -	if (mr[2] != info->mr[2]) { -		exec->mrs (exec, 2, info->mr[2]); -		exec->wait(exec, tMRD); -	} - -	if (mr[1] != info->mr[1]) { -		/* need to keep DLL off until later, at least on GDDR3 */ -		exec->mrs (exec, 1, info->mr[1] | (mr[1] & mr1_dlloff)); -		exec->wait(exec, tMRD); -	} - -	if (mr[0] != info->mr[0]) { -		exec->mrs (exec, 0, info->mr[0]); -		exec->wait(exec, tMRD); -	} - -	/* update PFB timing registers */ -	exec->timing_set(exec); - -	/* DLL (enable + ) reset */ -	if (!(info->mr[1] & mr1_dlloff)) { -		if (mr[1] & mr1_dlloff) { -			exec->mrs (exec, 1, info->mr[1]); -			exec->wait(exec, tMRD); -		} -		exec->mrs (exec, 0, info->mr[0] | 0x00000100); -		exec->wait(exec, tMRD); -		exec->mrs (exec, 0, info->mr[0] | 0x00000000); -		exec->wait(exec, tMRD); -		exec->wait(exec, tDLLK); -		if (pfb->ram->type == NV_MEM_TYPE_GDDR3) -			exec->precharge(exec); -	} - -	return 0; -} diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c deleted file mode 100644 index 4fe883c5491..00000000000 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> - -#include "nouveau_drm.h" -#include "nouveau_reg.h" -#include "nouveau_pm.h" - -static u8 * -nouveau_perf_table(struct drm_device *dev, u8 *ver) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nvbios *bios = &drm->vbios; -	struct bit_entry P; - -	if (!bit_table(dev, 'P', &P) && P.version && P.version <= 2) { -		u8 *perf = ROMPTR(dev, P.data[0]); -		if (perf) { -			*ver = perf[0]; -			return perf; -		} -	} - -	if (bios->type == NVBIOS_BMP) { -		if (bios->data[bios->offset + 6] >= 0x25) { -			u8 *perf = ROMPTR(dev, bios->data[bios->offset + 0x94]); -			if (perf) { -				*ver = perf[1]; -				return perf; -			} -		} -	} - -	return NULL; -} - -static u8 * -nouveau_perf_entry(struct drm_device *dev, int idx, -		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len) -{ -	u8 *perf = nouveau_perf_table(dev, ver); -	if (perf) { -		if (*ver >= 0x12 && *ver < 0x20 && idx < perf[2]) { -			*hdr = perf[3]; -			*cnt = 0; -			*len = 0; -			return perf + perf[0] + idx * perf[3]; -		} else -		if (*ver >= 0x20 && *ver < 0x40 && idx < perf[2]) { -			*hdr = perf[3]; -			*cnt = perf[4]; -			*len = perf[5]; -			return perf + perf[1] + idx * (*hdr + (*cnt * *len)); -		} else -		if (*ver >= 0x40 && *ver < 0x41 && idx < perf[5]) { -			*hdr = perf[2]; -			*cnt = perf[4]; -			*len = perf[3]; -			return perf + perf[1] + idx * (*hdr + (*cnt * *len)); -		} -	} -	return NULL; -} - -u8 * -nouveau_perf_rammap(struct drm_device *dev, u32 freq, -		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct bit_entry P; -	u8 *perf, i = 0; - -	if (!bit_table(dev, 'P', &P) && P.version == 2) { -		u8 *rammap = ROMPTR(dev, P.data[4]); -		if (rammap) { -			u8 *ramcfg = rammap + rammap[1]; - -			*ver = rammap[0]; -			*hdr = rammap[2]; -			*cnt = rammap[4]; -			*len = rammap[3]; - -			freq /= 1000; -			for (i = 0; i < rammap[5]; i++) { -				if (freq >= ROM16(ramcfg[0]) && -				    freq <= ROM16(ramcfg[2])) -					return ramcfg; - -				ramcfg += *hdr + (*cnt * *len); -			} -		} - -		return NULL; -	} - -	if (nv_device(drm->device)->chipset == 0x49 || -	    nv_device(drm->device)->chipset == 0x4b) -		freq /= 2; - -	while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) { -		if (*ver >= 0x20 && *ver < 0x25) { -			if (perf[0] != 0xff && freq <= ROM16(perf[11]) * 1000) -				break; -		} else -		if (*ver >= 0x25 && *ver < 0x40) { -			if (perf[0] != 0xff && freq <= ROM16(perf[12]) * 1000) -				break; -		} -	} - -	if (perf) { -		u8 *ramcfg = perf + *hdr; -		*ver = 0x00; -		*hdr = 0; -		return ramcfg; -	} - -	return NULL; -} - -u8 * -nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nvbios *bios = &drm->vbios; -	u8 strap, hdr, cnt; -	u8 *rammap; - -	strap = (nv_rd32(device, 0x101000) & 0x0000003c) >> 2; -	if (bios->ram_restrict_tbl_ptr) -		strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; - -	rammap = nouveau_perf_rammap(dev, freq, ver, &hdr, &cnt, len); -	if (rammap && strap < cnt) -		return rammap + hdr + (strap * *len); - -	return NULL; -} - -u8 * -nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nvbios *bios = &drm->vbios; -	struct bit_entry P; -	u8 *perf, *timing = NULL; -	u8 i = 0, hdr, cnt; - -	if (bios->type == NVBIOS_BMP) { -		while ((perf = nouveau_perf_entry(dev, i++, ver, &hdr, &cnt, -						  len)) && *ver == 0x15) { -			if (freq <= ROM32(perf[5]) * 20) { -				*ver = 0x00; -				*len = 14; -				return perf + 41; -			} -		} -		return NULL; -	} - -	if (!bit_table(dev, 'P', &P)) { -		if (P.version == 1) -			timing = ROMPTR(dev, P.data[4]); -		else -		if (P.version == 2) -			timing = ROMPTR(dev, P.data[8]); -	} - -	if (timing && timing[0] == 0x10) { -		u8 *ramcfg = nouveau_perf_ramcfg(dev, freq, ver, len); -		if (ramcfg && ramcfg[1] < timing[2]) { -			*ver = timing[0]; -			*len = timing[3]; -			return timing + timing[1] + (ramcfg[1] * timing[3]); -		} -	} - -	return NULL; -} - -static void -legacy_perf_init(struct drm_device *dev) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nvbios *bios = &drm->vbios; -	struct nouveau_pm *pm = nouveau_pm(dev); -	char *perf, *entry, *bmp = &bios->data[bios->offset]; -	int headerlen, use_straps; - -	if (bmp[5] < 0x5 || bmp[6] < 0x14) { -		NV_DEBUG(drm, "BMP version too old for perf\n"); -		return; -	} - -	perf = ROMPTR(dev, bmp[0x73]); -	if (!perf) { -		NV_DEBUG(drm, "No memclock table pointer found.\n"); -		return; -	} - -	switch (perf[0]) { -	case 0x12: -	case 0x14: -	case 0x18: -		use_straps = 0; -		headerlen = 1; -		break; -	case 0x01: -		use_straps = perf[1] & 1; -		headerlen = (use_straps ? 8 : 2); -		break; -	default: -		NV_WARN(drm, "Unknown memclock table version %x.\n", perf[0]); -		return; -	} - -	entry = perf + headerlen; -	if (use_straps) -		entry += (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; - -	sprintf(pm->perflvl[0].name, "performance_level_0"); -	pm->perflvl[0].memory = ROM16(entry[0]) * 20; -	pm->nr_perflvl = 1; -} - -static void -nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct bit_entry P; -	u8 *vmap; -	int id; - -	id = perflvl->volt_min; -	perflvl->volt_min = 0; - -	/* boards using voltage table version <0x40 store the voltage -	 * level directly in the perflvl entry as a multiple of 10mV -	 */ -	if (drm->pm->voltage.version < 0x40) { -		perflvl->volt_min = id * 10000; -		perflvl->volt_max = perflvl->volt_min; -		return; -	} - -	/* on newer ones, the perflvl stores an index into yet another -	 * vbios table containing a min/max voltage value for the perflvl -	 */ -	if (bit_table(dev, 'P', &P) || P.version != 2 || P.length < 34) { -		NV_DEBUG(drm, "where's our volt map table ptr? %d %d\n", -			 P.version, P.length); -		return; -	} - -	vmap = ROMPTR(dev, P.data[32]); -	if (!vmap) { -		NV_DEBUG(drm, "volt map table pointer invalid\n"); -		return; -	} - -	if (id < vmap[3]) { -		vmap += vmap[1] + (vmap[2] * id); -		perflvl->volt_min = ROM32(vmap[0]); -		perflvl->volt_max = ROM32(vmap[4]); -	} -} - -void -nouveau_perf_init(struct drm_device *dev) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nvbios *bios = &drm->vbios; -	u8 *perf, ver, hdr, cnt, len; -	int ret, vid, i = -1; - -	if (bios->type == NVBIOS_BMP && bios->data[bios->offset + 6] < 0x25) { -		legacy_perf_init(dev); -		return; -	} - -	perf = nouveau_perf_table(dev, &ver); - -	while ((perf = nouveau_perf_entry(dev, ++i, &ver, &hdr, &cnt, &len))) { -		struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; - -		if (perf[0] == 0xff) -			continue; - -		switch (ver) { -		case 0x12: -		case 0x13: -		case 0x15: -			perflvl->fanspeed = perf[55]; -			if (hdr > 56) -				perflvl->volt_min = perf[56]; -			perflvl->core = ROM32(perf[1]) * 10; -			perflvl->memory = ROM32(perf[5]) * 20; -			break; -		case 0x21: -		case 0x23: -		case 0x24: -			perflvl->fanspeed = perf[4]; -			perflvl->volt_min = perf[5]; -			perflvl->shader = ROM16(perf[6]) * 1000; -			perflvl->core = perflvl->shader; -			perflvl->core += (signed char)perf[8] * 1000; -			if (nv_device(drm->device)->chipset == 0x49 || -			    nv_device(drm->device)->chipset == 0x4b) -				perflvl->memory = ROM16(perf[11]) * 1000; -			else -				perflvl->memory = ROM16(perf[11]) * 2000; -			break; -		case 0x25: -			perflvl->fanspeed = perf[4]; -			perflvl->volt_min = perf[5]; -			perflvl->core = ROM16(perf[6]) * 1000; -			perflvl->shader = ROM16(perf[10]) * 1000; -			perflvl->memory = ROM16(perf[12]) * 1000; -			break; -		case 0x30: -			perflvl->memscript = ROM16(perf[2]); -		case 0x35: -			perflvl->fanspeed = perf[6]; -			perflvl->volt_min = perf[7]; -			perflvl->core = ROM16(perf[8]) * 1000; -			perflvl->shader = ROM16(perf[10]) * 1000; -			perflvl->memory = ROM16(perf[12]) * 1000; -			perflvl->vdec = ROM16(perf[16]) * 1000; -			perflvl->dom6 = ROM16(perf[20]) * 1000; -			break; -		case 0x40: -#define subent(n) ((ROM16(perf[hdr + (n) * len]) & 0xfff) * 1000) -			perflvl->fanspeed = 0; /*XXX*/ -			perflvl->volt_min = perf[2]; -			if (nv_device(drm->device)->card_type == NV_50) { -				perflvl->core   = subent(0); -				perflvl->shader = subent(1); -				perflvl->memory = subent(2); -				perflvl->vdec   = subent(3); -				perflvl->unka0  = subent(4); -			} else { -				perflvl->hub06  = subent(0); -				perflvl->hub01  = subent(1); -				perflvl->copy   = subent(2); -				perflvl->shader = subent(3); -				perflvl->rop    = subent(4); -				perflvl->memory = subent(5); -				perflvl->vdec   = subent(6); -				perflvl->daemon = subent(10); -				perflvl->hub07  = subent(11); -				perflvl->core   = perflvl->shader / 2; -			} -			break; -		} - -		/* make sure vid is valid */ -		nouveau_perf_voltage(dev, perflvl); -		if (pm->voltage.supported && perflvl->volt_min) { -			vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); -			if (vid < 0) { -				NV_DEBUG(drm, "perflvl %d, bad vid\n", i); -				continue; -			} -		} - -		/* get the corresponding memory timings */ -		ret = nouveau_mem_timing_calc(dev, perflvl->memory, -					          &perflvl->timing); -		if (ret) { -			NV_DEBUG(drm, "perflvl %d, bad timing: %d\n", i, ret); -			continue; -		} - -		snprintf(perflvl->name, sizeof(perflvl->name), -			 "performance_level_%d", i); -		perflvl->id = i; - -		snprintf(perflvl->profile.name, sizeof(perflvl->profile.name), -			 "%d", perflvl->id); -		perflvl->profile.func = &nouveau_pm_static_profile_func; -		list_add_tail(&perflvl->profile.head, &pm->profiles); - - -		pm->nr_perflvl++; -	} -} - -void -nouveau_perf_fini(struct drm_device *dev) -{ -} diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h deleted file mode 100644 index 73b789c230a..00000000000 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#ifndef __NOUVEAU_PM_H__ -#define __NOUVEAU_PM_H__ - -#include <subdev/bios/pll.h> -#include <subdev/clock.h> - -struct nouveau_pm_voltage_level { -	u32 voltage; /* microvolts */ -	u8  vid; -}; - -struct nouveau_pm_voltage { -	bool supported; -	u8 version; -	u8 vid_mask; - -	struct nouveau_pm_voltage_level *level; -	int nr_level; -}; - -/* Exclusive upper limits */ -#define NV_MEM_CL_DDR2_MAX 8 -#define NV_MEM_WR_DDR2_MAX 9 -#define NV_MEM_CL_DDR3_MAX 17 -#define NV_MEM_WR_DDR3_MAX 17 -#define NV_MEM_CL_GDDR3_MAX 16 -#define NV_MEM_WR_GDDR3_MAX 18 -#define NV_MEM_CL_GDDR5_MAX 21 -#define NV_MEM_WR_GDDR5_MAX 20 - -struct nouveau_pm_memtiming { -	int id; - -	u32 reg[9]; -	u32 mr[4]; - -	u8 tCWL; - -	u8 odt; -	u8 drive_strength; -}; - -struct nouveau_pm_tbl_header { -	u8 version; -	u8 header_len; -	u8 entry_cnt; -	u8 entry_len; -}; - -struct nouveau_pm_tbl_entry { -	u8 tWR; -	u8 tWTR; -	u8 tCL; -	u8 tRC; -	u8 empty_4; -	u8 tRFC;	/* Byte 5 */ -	u8 empty_6; -	u8 tRAS;	/* Byte 7 */ -	u8 empty_8; -	u8 tRP;		/* Byte 9 */ -	u8 tRCDRD; -	u8 tRCDWR; -	u8 tRRD; -	u8 tUNK_13; -	u8 RAM_FT1;		/* 14, a bitmask of random RAM features */ -	u8 empty_15; -	u8 tUNK_16; -	u8 empty_17; -	u8 tUNK_18; -	u8 tCWL; -	u8 tUNK_20, tUNK_21; -}; - -struct nouveau_pm_profile; -struct nouveau_pm_profile_func { -	void (*destroy)(struct nouveau_pm_profile *); -	void (*init)(struct nouveau_pm_profile *); -	void (*fini)(struct nouveau_pm_profile *); -	struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); -}; - -struct nouveau_pm_profile { -	const struct nouveau_pm_profile_func *func; -	struct list_head head; -	char name[8]; -}; - -#define NOUVEAU_PM_MAX_LEVEL 8 -struct nouveau_pm_level { -	struct nouveau_pm_profile profile; -	struct device_attribute dev_attr; -	char name[32]; -	int id; - -	struct nouveau_pm_memtiming timing; -	u32 memory; -	u16 memscript; - -	u32 core; -	u32 shader; -	u32 rop; -	u32 copy; -	u32 daemon; -	u32 vdec; -	u32 dom6; -	u32 unka0;	/* nva3:nvc0 */ -	u32 hub01;	/* nvc0- */ -	u32 hub06;	/* nvc0- */ -	u32 hub07;	/* nvc0- */ - -	u32 volt_min; /* microvolts */ -	u32 volt_max; -	u8  fanspeed; -}; - -struct nouveau_pm_temp_sensor_constants { -	u16 offset_constant; -	s16 offset_mult; -	s16 offset_div; -	s16 slope_mult; -	s16 slope_div; -}; - -struct nouveau_pm_threshold_temp { -	s16 critical; -	s16 down_clock; -}; - -struct nouveau_pm { -	struct drm_device *dev; - -	struct nouveau_pm_voltage voltage; -	struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; -	int nr_perflvl; -	struct nouveau_pm_temp_sensor_constants sensor_constants; -	struct nouveau_pm_threshold_temp threshold_temp; - -	struct nouveau_pm_profile *profile_ac; -	struct nouveau_pm_profile *profile_dc; -	struct nouveau_pm_profile *profile; -	struct list_head profiles; - -	struct nouveau_pm_level boot; -	struct nouveau_pm_level *cur; - -	struct device *hwmon; -	struct notifier_block acpi_nb; - -	int  (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); -	void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); -	int (*clocks_set)(struct drm_device *, void *); - -	int (*voltage_get)(struct drm_device *); -	int (*voltage_set)(struct drm_device *, int voltage); -}; - -static inline struct nouveau_pm * -nouveau_pm(struct drm_device *dev) -{ -	return nouveau_drm(dev)->pm; -} - -struct nouveau_mem_exec_func { -	struct drm_device *dev; -	void (*precharge)(struct nouveau_mem_exec_func *); -	void (*refresh)(struct nouveau_mem_exec_func *); -	void (*refresh_auto)(struct nouveau_mem_exec_func *, bool); -	void (*refresh_self)(struct nouveau_mem_exec_func *, bool); -	void (*wait)(struct nouveau_mem_exec_func *, u32 nsec); -	u32  (*mrg)(struct nouveau_mem_exec_func *, int mr); -	void (*mrs)(struct nouveau_mem_exec_func *, int mr, u32 data); -	void (*clock_set)(struct nouveau_mem_exec_func *); -	void (*timing_set)(struct nouveau_mem_exec_func *); -	void *priv; -}; - -/* nouveau_mem.c */ -int  nouveau_mem_exec(struct nouveau_mem_exec_func *, -		      struct nouveau_pm_level *); - -/* nouveau_pm.c */ -int  nouveau_pm_init(struct drm_device *dev); -void nouveau_pm_fini(struct drm_device *dev); -void nouveau_pm_resume(struct drm_device *dev); -extern const struct nouveau_pm_profile_func nouveau_pm_static_profile_func; -void nouveau_pm_trigger(struct drm_device *dev); - -/* nouveau_volt.c */ -void nouveau_volt_init(struct drm_device *); -void nouveau_volt_fini(struct drm_device *); -int  nouveau_volt_vid_lookup(struct drm_device *, int voltage); -int  nouveau_volt_lvl_lookup(struct drm_device *, int vid); -int  nouveau_voltage_gpio_get(struct drm_device *); -int  nouveau_voltage_gpio_set(struct drm_device *, int voltage); - -/* nouveau_perf.c */ -void nouveau_perf_init(struct drm_device *); -void nouveau_perf_fini(struct drm_device *); -u8 *nouveau_perf_rammap(struct drm_device *, u32 freq, u8 *ver, -			u8 *hdr, u8 *cnt, u8 *len); -u8 *nouveau_perf_ramcfg(struct drm_device *, u32 freq, u8 *ver, u8 *len); -u8 *nouveau_perf_timing(struct drm_device *, u32 freq, u8 *ver, u8 *len); - -/* nouveau_mem.c */ -void nouveau_mem_timing_init(struct drm_device *); -void nouveau_mem_timing_fini(struct drm_device *); - -/* nv04_pm.c */ -int nv04_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nv04_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nv04_pm_clocks_set(struct drm_device *, void *); - -/* nv40_pm.c */ -int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nv40_pm_clocks_set(struct drm_device *, void *); -int nv40_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); -int nv40_pm_pwm_set(struct drm_device *, int, u32, u32); - -/* nv50_pm.c */ -int nv50_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nv50_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nv50_pm_clocks_set(struct drm_device *, void *); -int nv50_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); -int nv50_pm_pwm_set(struct drm_device *, int, u32, u32); - -/* nva3_pm.c */ -int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nva3_pm_clocks_set(struct drm_device *, void *); - -/* nvc0_pm.c */ -int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nvc0_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nvc0_pm_clocks_set(struct drm_device *, void *); - -/* nouveau_mem.c */ -int  nouveau_mem_timing_calc(struct drm_device *, u32 freq, -			     struct nouveau_pm_memtiming *); -void nouveau_mem_timing_read(struct drm_device *, -			     struct nouveau_pm_memtiming *); - -static inline int -nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *pll, u32 freq, -	      int *N, int *fN, int *M, int *P) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_clock *clk = nouveau_clock(device); -	struct nouveau_pll_vals pv; -	int ret; - -	ret = clk->pll_calc(clk, pll, freq, &pv); -	*N = pv.N1; -	*M = pv.M1; -	*P = pv.log2P; -	return ret; -} - -#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index e90468d5e5c..51a2cb102b4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -71,14 +71,16 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,  		return ERR_PTR(ret);  	nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART; -	nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); -	if (!nvbo->gem) { + +	/* Initialize the embedded gem-object. We return a single gem-reference +	 * to the caller, instead of a normal nouveau_bo ttm reference. */ +	ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size); +	if (ret) {  		nouveau_bo_ref(NULL, &nvbo);  		return ERR_PTR(-ENOMEM);  	} -	nvbo->gem->driver_private = nvbo; -	return nvbo->gem; +	return &nvbo->gem;  }  int nouveau_gem_prime_pin(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index ca5492ac2da..a4d22e5eb17 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -31,16 +31,17 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)  {  	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;  	struct nouveau_mem *node = mem->mm_node; -	u64 size = mem->num_pages << 12;  	if (ttm->sg) { -		node->sg = ttm->sg; -		nouveau_vm_map_sg_table(&node->vma[0], 0, size, node); +		node->sg    = ttm->sg; +		node->pages = NULL;  	} else { +		node->sg    = NULL;  		node->pages = nvbe->ttm.dma_address; -		nouveau_vm_map_sg(&node->vma[0], 0, size, node);  	} +	node->size = (mem->num_pages << PAGE_SHIFT) >> 12; +	nouveau_vm_map(&node->vma[0], node);  	nvbe->node = node;  	return 0;  } @@ -67,9 +68,13 @@ nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)  	/* noop: bound in move_notify() */  	if (ttm->sg) { -		node->sg = ttm->sg; -	} else +		node->sg    = ttm->sg; +		node->pages = NULL; +	} else { +		node->sg    = NULL;  		node->pages = nvbe->ttm.dma_address; +	} +	node->size = (mem->num_pages << PAGE_SHIFT) >> 12;  	return 0;  } @@ -104,9 +109,7 @@ nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,  	else  		nvbe->ttm.ttm.func = &nv50_sgdma_backend; -	if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) { -		kfree(nvbe); +	if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page))  		return NULL; -	}  	return &nvbe->ttm.ttm;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c new file mode 100644 index 00000000000..75dda2b0717 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c @@ -0,0 +1,164 @@ +/* + * Copyright 2013 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs <bskeggs@redhat.com> + */ + +#include "nouveau_sysfs.h" + +#include <core/object.h> +#include <core/class.h> + +static inline struct drm_device * +drm_device(struct device *d) +{ +	return dev_get_drvdata(d); +} + +#define snappendf(p,r,f,a...) do {                                             \ +	snprintf(p, r, f, ##a);                                                \ +	r -= strlen(p);                                                        \ +	p += strlen(p);                                                        \ +} while(0) + +static ssize_t +nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b) +{ +	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d)); +	struct nv_control_pstate_info info; +	size_t cnt = PAGE_SIZE; +	char *buf = b; +	int ret, i; + +	ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_INFO, &info, sizeof(info)); +	if (ret) +		return ret; + +	for (i = 0; i < info.count + 1; i++) { +		const s32 state = i < info.count ? i : +			NV_CONTROL_PSTATE_ATTR_STATE_CURRENT; +		struct nv_control_pstate_attr attr = { +			.state = state, +			.index = 0, +		}; + +		ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_ATTR, +			     &attr, sizeof(attr)); +		if (ret) +			return ret; + +		if (i < info.count) +			snappendf(buf, cnt, "%02x:", attr.state); +		else +			snappendf(buf, cnt, "--:"); + +		attr.index = 0; +		do { +			attr.state = state; +			ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_ATTR, +				     &attr, sizeof(attr)); +			if (ret) +				return ret; + +			snappendf(buf, cnt, " %s %d", attr.name, attr.min); +			if (attr.min != attr.max) +				snappendf(buf, cnt, "-%d", attr.max); +			snappendf(buf, cnt, " %s", attr.unit); +		} while (attr.index); + +		if ((state >= 0 && info.pstate == state) || +		    (state <  0 && info.ustate < 0)) +			snappendf(buf, cnt, " *"); +		snappendf(buf, cnt, "\n"); +	} + +	return strlen(b); +} + +static ssize_t +nouveau_sysfs_pstate_set(struct device *d, struct device_attribute *a, +			 const char *buf, size_t count) +{ +	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d)); +	struct nv_control_pstate_user args; +	long value, ret; +	char *tmp; + +	if ((tmp = strchr(buf, '\n'))) +		*tmp = '\0'; + +	if (!strcasecmp(buf, "none")) +		args.state = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN; +	else +	if (!strcasecmp(buf, "auto")) +		args.state = NV_CONTROL_PSTATE_USER_STATE_PERFMON; +	else { +		ret = kstrtol(buf, 16, &value); +		if (ret) +			return ret; +		args.state = value; +	} + +	ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args)); +	if (ret < 0) +		return ret; + +	return count; +} + +static DEVICE_ATTR(pstate, S_IRUGO | S_IWUSR, +		   nouveau_sysfs_pstate_get, nouveau_sysfs_pstate_set); + +void +nouveau_sysfs_fini(struct drm_device *dev) +{ +	struct nouveau_sysfs *sysfs = nouveau_sysfs(dev); +	struct nouveau_drm *drm = nouveau_drm(dev); +	struct nouveau_device *device = nv_device(drm->device); + +	if (sysfs->ctrl) { +		device_remove_file(nv_device_base(device), &dev_attr_pstate); +		nouveau_object_del(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL); +	} + +	drm->sysfs = NULL; +	kfree(sysfs); +} + +int +nouveau_sysfs_init(struct drm_device *dev) +{ +	struct nouveau_drm *drm = nouveau_drm(dev); +	struct nouveau_device *device = nv_device(drm->device); +	struct nouveau_sysfs *sysfs; +	int ret; + +	sysfs = drm->sysfs = kzalloc(sizeof(*sysfs), GFP_KERNEL); +	if (!sysfs) +		return -ENOMEM; + +	ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, NVDRM_CONTROL, +				 NV_CONTROL_CLASS, NULL, 0, &sysfs->ctrl); +	if (ret == 0) +		device_create_file(nv_device_base(device), &dev_attr_pstate); + +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.h b/drivers/gpu/drm/nouveau/nouveau_sysfs.h new file mode 100644 index 00000000000..74b47f1e01e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.h @@ -0,0 +1,19 @@ +#ifndef __NOUVEAU_SYSFS_H__ +#define __NOUVEAU_SYSFS_H__ + +#include "nouveau_drm.h" + +struct nouveau_sysfs { +	struct nouveau_object *ctrl; +}; + +static inline struct nouveau_sysfs * +nouveau_sysfs(struct drm_device *dev) +{ +	return nouveau_drm(dev)->sysfs; +} + +int  nouveau_sysfs_init(struct drm_device *); +void nouveau_sysfs_fini(struct drm_device *); + +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 19e3757291f..ab0228f640a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -171,6 +171,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,  	node = kzalloc(sizeof(*node), GFP_KERNEL);  	if (!node)  		return -ENOMEM; +  	node->page_shift = 12;  	switch (nv_device(drm->device)->card_type) { @@ -353,21 +354,26 @@ int  nouveau_ttm_init(struct nouveau_drm *drm)  {  	struct drm_device *dev = drm->dev; +	struct nouveau_device *device = nv_device(drm->device);  	u32 bits;  	int ret;  	bits = nouveau_vmmgr(drm->device)->dma_bits; -	if ( drm->agp.stat == ENABLED || -	    !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) -		bits = 32; - -	ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); -	if (ret) -		return ret; - -	ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); -	if (ret) -		pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); +	if (nv_device_is_pci(device)) { +		if (drm->agp.stat == ENABLED || +		     !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) +			bits = 32; + +		ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); +		if (ret) +			return ret; + +		ret = pci_set_consistent_dma_mask(dev->pdev, +						  DMA_BIT_MASK(bits)); +		if (ret) +			pci_set_consistent_dma_mask(dev->pdev, +						    DMA_BIT_MASK(32)); +	}  	ret = nouveau_ttm_global_init(drm);  	if (ret) @@ -375,7 +381,9 @@ nouveau_ttm_init(struct nouveau_drm *drm)  	ret = ttm_bo_device_init(&drm->ttm.bdev,  				  drm->ttm.bo_global_ref.ref.object, -				  &nouveau_bo_driver, DRM_FILE_PAGE_OFFSET, +				  &nouveau_bo_driver, +				  dev->anon_inode->i_mapping, +				  DRM_FILE_PAGE_OFFSET,  				  bits <= 32 ? true : false);  	if (ret) {  		NV_ERROR(drm, "error initialising bo driver, %d\n", ret); @@ -393,8 +401,8 @@ nouveau_ttm_init(struct nouveau_drm *drm)  		return ret;  	} -	drm->ttm.mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 1), -					 pci_resource_len(dev->pdev, 1)); +	drm->ttm.mtrr = arch_phys_wc_add(nv_device_resource_start(device, 1), +					 nv_device_resource_len(device, 1));  	/* GART init */  	if (drm->agp.stat != ENABLED) { diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index 81638d7f2ef..4f4c3fec691 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -14,7 +14,9 @@ nouveau_vga_set_decode(void *priv, bool state)  {  	struct nouveau_device *device = nouveau_dev(priv); -	if (device->chipset >= 0x40) +	if (device->card_type == NV_40 && device->chipset >= 0x4c) +		nv_wr32(device, 0x088060, state); +	else if (device->chipset >= 0x40)  		nv_wr32(device, 0x088054, state);  	else  		nv_wr32(device, 0x001854, state); @@ -62,12 +64,13 @@ static bool  nouveau_switcheroo_can_switch(struct pci_dev *pdev)  {  	struct drm_device *dev = pci_get_drvdata(pdev); -	bool can_switch; -	spin_lock(&dev->count_lock); -	can_switch = (dev->open_count == 0); -	spin_unlock(&dev->count_lock); -	return can_switch; +	/* +	 * FIXME: open_count is protected by drm_global_mutex but that would lead to +	 * locking inversion with the driver load path. And the access here is +	 * completely racy anyway. So don't bother with locking for now. +	 */ +	return dev->open_count == 0;  }  static const struct vga_switcheroo_client_ops @@ -82,6 +85,11 @@ nouveau_vga_init(struct nouveau_drm *drm)  {  	struct drm_device *dev = drm->dev;  	bool runtime = false; + +	/* only relevant for PCI devices */ +	if (!dev->pdev) +		return; +  	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);  	if (nouveau_runtime_pm == 1) diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c deleted file mode 100644 index 9976414cbe5..00000000000 --- a/drivers/gpu/drm/nouveau/nouveau_volt.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> - -#include "nouveau_drm.h" -#include "nouveau_pm.h" - -#include <subdev/bios/gpio.h> -#include <subdev/gpio.h> - -static const enum dcb_gpio_func_name vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; -static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); - -int -nouveau_voltage_gpio_get(struct drm_device *dev) -{ -	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(device); -	u8 vid = 0; -	int i; - -	for (i = 0; i < nr_vidtag; i++) { -		if (!(volt->vid_mask & (1 << i))) -			continue; - -		vid |= gpio->get(gpio, 0, vidtag[i], 0xff) << i; -	} - -	return nouveau_volt_lvl_lookup(dev, vid); -} - -int -nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(device); -	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; -	int vid, i; - -	vid = nouveau_volt_vid_lookup(dev, voltage); -	if (vid < 0) -		return vid; - -	for (i = 0; i < nr_vidtag; i++) { -		if (!(volt->vid_mask & (1 << i))) -			continue; - -		gpio->set(gpio, 0, vidtag[i], 0xff, !!(vid & (1 << i))); -	} - -	return 0; -} - -int -nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) -{ -	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; -	int i; - -	for (i = 0; i < volt->nr_level; i++) { -		if (volt->level[i].voltage == voltage) -			return volt->level[i].vid; -	} - -	return -ENOENT; -} - -int -nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) -{ -	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; -	int i; - -	for (i = 0; i < volt->nr_level; i++) { -		if (volt->level[i].vid == vid) -			return volt->level[i].voltage; -	} - -	return -ENOENT; -} - -void -nouveau_volt_init(struct drm_device *dev) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); -	struct nouveau_pm *pm = nouveau_pm(dev); -	struct nouveau_pm_voltage *voltage = &pm->voltage; -	struct nvbios *bios = &drm->vbios; -	struct dcb_gpio_func func; -	struct bit_entry P; -	u8 *volt = NULL, *entry; -	int i, headerlen, recordlen, entries, vidmask, vidshift; - -	if (bios->type == NVBIOS_BIT) { -		if (bit_table(dev, 'P', &P)) -			return; - -		if (P.version == 1) -			volt = ROMPTR(dev, P.data[16]); -		else -		if (P.version == 2) -			volt = ROMPTR(dev, P.data[12]); -		else { -			NV_WARN(drm, "unknown volt for BIT P %d\n", P.version); -		} -	} else { -		if (bios->data[bios->offset + 6] < 0x27) { -			NV_DEBUG(drm, "BMP version too old for voltage\n"); -			return; -		} - -		volt = ROMPTR(dev, bios->data[bios->offset + 0x98]); -	} - -	if (!volt) { -		NV_DEBUG(drm, "voltage table pointer invalid\n"); -		return; -	} - -	switch (volt[0]) { -	case 0x10: -	case 0x11: -	case 0x12: -		headerlen = 5; -		recordlen = volt[1]; -		entries   = volt[2]; -		vidshift  = 0; -		vidmask   = volt[4]; -		break; -	case 0x20: -		headerlen = volt[1]; -		recordlen = volt[3]; -		entries   = volt[2]; -		vidshift  = 0; /* could be vidshift like 0x30? */ -		vidmask   = volt[5]; -		break; -	case 0x30: -		headerlen = volt[1]; -		recordlen = volt[2]; -		entries   = volt[3]; -		vidmask   = volt[4]; -		/* no longer certain what volt[5] is, if it's related to -		 * the vid shift then it's definitely not a function of -		 * how many bits are set. -		 * -		 * after looking at a number of nva3+ vbios images, they -		 * all seem likely to have a static shift of 2.. lets -		 * go with that for now until proven otherwise. -		 */ -		vidshift  = 2; -		break; -	case 0x40: -		headerlen = volt[1]; -		recordlen = volt[2]; -		entries   = volt[3]; /* not a clue what the entries are for.. */ -		vidmask   = volt[11]; /* guess.. */ -		vidshift  = 0; -		break; -	default: -		NV_WARN(drm, "voltage table 0x%02x unknown\n", volt[0]); -		return; -	} - -	/* validate vid mask */ -	voltage->vid_mask = vidmask; -	if (!voltage->vid_mask) -		return; - -	i = 0; -	while (vidmask) { -		if (i > nr_vidtag) { -			NV_DEBUG(drm, "vid bit %d unknown\n", i); -			return; -		} - -		if (gpio && gpio->find(gpio, 0, vidtag[i], 0xff, &func)) { -			NV_DEBUG(drm, "vid bit %d has no gpio tag\n", i); -			return; -		} - -		vidmask >>= 1; -		i++; -	} - -	/* parse vbios entries into common format */ -	voltage->version = volt[0]; -	if (voltage->version < 0x40) { -		voltage->nr_level = entries; -		voltage->level = -			kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); -		if (!voltage->level) -			return; - -		entry = volt + headerlen; -		for (i = 0; i < entries; i++, entry += recordlen) { -			voltage->level[i].voltage = entry[0] * 10000; -			voltage->level[i].vid     = entry[1] >> vidshift; -		} -	} else { -		u32 volt_uv = ROM32(volt[4]); -		s16 step_uv = ROM16(volt[8]); -		u8 vid; - -		voltage->nr_level = voltage->vid_mask + 1; -		voltage->level = kcalloc(voltage->nr_level, -					 sizeof(*voltage->level), GFP_KERNEL); -		if (!voltage->level) -			return; - -		for (vid = 0; vid <= voltage->vid_mask; vid++) { -			voltage->level[vid].voltage = volt_uv; -			voltage->level[vid].vid = vid; -			volt_uv += step_uv; -		} -	} - -	voltage->supported = true; -} - -void -nouveau_volt_fini(struct drm_device *dev) -{ -	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; - -	kfree(volt->level); -} diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 77dcc9c5077..8fe32bbed99 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -255,6 +255,12 @@ nv04_fbcon_accel_init(struct fb_info *info)  	OUT_RING(chan, NvCtxSurf2D);  	BEGIN_NV04(chan, NvSubImageBlit, 0x02fc, 1);  	OUT_RING(chan, 3); +	if (device->chipset >= 0x11 /*XXX: oclass == 0x009f*/) { +		BEGIN_NV04(chan, NvSubImageBlit, 0x0120, 3); +		OUT_RING(chan, 0); +		OUT_RING(chan, 1); +		OUT_RING(chan, 2); +	}  	BEGIN_NV04(chan, NvSubGdiRect, 0x0000, 1);  	OUT_RING(chan, NvGdiRect); diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c deleted file mode 100644 index 27afc0ea28b..00000000000 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> -#include "nouveau_drm.h" -#include "nouveau_reg.h" -#include "dispnv04/hw.h" -#include "nouveau_pm.h" - -#include <subdev/bios/pll.h> -#include <subdev/clock.h> -#include <subdev/timer.h> - -int -nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	int ret; - -	ret = nouveau_hw_get_clock(dev, PLL_CORE); -	if (ret < 0) -		return ret; -	perflvl->core = ret; - -	ret = nouveau_hw_get_clock(dev, PLL_MEMORY); -	if (ret < 0) -		return ret; -	perflvl->memory = ret; - -	return 0; -} - -struct nv04_pm_clock { -	struct nvbios_pll pll; -	struct nouveau_pll_vals calc; -}; - -struct nv04_pm_state { -	struct nv04_pm_clock core; -	struct nv04_pm_clock memory; -}; - -static int -calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nouveau_clock *pclk = nouveau_clock(device); -	int ret; - -	ret = nvbios_pll_parse(bios, id, &clk->pll); -	if (ret) -		return ret; - -	ret = pclk->pll_calc(pclk, &clk->pll, khz, &clk->calc); -	if (!ret) -		return -EINVAL; - -	return 0; -} - -void * -nv04_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nv04_pm_state *info; -	int ret; - -	info = kzalloc(sizeof(*info), GFP_KERNEL); -	if (!info) -		return ERR_PTR(-ENOMEM); - -	ret = calc_pll(dev, PLL_CORE, perflvl->core, &info->core); -	if (ret) -		goto error; - -	if (perflvl->memory) { -		ret = calc_pll(dev, PLL_MEMORY, perflvl->memory, &info->memory); -		if (ret) -			goto error; -	} - -	return info; -error: -	kfree(info); -	return ERR_PTR(ret); -} - -static void -prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_clock *pclk = nouveau_clock(device); -	u32 reg = clk->pll.reg; - -	/* thank the insane nouveau_hw_setpll() interface for this */ -	if (device->card_type >= NV_40) -		reg += 4; - -	pclk->pll_prog(pclk, reg, &clk->calc); -} - -int -nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_timer *ptimer = nouveau_timer(device); -	struct nv04_pm_state *state = pre_state; - -	prog_pll(dev, &state->core); - -	if (state->memory.pll.reg) { -		prog_pll(dev, &state->memory); -		if (device->card_type < NV_30) { -			if (device->card_type == NV_20) -				nv_mask(device, 0x1002c4, 0, 1 << 20); - -			/* Reset the DLLs */ -			nv_mask(device, 0x1002c0, 0, 1 << 8); -		} -	} - -	nv_ofuncs(ptimer)->init(nv_object(ptimer)); - -	kfree(state); -	return 0; -} diff --git a/drivers/gpu/drm/nouveau/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c deleted file mode 100644 index 625f80d53dc..00000000000 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> -#include "nouveau_drm.h" -#include "nouveau_bios.h" -#include "nouveau_pm.h" -#include "dispnv04/hw.h" - -#include <subdev/bios/pll.h> -#include <subdev/clock.h> -#include <subdev/timer.h> - -#include <engine/fifo.h> - -#define min2(a,b) ((a) < (b) ? (a) : (b)) - -static u32 -read_pll_1(struct drm_device *dev, u32 reg) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ctrl = nv_rd32(device, reg + 0x00); -	int P = (ctrl & 0x00070000) >> 16; -	int N = (ctrl & 0x0000ff00) >> 8; -	int M = (ctrl & 0x000000ff) >> 0; -	u32 ref = 27000, clk = 0; - -	if (ctrl & 0x80000000) -		clk = ref * N / M; - -	return clk >> P; -} - -static u32 -read_pll_2(struct drm_device *dev, u32 reg) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ctrl = nv_rd32(device, reg + 0x00); -	u32 coef = nv_rd32(device, reg + 0x04); -	int N2 = (coef & 0xff000000) >> 24; -	int M2 = (coef & 0x00ff0000) >> 16; -	int N1 = (coef & 0x0000ff00) >> 8; -	int M1 = (coef & 0x000000ff) >> 0; -	int P = (ctrl & 0x00070000) >> 16; -	u32 ref = 27000, clk = 0; - -	if ((ctrl & 0x80000000) && M1) { -		clk = ref * N1 / M1; -		if ((ctrl & 0x40000100) == 0x40000000) { -			if (M2) -				clk = clk * N2 / M2; -			else -				clk = 0; -		} -	} - -	return clk >> P; -} - -static u32 -read_clk(struct drm_device *dev, u32 src) -{ -	switch (src) { -	case 3: -		return read_pll_2(dev, 0x004000); -	case 2: -		return read_pll_1(dev, 0x004008); -	default: -		break; -	} - -	return 0; -} - -int -nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ctrl = nv_rd32(device, 0x00c040); - -	perflvl->core   = read_clk(dev, (ctrl & 0x00000003) >> 0); -	perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); -	perflvl->memory = read_pll_2(dev, 0x4020); -	return 0; -} - -struct nv40_pm_state { -	u32 ctrl; -	u32 npll_ctrl; -	u32 npll_coef; -	u32 spll; -	u32 mpll_ctrl; -	u32 mpll_coef; -}; - -static int -nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, -	      u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nouveau_clock *pclk = nouveau_clock(device); -	struct nouveau_pll_vals coef; -	int ret; - -	ret = nvbios_pll_parse(bios, reg, pll); -	if (ret) -		return ret; - -	if (clk < pll->vco1.max_freq) -		pll->vco2.max_freq = 0; - -	ret = pclk->pll_calc(pclk, pll, clk, &coef); -	if (ret == 0) -		return -ERANGE; - -	*N1 = coef.N1; -	*M1 = coef.M1; -	if (N2 && M2) { -		if (pll->vco2.max_freq) { -			*N2 = coef.N2; -			*M2 = coef.M2; -		} else { -			*N2 = 1; -			*M2 = 1; -		} -	} -	*log2P = coef.log2P; -	return 0; -} - -void * -nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nv40_pm_state *info; -	struct nvbios_pll pll; -	int N1, N2, M1, M2, log2P; -	int ret; - -	info = kmalloc(sizeof(*info), GFP_KERNEL); -	if (!info) -		return ERR_PTR(-ENOMEM); - -	/* core/geometric clock */ -	ret = nv40_calc_pll(dev, 0x004000, &pll, perflvl->core, -			    &N1, &M1, &N2, &M2, &log2P); -	if (ret < 0) -		goto out; - -	if (N2 == M2) { -		info->npll_ctrl = 0x80000100 | (log2P << 16); -		info->npll_coef = (N1 << 8) | M1; -	} else { -		info->npll_ctrl = 0xc0000000 | (log2P << 16); -		info->npll_coef = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; -	} - -	/* use the second PLL for shader/rop clock, if it differs from core */ -	if (perflvl->shader && perflvl->shader != perflvl->core) { -		ret = nv40_calc_pll(dev, 0x004008, &pll, perflvl->shader, -				    &N1, &M1, NULL, NULL, &log2P); -		if (ret < 0) -			goto out; - -		info->spll = 0xc0000000 | (log2P << 16) | (N1 << 8) | M1; -		info->ctrl = 0x00000223; -	} else { -		info->spll = 0x00000000; -		info->ctrl = 0x00000333; -	} - -	/* memory clock */ -	if (!perflvl->memory) { -		info->mpll_ctrl = 0x00000000; -		goto out; -	} - -	ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory, -			    &N1, &M1, &N2, &M2, &log2P); -	if (ret < 0) -		goto out; - -	info->mpll_ctrl  = 0x80000000 | (log2P << 16); -	info->mpll_ctrl |= min2(pll.bias_p + log2P, pll.max_p) << 20; -	if (N2 == M2) { -		info->mpll_ctrl |= 0x00000100; -		info->mpll_coef  = (N1 << 8) | M1; -	} else { -		info->mpll_ctrl |= 0x40000000; -		info->mpll_coef  = (N2 << 24) | (M2 << 16) | (N1 << 8) | M1; -	} - -out: -	if (ret < 0) { -		kfree(info); -		info = ERR_PTR(ret); -	} -	return info; -} - -static bool -nv40_pm_gr_idle(void *data) -{ -	struct drm_device *dev = data; -	struct nouveau_device *device = nouveau_dev(dev); - -	if ((nv_rd32(device, 0x400760) & 0x000000f0) >> 4 != -	    (nv_rd32(device, 0x400760) & 0x0000000f)) -		return false; - -	if (nv_rd32(device, 0x400700)) -		return false; - -	return true; -} - -int -nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_fifo *pfifo = nouveau_fifo(device); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nv40_pm_state *info = pre_state; -	unsigned long flags; -	struct bit_entry M; -	u32 crtc_mask = 0; -	u8 sr1[2]; -	int i, ret = -EAGAIN; - -	/* determine which CRTCs are active, fetch VGA_SR1 for each */ -	for (i = 0; i < 2; i++) { -		u32 vbl = nv_rd32(device, 0x600808 + (i * 0x2000)); -		u32 cnt = 0; -		do { -			if (vbl != nv_rd32(device, 0x600808 + (i * 0x2000))) { -				nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); -				sr1[i] = nv_rd08(device, 0x0c03c5 + (i * 0x2000)); -				if (!(sr1[i] & 0x20)) -					crtc_mask |= (1 << i); -				break; -			} -			udelay(1); -		} while (cnt++ < 32); -	} - -	/* halt and idle engines */ -	pfifo->pause(pfifo, &flags); - -	if (!nv_wait_cb(device, nv40_pm_gr_idle, dev)) -		goto resume; - -	ret = 0; - -	/* set engine clocks */ -	nv_mask(device, 0x00c040, 0x00000333, 0x00000000); -	nv_wr32(device, 0x004004, info->npll_coef); -	nv_mask(device, 0x004000, 0xc0070100, info->npll_ctrl); -	nv_mask(device, 0x004008, 0xc007ffff, info->spll); -	mdelay(5); -	nv_mask(device, 0x00c040, 0x00000333, info->ctrl); - -	if (!info->mpll_ctrl) -		goto resume; - -	/* wait for vblank start on active crtcs, disable memory access */ -	for (i = 0; i < 2; i++) { -		if (!(crtc_mask & (1 << i))) -			continue; -		nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); -		nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); -		nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); -		nv_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); -	} - -	/* prepare ram for reclocking */ -	nv_wr32(device, 0x1002d4, 0x00000001); /* precharge */ -	nv_wr32(device, 0x1002d0, 0x00000001); /* refresh */ -	nv_wr32(device, 0x1002d0, 0x00000001); /* refresh */ -	nv_mask(device, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ -	nv_wr32(device, 0x1002dc, 0x00000001); /* enable self-refresh */ - -	/* change the PLL of each memory partition */ -	nv_mask(device, 0x00c040, 0x0000c000, 0x00000000); -	switch (nv_device(drm->device)->chipset) { -	case 0x40: -	case 0x45: -	case 0x41: -	case 0x42: -	case 0x47: -		nv_mask(device, 0x004044, 0xc0771100, info->mpll_ctrl); -		nv_mask(device, 0x00402c, 0xc0771100, info->mpll_ctrl); -		nv_wr32(device, 0x004048, info->mpll_coef); -		nv_wr32(device, 0x004030, info->mpll_coef); -	case 0x43: -	case 0x49: -	case 0x4b: -		nv_mask(device, 0x004038, 0xc0771100, info->mpll_ctrl); -		nv_wr32(device, 0x00403c, info->mpll_coef); -	default: -		nv_mask(device, 0x004020, 0xc0771100, info->mpll_ctrl); -		nv_wr32(device, 0x004024, info->mpll_coef); -		break; -	} -	udelay(100); -	nv_mask(device, 0x00c040, 0x0000c000, 0x0000c000); - -	/* re-enable normal operation of memory controller */ -	nv_wr32(device, 0x1002dc, 0x00000000); -	nv_mask(device, 0x100210, 0x80000000, 0x80000000); -	udelay(100); - -	/* execute memory reset script from vbios */ -	if (!bit_table(dev, 'M', &M)) -		nouveau_bios_run_init_table(dev, ROM16(M.data[0]), NULL, 0); - -	/* make sure we're in vblank (hopefully the same one as before), and -	 * then re-enable crtc memory access -	 */ -	for (i = 0; i < 2; i++) { -		if (!(crtc_mask & (1 << i))) -			continue; -		nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); -		nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); -		nv_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i]); -	} - -	/* resume engines */ -resume: -	pfifo->start(pfifo, &flags); -	kfree(info); -	return ret; -} diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f8e66c08b11..4c534b7b04d 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1,4 +1,4 @@ -	/* +/*   * Copyright 2011 Red Hat Inc.   *   * Permission is hereby granted, free of charge, to any person obtaining a @@ -26,6 +26,7 @@  #include <drm/drmP.h>  #include <drm/drm_crtc_helper.h> +#include <drm/drm_dp_helper.h>  #include "nouveau_drm.h"  #include "nouveau_dma.h" @@ -651,7 +652,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)  	nv_connector = nouveau_crtc_connector_get(nv_crtc);  	connector = &nv_connector->base;  	if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { -		if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) +		if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)  			mode = DITHERING_MODE_DYNAMIC2X2;  	} else {  		mode = nv_connector->dithering_mode; @@ -785,7 +786,8 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)  		if (update) {  			nv50_display_flip_stop(crtc); -			nv50_display_flip_next(crtc, crtc->fb, NULL, 1); +			nv50_display_flip_next(crtc, crtc->primary->fb, +					       NULL, 1);  		}  	} @@ -956,7 +958,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)  	nv50_display_flip_stop(crtc); -	push = evo_wait(mast, 2); +	push = evo_wait(mast, 6);  	if (push) {  		if (nv50_vers(mast) < NV84_DISP_MAST_CLASS) {  			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1); @@ -1028,20 +1030,21 @@ nv50_crtc_commit(struct drm_crtc *crtc)  	}  	nv50_crtc_cursor_show_hide(nv_crtc, nv_crtc->cursor.visible, true); -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1); +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);  }  static bool  nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,  		     struct drm_display_mode *adjusted_mode)  { +	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);  	return true;  }  static int  nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)  { -	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); +	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);  	struct nv50_head *head = nv50_head(crtc);  	int ret; @@ -1138,7 +1141,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,  	nv50_crtc_set_dither(nv_crtc, false);  	nv50_crtc_set_scale(nv_crtc, false);  	nv50_crtc_set_color_vibrance(nv_crtc, false); -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, false); +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);  	return 0;  } @@ -1150,7 +1153,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);  	int ret; -	if (!crtc->fb) { +	if (!crtc->primary->fb) {  		NV_DEBUG(drm, "No FB bound\n");  		return 0;  	} @@ -1160,8 +1163,8 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,  		return ret;  	nv50_display_flip_stop(crtc); -	nv50_crtc_set_image(nv_crtc, crtc->fb, x, y, true); -	nv50_display_flip_next(crtc, crtc->fb, NULL, 1); +	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true); +	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);  	return 0;  } @@ -1205,6 +1208,7 @@ static void  nv50_crtc_disable(struct drm_crtc *crtc)  {  	struct nv50_head *head = nv50_head(crtc); +	evo_sync(crtc->dev);  	if (head->image)  		nouveau_bo_unpin(head->image);  	nouveau_bo_ref(NULL, &head->image); @@ -1265,7 +1269,7 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,  		    uint32_t start, uint32_t size)  {  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -	u32 end = max(start + size, (u32)256); +	u32 end = min_t(u32, start + size, 256);  	u32 i;  	for (i = start; i < end; i++) { @@ -1698,10 +1702,9 @@ nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)  }  static void -nv50_hdmi_disconnect(struct drm_encoder *encoder) +nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)  {  	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -	struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);  	struct nv50_disp *disp = nv50_disp(encoder->dev);  	const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; @@ -1720,7 +1723,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)  	struct drm_device *dev = encoder->dev;  	struct nv50_disp *disp = nv50_disp(dev);  	struct drm_encoder *partner; -	int or = nv_encoder->or; +	u32 mthd;  	nv_encoder->last_dpms = mode; @@ -1738,7 +1741,18 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)  		}  	} -	nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); +	mthd  = (ffs(nv_encoder->dcb->heads) - 1) << 3; +	mthd |= (ffs(nv_encoder->dcb->sorconf.link) - 1) << 2; +	mthd |= nv_encoder->or; + +	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { +		nv_call(disp->core, NV50_DISP_SOR_PWR | mthd, 1); +		mthd |= NV94_DISP_SOR_DP_PWR; +	} else { +		mthd |= NV50_DISP_SOR_PWR; +	} + +	nv_call(disp->core, mthd, (mode == DRM_MODE_DPMS_ON));  }  static bool @@ -1762,33 +1776,36 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder,  }  static void -nv50_sor_disconnect(struct drm_encoder *encoder) +nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data)  { -	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -	struct nv50_mast *mast = nv50_mast(encoder->dev); -	const int or = nv_encoder->or; -	u32 *push; - -	if (nv_encoder->crtc) { -		nv50_crtc_prepare(nv_encoder->crtc); - -		push = evo_wait(mast, 4); -		if (push) { -			if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { -				evo_mthd(push, 0x0600 + (or * 0x40), 1); -				evo_data(push, 0x00000000); -			} else { -				evo_mthd(push, 0x0200 + (or * 0x20), 1); -				evo_data(push, 0x00000000); -			} -			evo_kick(push, mast); +	struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev); +	u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push; +	if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) { +		if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { +			evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1); +			evo_data(push, (nv_encoder->ctrl = temp)); +		} else { +			evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); +			evo_data(push, (nv_encoder->ctrl = temp));  		} - -		nv50_hdmi_disconnect(encoder); +		evo_kick(push, mast);  	} +} + +static void +nv50_sor_disconnect(struct drm_encoder *encoder) +{ +	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +	struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);  	nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;  	nv_encoder->crtc = NULL; + +	if (nv_crtc) { +		nv50_crtc_prepare(&nv_crtc->base); +		nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0); +		nv50_hdmi_disconnect(&nv_encoder->base.base, nv_crtc); +	}  }  static void @@ -1808,12 +1825,14 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,  	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);  	struct nouveau_connector *nv_connector;  	struct nvbios *bios = &drm->vbios; -	u32 *push, lvds = 0; +	u32 lvds = 0, mask, ctrl;  	u8 owner = 1 << nv_crtc->index;  	u8 proto = 0xf;  	u8 depth = 0x0;  	nv_connector = nouveau_encoder_connector_get(nv_encoder); +	nv_encoder->crtc = encoder->crtc; +  	switch (nv_encoder->dcb->type) {  	case DCB_OUTPUT_TMDS:  		if (nv_encoder->dcb->sorconf.link & 1) { @@ -1825,7 +1844,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,  			proto = 0x2;  		} -		nv50_hdmi_mode_set(encoder, mode); +		nv50_hdmi_mode_set(&nv_encoder->base.base, mode);  		break;  	case DCB_OUTPUT_LVDS:  		proto = 0x0; @@ -1881,19 +1900,11 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,  		break;  	} -	nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); +	nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON); -	push = evo_wait(nv50_mast(dev), 8); -	if (push) { -		if (nv50_vers(mast) < NVD0_DISP_CLASS) { -			u32 ctrl = (depth << 16) | (proto << 8) | owner; -			if (mode->flags & DRM_MODE_FLAG_NHSYNC) -				ctrl |= 0x00001000; -			if (mode->flags & DRM_MODE_FLAG_NVSYNC) -				ctrl |= 0x00002000; -			evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1); -			evo_data(push, ctrl); -		} else { +	if (nv50_vers(mast) >= NVD0_DISP_CLASS) { +		u32 *push = evo_wait(mast, 3); +		if (push) {  			u32 magic = 0x31ec6000 | (nv_crtc->index << 25);  			u32 syncs = 0x00000001; @@ -1908,14 +1919,21 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,  			evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);  			evo_data(push, syncs | (depth << 6));  			evo_data(push, magic); -			evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1); -			evo_data(push, owner | (proto << 8)); +			evo_kick(push, mast);  		} -		evo_kick(push, mast); +		ctrl = proto << 8; +		mask = 0x00000f00; +	} else { +		ctrl = (depth << 16) | (proto << 8); +		if (mode->flags & DRM_MODE_FLAG_NHSYNC) +			ctrl |= 0x00001000; +		if (mode->flags & DRM_MODE_FLAG_NVSYNC) +			ctrl |= 0x00002000; +		mask = 0x000f3f00;  	} -	nv_encoder->crtc = encoder->crtc; +	nv50_sor_ctrl(nv_encoder, mask | owner, ctrl | owner);  }  static void @@ -2199,16 +2217,6 @@ nv50_display_destroy(struct drm_device *dev)  int  nv50_display_create(struct drm_device *dev)  { -	static const u16 oclass[] = { -		NVF0_DISP_CLASS, -		NVE0_DISP_CLASS, -		NVD0_DISP_CLASS, -		NVA3_DISP_CLASS, -		NV94_DISP_CLASS, -		NVA0_DISP_CLASS, -		NV84_DISP_CLASS, -		NV50_DISP_CLASS, -	};  	struct nouveau_device *device = nouveau_dev(dev);  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct dcb_table *dcb = &drm->vbios.dcb; @@ -2225,6 +2233,7 @@ nv50_display_create(struct drm_device *dev)  	nouveau_display(dev)->dtor = nv50_display_destroy;  	nouveau_display(dev)->init = nv50_display_init;  	nouveau_display(dev)->fini = nv50_display_fini; +	disp->core = nouveau_display(dev)->core;  	/* small shared memory area we use for notifiers and semaphores */  	ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, @@ -2243,17 +2252,6 @@ nv50_display_create(struct drm_device *dev)  	if (ret)  		goto out; -	/* attempt to allocate a supported evo display class */ -	ret = -ENODEV; -	for (i = 0; ret && i < ARRAY_SIZE(oclass); i++) { -		ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, -					 0xd1500000, oclass[i], NULL, 0, -					 &disp->core); -	} - -	if (ret) -		goto out; -  	/* allocate master evo channel */  	ret = nv50_dmac_create(disp->core, NV50_DISP_MAST_CLASS, 0,  			      &(struct nv50_display_mast_class) { @@ -2313,7 +2311,7 @@ nv50_display_create(struct drm_device *dev)  			continue;  		NV_WARN(drm, "%s has no encoders, removing\n", -			drm_get_connector_name(connector)); +			connector->name);  		connector->funcs->destroy(connector);  	} diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c deleted file mode 100644 index 4efc33fa73f..00000000000 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ /dev/null @@ -1,855 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> -#include "nouveau_drm.h" -#include "nouveau_bios.h" -#include "dispnv04/hw.h" -#include "nouveau_pm.h" -#include "nouveau_hwsq.h" - -#include "nv50_display.h" - -#include <subdev/bios/pll.h> -#include <subdev/clock.h> -#include <subdev/timer.h> -#include <subdev/fb.h> - -enum clk_src { -	clk_src_crystal, -	clk_src_href, -	clk_src_hclk, -	clk_src_hclkm3, -	clk_src_hclkm3d2, -	clk_src_host, -	clk_src_nvclk, -	clk_src_sclk, -	clk_src_mclk, -	clk_src_vdec, -	clk_src_dom6 -}; - -static u32 read_clk(struct drm_device *, enum clk_src); - -static u32 -read_div(struct drm_device *dev) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); - -	switch (nv_device(drm->device)->chipset) { -	case 0x50: /* it exists, but only has bit 31, not the dividers.. */ -	case 0x84: -	case 0x86: -	case 0x98: -	case 0xa0: -		return nv_rd32(device, 0x004700); -	case 0x92: -	case 0x94: -	case 0x96: -		return nv_rd32(device, 0x004800); -	default: -		return 0x00000000; -	} -} - -static u32 -read_pll_src(struct drm_device *dev, u32 base) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	u32 coef, ref = read_clk(dev, clk_src_crystal); -	u32 rsel = nv_rd32(device, 0x00e18c); -	int P, N, M, id; - -	switch (nv_device(drm->device)->chipset) { -	case 0x50: -	case 0xa0: -		switch (base) { -		case 0x4020: -		case 0x4028: id = !!(rsel & 0x00000004); break; -		case 0x4008: id = !!(rsel & 0x00000008); break; -		case 0x4030: id = 0; break; -		default: -			NV_ERROR(drm, "ref: bad pll 0x%06x\n", base); -			return 0; -		} - -		coef = nv_rd32(device, 0x00e81c + (id * 0x0c)); -		ref *=  (coef & 0x01000000) ? 2 : 4; -		P    =  (coef & 0x00070000) >> 16; -		N    = ((coef & 0x0000ff00) >> 8) + 1; -		M    = ((coef & 0x000000ff) >> 0) + 1; -		break; -	case 0x84: -	case 0x86: -	case 0x92: -		coef = nv_rd32(device, 0x00e81c); -		P    = (coef & 0x00070000) >> 16; -		N    = (coef & 0x0000ff00) >> 8; -		M    = (coef & 0x000000ff) >> 0; -		break; -	case 0x94: -	case 0x96: -	case 0x98: -		rsel = nv_rd32(device, 0x00c050); -		switch (base) { -		case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; -		case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; -		case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; -		case 0x4030: rsel = 3; break; -		default: -			NV_ERROR(drm, "ref: bad pll 0x%06x\n", base); -			return 0; -		} - -		switch (rsel) { -		case 0: id = 1; break; -		case 1: return read_clk(dev, clk_src_crystal); -		case 2: return read_clk(dev, clk_src_href); -		case 3: id = 0; break; -		} - -		coef =  nv_rd32(device, 0x00e81c + (id * 0x28)); -		P    = (nv_rd32(device, 0x00e824 + (id * 0x28)) >> 16) & 7; -		P   += (coef & 0x00070000) >> 16; -		N    = (coef & 0x0000ff00) >> 8; -		M    = (coef & 0x000000ff) >> 0; -		break; -	default: -		BUG_ON(1); -	} - -	if (M) -		return (ref * N / M) >> P; -	return 0; -} - -static u32 -read_pll_ref(struct drm_device *dev, u32 base) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	u32 src, mast = nv_rd32(device, 0x00c040); - -	switch (base) { -	case 0x004028: -		src = !!(mast & 0x00200000); -		break; -	case 0x004020: -		src = !!(mast & 0x00400000); -		break; -	case 0x004008: -		src = !!(mast & 0x00010000); -		break; -	case 0x004030: -		src = !!(mast & 0x02000000); -		break; -	case 0x00e810: -		return read_clk(dev, clk_src_crystal); -	default: -		NV_ERROR(drm, "bad pll 0x%06x\n", base); -		return 0; -	} - -	if (src) -		return read_clk(dev, clk_src_href); -	return read_pll_src(dev, base); -} - -static u32 -read_pll(struct drm_device *dev, u32 base) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	u32 mast = nv_rd32(device, 0x00c040); -	u32 ctrl = nv_rd32(device, base + 0); -	u32 coef = nv_rd32(device, base + 4); -	u32 ref = read_pll_ref(dev, base); -	u32 clk = 0; -	int N1, N2, M1, M2; - -	if (base == 0x004028 && (mast & 0x00100000)) { -		/* wtf, appears to only disable post-divider on nva0 */ -		if (nv_device(drm->device)->chipset != 0xa0) -			return read_clk(dev, clk_src_dom6); -	} - -	N2 = (coef & 0xff000000) >> 24; -	M2 = (coef & 0x00ff0000) >> 16; -	N1 = (coef & 0x0000ff00) >> 8; -	M1 = (coef & 0x000000ff); -	if ((ctrl & 0x80000000) && M1) { -		clk = ref * N1 / M1; -		if ((ctrl & 0x40000100) == 0x40000000) { -			if (M2) -				clk = clk * N2 / M2; -			else -				clk = 0; -		} -	} - -	return clk; -} - -static u32 -read_clk(struct drm_device *dev, enum clk_src src) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	u32 mast = nv_rd32(device, 0x00c040); -	u32 P = 0; - -	switch (src) { -	case clk_src_crystal: -		return device->crystal; -	case clk_src_href: -		return 100000; /* PCIE reference clock */ -	case clk_src_hclk: -		return read_clk(dev, clk_src_href) * 27778 / 10000; -	case clk_src_hclkm3: -		return read_clk(dev, clk_src_hclk) * 3; -	case clk_src_hclkm3d2: -		return read_clk(dev, clk_src_hclk) * 3 / 2; -	case clk_src_host: -		switch (mast & 0x30000000) { -		case 0x00000000: return read_clk(dev, clk_src_href); -		case 0x10000000: break; -		case 0x20000000: /* !0x50 */ -		case 0x30000000: return read_clk(dev, clk_src_hclk); -		} -		break; -	case clk_src_nvclk: -		if (!(mast & 0x00100000)) -			P = (nv_rd32(device, 0x004028) & 0x00070000) >> 16; -		switch (mast & 0x00000003) { -		case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; -		case 0x00000001: return read_clk(dev, clk_src_dom6); -		case 0x00000002: return read_pll(dev, 0x004020) >> P; -		case 0x00000003: return read_pll(dev, 0x004028) >> P; -		} -		break; -	case clk_src_sclk: -		P = (nv_rd32(device, 0x004020) & 0x00070000) >> 16; -		switch (mast & 0x00000030) { -		case 0x00000000: -			if (mast & 0x00000080) -				return read_clk(dev, clk_src_host) >> P; -			return read_clk(dev, clk_src_crystal) >> P; -		case 0x00000010: break; -		case 0x00000020: return read_pll(dev, 0x004028) >> P; -		case 0x00000030: return read_pll(dev, 0x004020) >> P; -		} -		break; -	case clk_src_mclk: -		P = (nv_rd32(device, 0x004008) & 0x00070000) >> 16; -		if (nv_rd32(device, 0x004008) & 0x00000200) { -			switch (mast & 0x0000c000) { -			case 0x00000000: -				return read_clk(dev, clk_src_crystal) >> P; -			case 0x00008000: -			case 0x0000c000: -				return read_clk(dev, clk_src_href) >> P; -			} -		} else { -			return read_pll(dev, 0x004008) >> P; -		} -		break; -	case clk_src_vdec: -		P = (read_div(dev) & 0x00000700) >> 8; -		switch (nv_device(drm->device)->chipset) { -		case 0x84: -		case 0x86: -		case 0x92: -		case 0x94: -		case 0x96: -		case 0xa0: -			switch (mast & 0x00000c00) { -			case 0x00000000: -				if (nv_device(drm->device)->chipset == 0xa0) /* wtf?? */ -					return read_clk(dev, clk_src_nvclk) >> P; -				return read_clk(dev, clk_src_crystal) >> P; -			case 0x00000400: -				return 0; -			case 0x00000800: -				if (mast & 0x01000000) -					return read_pll(dev, 0x004028) >> P; -				return read_pll(dev, 0x004030) >> P; -			case 0x00000c00: -				return read_clk(dev, clk_src_nvclk) >> P; -			} -			break; -		case 0x98: -			switch (mast & 0x00000c00) { -			case 0x00000000: -				return read_clk(dev, clk_src_nvclk) >> P; -			case 0x00000400: -				return 0; -			case 0x00000800: -				return read_clk(dev, clk_src_hclkm3d2) >> P; -			case 0x00000c00: -				return read_clk(dev, clk_src_mclk) >> P; -			} -			break; -		} -		break; -	case clk_src_dom6: -		switch (nv_device(drm->device)->chipset) { -		case 0x50: -		case 0xa0: -			return read_pll(dev, 0x00e810) >> 2; -		case 0x84: -		case 0x86: -		case 0x92: -		case 0x94: -		case 0x96: -		case 0x98: -			P = (read_div(dev) & 0x00000007) >> 0; -			switch (mast & 0x0c000000) { -			case 0x00000000: return read_clk(dev, clk_src_href); -			case 0x04000000: break; -			case 0x08000000: return read_clk(dev, clk_src_hclk); -			case 0x0c000000: -				return read_clk(dev, clk_src_hclkm3) >> P; -			} -			break; -		default: -			break; -		} -	default: -		break; -	} - -	NV_DEBUG(drm, "unknown clock source %d 0x%08x\n", src, mast); -	return 0; -} - -int -nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	if (nv_device(drm->device)->chipset == 0xaa || -	    nv_device(drm->device)->chipset == 0xac) -		return 0; - -	perflvl->core   = read_clk(dev, clk_src_nvclk); -	perflvl->shader = read_clk(dev, clk_src_sclk); -	perflvl->memory = read_clk(dev, clk_src_mclk); -	if (nv_device(drm->device)->chipset != 0x50) { -		perflvl->vdec = read_clk(dev, clk_src_vdec); -		perflvl->dom6 = read_clk(dev, clk_src_dom6); -	} - -	return 0; -} - -struct nv50_pm_state { -	struct nouveau_pm_level *perflvl; -	struct hwsq_ucode eclk_hwsq; -	struct hwsq_ucode mclk_hwsq; -	u32 mscript; -	u32 mmast; -	u32 mctrl; -	u32 mcoef; -}; - -static u32 -calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, -	 u32 clk, int *N1, int *M1, int *log2P) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nouveau_clock *pclk = nouveau_clock(device); -	struct nouveau_pll_vals coef; -	int ret; - -	ret = nvbios_pll_parse(bios, reg, pll); -	if (ret) -		return 0; - -	pll->vco2.max_freq = 0; -	pll->refclk = read_pll_ref(dev, reg); -	if (!pll->refclk) -		return 0; - -	ret = pclk->pll_calc(pclk, pll, clk, &coef); -	if (ret == 0) -		return 0; - -	*N1 = coef.N1; -	*M1 = coef.M1; -	*log2P = coef.log2P; -	return ret; -} - -static inline u32 -calc_div(u32 src, u32 target, int *div) -{ -	u32 clk0 = src, clk1 = src; -	for (*div = 0; *div <= 7; (*div)++) { -		if (clk0 <= target) { -			clk1 = clk0 << (*div ? 1 : 0); -			break; -		} -		clk0 >>= 1; -	} - -	if (target - clk0 <= clk1 - target) -		return clk0; -	(*div)--; -	return clk1; -} - -static inline u32 -clk_same(u32 a, u32 b) -{ -	return ((a / 1000) == (b / 1000)); -} - -static void -mclk_precharge(struct nouveau_mem_exec_func *exec) -{ -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; - -	hwsq_wr32(hwsq, 0x1002d4, 0x00000001); -} - -static void -mclk_refresh(struct nouveau_mem_exec_func *exec) -{ -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; - -	hwsq_wr32(hwsq, 0x1002d0, 0x00000001); -} - -static void -mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) -{ -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; - -	hwsq_wr32(hwsq, 0x100210, enable ? 0x80000000 : 0x00000000); -} - -static void -mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) -{ -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; - -	hwsq_wr32(hwsq, 0x1002dc, enable ? 0x00000001 : 0x00000000); -} - -static void -mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) -{ -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; - -	if (nsec > 1000) -		hwsq_usec(hwsq, (nsec + 500) / 1000); -} - -static u32 -mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	if (mr <= 1) -		return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4)); -	if (mr <= 3) -		return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4)); -	return 0; -} - -static void -mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; - -	if (mr <= 1) { -		if (pfb->ram->ranks > 1) -			hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); -		hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); -	} else -	if (mr <= 3) { -		if (pfb->ram->ranks > 1) -			hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); -		hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); -	} -} - -static void -mclk_clock_set(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nv50_pm_state *info = exec->priv; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; -	u32 ctrl = nv_rd32(device, 0x004008); - -	info->mmast = nv_rd32(device, 0x00c040); -	info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */ -	info->mmast |=  0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */ - -	hwsq_wr32(hwsq, 0xc040, info->mmast); -	hwsq_wr32(hwsq, 0x4008, ctrl | 0x00000200); /* bypass MPLL */ -	if (info->mctrl & 0x80000000) -		hwsq_wr32(hwsq, 0x400c, info->mcoef); -	hwsq_wr32(hwsq, 0x4008, info->mctrl); -} - -static void -mclk_timing_set(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nv50_pm_state *info = exec->priv; -	struct nouveau_pm_level *perflvl = info->perflvl; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; -	int i; - -	for (i = 0; i < 9; i++) { -		u32 reg = 0x100220 + (i * 4); -		u32 val = nv_rd32(device, reg); -		if (val != perflvl->timing.reg[i]) -			hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]); -	} -} - -static int -calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, -	  struct nv50_pm_state *info) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_device *device = nouveau_dev(dev); -	u32 crtc_mask = 0; /*XXX: nv50_display_active_crtcs(dev); */ -	struct nouveau_mem_exec_func exec = { -		.dev = dev, -		.precharge = mclk_precharge, -		.refresh = mclk_refresh, -		.refresh_auto = mclk_refresh_auto, -		.refresh_self = mclk_refresh_self, -		.wait = mclk_wait, -		.mrg = mclk_mrg, -		.mrs = mclk_mrs, -		.clock_set = mclk_clock_set, -		.timing_set = mclk_timing_set, -		.priv = info -	}; -	struct hwsq_ucode *hwsq = &info->mclk_hwsq; -	struct nvbios_pll pll; -	int N, M, P; -	int ret; - -	/* use pcie refclock if possible, otherwise use mpll */ -	info->mctrl  = nv_rd32(device, 0x004008); -	info->mctrl &= ~0x81ff0200; -	if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { -		info->mctrl |= 0x00000200 | (pll.bias_p << 19); -	} else { -		ret = calc_pll(dev, 0x4008, &pll, perflvl->memory, &N, &M, &P); -		if (ret == 0) -			return -EINVAL; - -		info->mctrl |= 0x80000000 | (P << 22) | (P << 16); -		info->mctrl |= pll.bias_p << 19; -		info->mcoef  = (N << 8) | M; -	} - -	/* build the ucode which will reclock the memory for us */ -	hwsq_init(hwsq); -	if (crtc_mask) { -		hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */ -		hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */ -	} -	if (nv_device(drm->device)->chipset >= 0x92) -		hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */ -	hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ -	hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ - -	ret = nouveau_mem_exec(&exec, perflvl); -	if (ret) -		return ret; - -	hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ -	hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ -	if (nv_device(drm->device)->chipset >= 0x92) -		hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */ -	hwsq_fini(hwsq); -	return 0; -} - -void * -nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nv50_pm_state *info; -	struct hwsq_ucode *hwsq; -	struct nvbios_pll pll; -	u32 out, mast, divs, ctrl; -	int clk, ret = -EINVAL; -	int N, M, P1, P2; - -	if (nv_device(drm->device)->chipset == 0xaa || -	    nv_device(drm->device)->chipset == 0xac) -		return ERR_PTR(-ENODEV); - -	info = kmalloc(sizeof(*info), GFP_KERNEL); -	if (!info) -		return ERR_PTR(-ENOMEM); -	info->perflvl = perflvl; - -	/* memory: build hwsq ucode which we'll use to reclock memory. -	 *         use pcie refclock if possible, otherwise use mpll */ -	info->mclk_hwsq.len = 0; -	if (perflvl->memory) { -		ret = calc_mclk(dev, perflvl, info); -		if (ret) -			goto error; -		info->mscript = perflvl->memscript; -	} - -	divs = read_div(dev); -	mast = info->mmast; - -	/* start building HWSQ script for engine reclocking */ -	hwsq = &info->eclk_hwsq; -	hwsq_init(hwsq); -	hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ -	hwsq_op5f(hwsq, 0x00, 0x01); /* wait for access disabled? */ - -	/* vdec/dom6: switch to "safe" clocks temporarily */ -	if (perflvl->vdec) { -		mast &= ~0x00000c00; -		divs &= ~0x00000700; -	} - -	if (perflvl->dom6) { -		mast &= ~0x0c000000; -		divs &= ~0x00000007; -	} - -	hwsq_wr32(hwsq, 0x00c040, mast); - -	/* vdec: avoid modifying xpll until we know exactly how the other -	 * clock domains work, i suspect at least some of them can also be -	 * tied to xpll... -	 */ -	if (perflvl->vdec) { -		/* see how close we can get using nvclk as a source */ -		clk = calc_div(perflvl->core, perflvl->vdec, &P1); - -		/* see how close we can get using xpll/hclk as a source */ -		if (nv_device(drm->device)->chipset != 0x98) -			out = read_pll(dev, 0x004030); -		else -			out = read_clk(dev, clk_src_hclkm3d2); -		out = calc_div(out, perflvl->vdec, &P2); - -		/* select whichever gets us closest */ -		if (abs((int)perflvl->vdec - clk) <= -		    abs((int)perflvl->vdec - out)) { -			if (nv_device(drm->device)->chipset != 0x98) -				mast |= 0x00000c00; -			divs |= P1 << 8; -		} else { -			mast |= 0x00000800; -			divs |= P2 << 8; -		} -	} - -	/* dom6: nfi what this is, but we're limited to various combinations -	 * of the host clock frequency -	 */ -	if (perflvl->dom6) { -		if (clk_same(perflvl->dom6, read_clk(dev, clk_src_href))) { -			mast |= 0x00000000; -		} else -		if (clk_same(perflvl->dom6, read_clk(dev, clk_src_hclk))) { -			mast |= 0x08000000; -		} else { -			clk = read_clk(dev, clk_src_hclk) * 3; -			clk = calc_div(clk, perflvl->dom6, &P1); - -			mast |= 0x0c000000; -			divs |= P1; -		} -	} - -	/* vdec/dom6: complete switch to new clocks */ -	switch (nv_device(drm->device)->chipset) { -	case 0x92: -	case 0x94: -	case 0x96: -		hwsq_wr32(hwsq, 0x004800, divs); -		break; -	default: -		hwsq_wr32(hwsq, 0x004700, divs); -		break; -	} - -	hwsq_wr32(hwsq, 0x00c040, mast); - -	/* core/shader: make sure sclk/nvclk are disconnected from their -	 * PLLs (nvclk to dom6, sclk to hclk) -	 */ -	if (nv_device(drm->device)->chipset < 0x92) -		mast = (mast & ~0x001000b0) | 0x00100080; -	else -		mast = (mast & ~0x000000b3) | 0x00000081; - -	hwsq_wr32(hwsq, 0x00c040, mast); - -	/* core: for the moment at least, always use nvpll */ -	clk = calc_pll(dev, 0x4028, &pll, perflvl->core, &N, &M, &P1); -	if (clk == 0) -		goto error; - -	ctrl  = nv_rd32(device, 0x004028) & ~0xc03f0100; -	mast &= ~0x00100000; -	mast |= 3; - -	hwsq_wr32(hwsq, 0x004028, 0x80000000 | (P1 << 19) | (P1 << 16) | ctrl); -	hwsq_wr32(hwsq, 0x00402c, (N << 8) | M); - -	/* shader: tie to nvclk if possible, otherwise use spll.  have to be -	 * very careful that the shader clock is at least twice the core, or -	 * some chipsets will be very unhappy.  i expect most or all of these -	 * cases will be handled by tying to nvclk, but it's possible there's -	 * corners -	 */ -	ctrl = nv_rd32(device, 0x004020) & ~0xc03f0100; - -	if (P1-- && perflvl->shader == (perflvl->core << 1)) { -		hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); -		hwsq_wr32(hwsq, 0x00c040, 0x00000020 | mast); -	} else { -		clk = calc_pll(dev, 0x4020, &pll, perflvl->shader, &N, &M, &P1); -		if (clk == 0) -			goto error; -		ctrl |= 0x80000000; - -		hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); -		hwsq_wr32(hwsq, 0x004024, (N << 8) | M); -		hwsq_wr32(hwsq, 0x00c040, 0x00000030 | mast); -	} - -	hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ -	hwsq_op5f(hwsq, 0x00, 0x00); /* wait for access enabled? */ -	hwsq_fini(hwsq); - -	return info; -error: -	kfree(info); -	return ERR_PTR(ret); -} - -static int -prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	u32 hwsq_data, hwsq_kick; -	int i; - -	if (nv_device(drm->device)->chipset < 0x94) { -		hwsq_data = 0x001400; -		hwsq_kick = 0x00000003; -	} else { -		hwsq_data = 0x080000; -		hwsq_kick = 0x00000001; -	} -	/* upload hwsq ucode */ -	nv_mask(device, 0x001098, 0x00000008, 0x00000000); -	nv_wr32(device, 0x001304, 0x00000000); -	if (nv_device(drm->device)->chipset >= 0x92) -		nv_wr32(device, 0x001318, 0x00000000); -	for (i = 0; i < hwsq->len / 4; i++) -		nv_wr32(device, hwsq_data + (i * 4), hwsq->ptr.u32[i]); -	nv_mask(device, 0x001098, 0x00000018, 0x00000018); - -	/* launch, and wait for completion */ -	nv_wr32(device, 0x00130c, hwsq_kick); -	if (!nv_wait(device, 0x001308, 0x00000100, 0x00000000)) { -		NV_ERROR(drm, "hwsq ucode exec timed out\n"); -		NV_ERROR(drm, "0x001308: 0x%08x\n", nv_rd32(device, 0x001308)); -		for (i = 0; i < hwsq->len / 4; i++) { -			NV_ERROR(drm, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), -				 nv_rd32(device, 0x001400 + (i * 4))); -		} - -		return -EIO; -	} - -	return 0; -} - -int -nv50_pm_clocks_set(struct drm_device *dev, void *data) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nv50_pm_state *info = data; -	struct bit_entry M; -	int ret = -EBUSY; - -	/* halt and idle execution engines */ -	nv_mask(device, 0x002504, 0x00000001, 0x00000001); -	if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010)) -		goto resume; -	if (!nv_wait(device, 0x00251c, 0x0000003f, 0x0000003f)) -		goto resume; - -	/* program memory clock, if necessary - must come before engine clock -	 * reprogramming due to how we construct the hwsq scripts in pre() -	 */ -#define nouveau_bios_init_exec(a,b) nouveau_bios_run_init_table((a), (b), NULL, 0) -	if (info->mclk_hwsq.len) { -		/* execute some scripts that do ??? from the vbios.. */ -		if (!bit_table(dev, 'M', &M) && M.version == 1) { -			if (M.length >= 6) -				nouveau_bios_init_exec(dev, ROM16(M.data[5])); -			if (M.length >= 8) -				nouveau_bios_init_exec(dev, ROM16(M.data[7])); -			if (M.length >= 10) -				nouveau_bios_init_exec(dev, ROM16(M.data[9])); -			nouveau_bios_init_exec(dev, info->mscript); -		} - -		ret = prog_hwsq(dev, &info->mclk_hwsq); -		if (ret) -			goto resume; -	} - -	/* program engine clocks */ -	ret = prog_hwsq(dev, &info->eclk_hwsq); - -resume: -	nv_mask(device, 0x002504, 0x00000001, 0x00000000); -	kfree(info); -	return ret; -} diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c deleted file mode 100644 index 0d0ed597fea..00000000000 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include <drm/drmP.h> -#include "nouveau_drm.h" -#include "nouveau_bios.h" -#include "nouveau_pm.h" - -#include <subdev/bios/pll.h> -#include <subdev/bios.h> -#include <subdev/clock.h> -#include <subdev/timer.h> -#include <subdev/fb.h> - -static u32 read_clk(struct drm_device *, int, bool); -static u32 read_pll(struct drm_device *, int, u32); - -static u32 -read_vco(struct drm_device *dev, int clk) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 sctl = nv_rd32(device, 0x4120 + (clk * 4)); -	if ((sctl & 0x00000030) != 0x00000030) -		return read_pll(dev, 0x41, 0x00e820); -	return read_pll(dev, 0x42, 0x00e8a0); -} - -static u32 -read_clk(struct drm_device *dev, int clk, bool ignore_en) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	u32 sctl, sdiv, sclk; - -	/* refclk for the 0xe8xx plls is a fixed frequency */ -	if (clk >= 0x40) { -		if (nv_device(drm->device)->chipset == 0xaf) { -			/* no joke.. seriously.. sigh.. */ -			return nv_rd32(device, 0x00471c) * 1000; -		} - -		return device->crystal; -	} - -	sctl = nv_rd32(device, 0x4120 + (clk * 4)); -	if (!ignore_en && !(sctl & 0x00000100)) -		return 0; - -	switch (sctl & 0x00003000) { -	case 0x00000000: -		return device->crystal; -	case 0x00002000: -		if (sctl & 0x00000040) -			return 108000; -		return 100000; -	case 0x00003000: -		sclk = read_vco(dev, clk); -		sdiv = ((sctl & 0x003f0000) >> 16) + 2; -		return (sclk * 2) / sdiv; -	default: -		return 0; -	} -} - -static u32 -read_pll(struct drm_device *dev, int clk, u32 pll) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ctrl = nv_rd32(device, pll + 0); -	u32 sclk = 0, P = 1, N = 1, M = 1; - -	if (!(ctrl & 0x00000008)) { -		if (ctrl & 0x00000001) { -			u32 coef = nv_rd32(device, pll + 4); -			M = (coef & 0x000000ff) >> 0; -			N = (coef & 0x0000ff00) >> 8; -			P = (coef & 0x003f0000) >> 16; - -			/* no post-divider on these.. */ -			if ((pll & 0x00ff00) == 0x00e800) -				P = 1; - -			sclk = read_clk(dev, 0x00 + clk, false); -		} -	} else { -		sclk = read_clk(dev, 0x10 + clk, false); -	} - -	if (M * P) -		return sclk * N / (M * P); -	return 0; -} - -struct creg { -	u32 clk; -	u32 pll; -}; - -static int -calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) -{ -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nvbios_pll limits; -	u32 oclk, sclk, sdiv; -	int P, N, M, diff; -	int ret; - -	reg->pll = 0; -	reg->clk = 0; -	if (!khz) { -		NV_DEBUG(drm, "no clock for 0x%04x/0x%02x\n", pll, clk); -		return 0; -	} - -	switch (khz) { -	case 27000: -		reg->clk = 0x00000100; -		return khz; -	case 100000: -		reg->clk = 0x00002100; -		return khz; -	case 108000: -		reg->clk = 0x00002140; -		return khz; -	default: -		sclk = read_vco(dev, clk); -		sdiv = min((sclk * 2) / (khz - 2999), (u32)65); -		/* if the clock has a PLL attached, and we can get a within -		 * [-2, 3) MHz of a divider, we'll disable the PLL and use -		 * the divider instead. -		 * -		 * divider can go as low as 2, limited here because NVIDIA -		 * and the VBIOS on my NVA8 seem to prefer using the PLL -		 * for 810MHz - is there a good reason? -		 */ -		if (sdiv > 4) { -			oclk = (sclk * 2) / sdiv; -			diff = khz - oclk; -			if (!pll || (diff >= -2000 && diff < 3000)) { -				reg->clk = (((sdiv - 2) << 16) | 0x00003100); -				return oclk; -			} -		} - -		if (!pll) { -			NV_ERROR(drm, "bad freq %02x: %d %d\n", clk, khz, sclk); -			return -ERANGE; -		} - -		break; -	} - -	ret = nvbios_pll_parse(bios, pll, &limits); -	if (ret) -		return ret; - -	limits.refclk = read_clk(dev, clk - 0x10, true); -	if (!limits.refclk) -		return -EINVAL; - -	ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); -	if (ret >= 0) { -		reg->clk = nv_rd32(device, 0x4120 + (clk * 4)); -		reg->pll = (P << 16) | (N << 8) | M; -	} - -	return ret; -} - -static void -prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	const u32 src0 = 0x004120 + (clk * 4); -	const u32 src1 = 0x004160 + (clk * 4); -	const u32 ctrl = pll + 0; -	const u32 coef = pll + 4; - -	if (!reg->clk && !reg->pll) { -		NV_DEBUG(drm, "no clock for %02x\n", clk); -		return; -	} - -	if (reg->pll) { -		nv_mask(device, src0, 0x00000101, 0x00000101); -		nv_wr32(device, coef, reg->pll); -		nv_mask(device, ctrl, 0x00000015, 0x00000015); -		nv_mask(device, ctrl, 0x00000010, 0x00000000); -		nv_wait(device, ctrl, 0x00020000, 0x00020000); -		nv_mask(device, ctrl, 0x00000010, 0x00000010); -		nv_mask(device, ctrl, 0x00000008, 0x00000000); -		nv_mask(device, src1, 0x00000100, 0x00000000); -		nv_mask(device, src1, 0x00000001, 0x00000000); -	} else { -		nv_mask(device, src1, 0x003f3141, 0x00000101 | reg->clk); -		nv_mask(device, ctrl, 0x00000018, 0x00000018); -		udelay(20); -		nv_mask(device, ctrl, 0x00000001, 0x00000000); -		nv_mask(device, src0, 0x00000100, 0x00000000); -		nv_mask(device, src0, 0x00000001, 0x00000000); -	} -} - -static void -prog_clk(struct drm_device *dev, int clk, struct creg *reg) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); - -	if (!reg->clk) { -		NV_DEBUG(drm, "no clock for %02x\n", clk); -		return; -	} - -	nv_mask(device, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); -} - -int -nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	perflvl->core   = read_pll(dev, 0x00, 0x4200); -	perflvl->shader = read_pll(dev, 0x01, 0x4220); -	perflvl->memory = read_pll(dev, 0x02, 0x4000); -	perflvl->unka0  = read_clk(dev, 0x20, false); -	perflvl->vdec   = read_clk(dev, 0x21, false); -	perflvl->daemon = read_clk(dev, 0x25, false); -	perflvl->copy   = perflvl->core; -	return 0; -} - -struct nva3_pm_state { -	struct nouveau_pm_level *perflvl; - -	struct creg nclk; -	struct creg sclk; -	struct creg vdec; -	struct creg unka0; - -	struct creg mclk; -	u8 *rammap; -	u8  rammap_ver; -	u8  rammap_len; -	u8 *ramcfg; -	u8  ramcfg_len; -	u32 r004018; -	u32 r100760; -}; - -void * -nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nva3_pm_state *info; -	u8 ramcfg_cnt; -	int ret; - -	info = kzalloc(sizeof(*info), GFP_KERNEL); -	if (!info) -		return ERR_PTR(-ENOMEM); - -	ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); -	if (ret < 0) -		goto out; - -	ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); -	if (ret < 0) -		goto out; - -	ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); -	if (ret < 0) -		goto out; - -	ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0); -	if (ret < 0) -		goto out; - -	ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec); -	if (ret < 0) -		goto out; - -	info->rammap = nouveau_perf_rammap(dev, perflvl->memory, -					   &info->rammap_ver, -					   &info->rammap_len, -					   &ramcfg_cnt, &info->ramcfg_len); -	if (info->rammap_ver != 0x10 || info->rammap_len < 5) -		info->rammap = NULL; - -	info->ramcfg = nouveau_perf_ramcfg(dev, perflvl->memory, -					   &info->rammap_ver, -					   &info->ramcfg_len); -	if (info->rammap_ver != 0x10) -		info->ramcfg = NULL; - -	info->perflvl = perflvl; -out: -	if (ret < 0) { -		kfree(info); -		info = ERR_PTR(ret); -	} -	return info; -} - -static bool -nva3_pm_grcp_idle(void *data) -{ -	struct drm_device *dev = data; -	struct nouveau_device *device = nouveau_dev(dev); - -	if (!(nv_rd32(device, 0x400304) & 0x00000001)) -		return true; -	if (nv_rd32(device, 0x400308) == 0x0050001c) -		return true; -	return false; -} - -static void -mclk_precharge(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	nv_wr32(device, 0x1002d4, 0x00000001); -} - -static void -mclk_refresh(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	nv_wr32(device, 0x1002d0, 0x00000001); -} - -static void -mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	nv_wr32(device, 0x100210, enable ? 0x80000000 : 0x00000000); -} - -static void -mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	nv_wr32(device, 0x1002dc, enable ? 0x00000001 : 0x00000000); -} - -static void -mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	volatile u32 post = nv_rd32(device, 0); (void)post; -	udelay((nsec + 500) / 1000); -} - -static u32 -mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	if (mr <= 1) -		return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4)); -	if (mr <= 3) -		return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4)); -	return 0; -} - -static void -mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	if (mr <= 1) { -		if (pfb->ram->ranks > 1) -			nv_wr32(device, 0x1002c8 + ((mr - 0) * 4), data); -		nv_wr32(device, 0x1002c0 + ((mr - 0) * 4), data); -	} else -	if (mr <= 3) { -		if (pfb->ram->ranks > 1) -			nv_wr32(device, 0x1002e8 + ((mr - 2) * 4), data); -		nv_wr32(device, 0x1002e0 + ((mr - 2) * 4), data); -	} -} - -static void -mclk_clock_set(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nva3_pm_state *info = exec->priv; -	u32 ctrl; - -	ctrl = nv_rd32(device, 0x004000); -	if (!(ctrl & 0x00000008) && info->mclk.pll) { -		nv_wr32(device, 0x004000, (ctrl |=  0x00000008)); -		nv_mask(device, 0x1110e0, 0x00088000, 0x00088000); -		nv_wr32(device, 0x004018, 0x00001000); -		nv_wr32(device, 0x004000, (ctrl &= ~0x00000001)); -		nv_wr32(device, 0x004004, info->mclk.pll); -		nv_wr32(device, 0x004000, (ctrl |=  0x00000001)); -		udelay(64); -		nv_wr32(device, 0x004018, 0x00005000 | info->r004018); -		udelay(20); -	} else -	if (!info->mclk.pll) { -		nv_mask(device, 0x004168, 0x003f3040, info->mclk.clk); -		nv_wr32(device, 0x004000, (ctrl |= 0x00000008)); -		nv_mask(device, 0x1110e0, 0x00088000, 0x00088000); -		nv_wr32(device, 0x004018, 0x0000d000 | info->r004018); -	} - -	if (info->rammap) { -		if (info->ramcfg && (info->rammap[4] & 0x08)) { -			u32 unk5a0 = (ROM16(info->ramcfg[5]) << 8) | -				      info->ramcfg[5]; -			u32 unk5a4 = ROM16(info->ramcfg[7]); -			u32 unk804 = (info->ramcfg[9] & 0xf0) << 16 | -				     (info->ramcfg[3] & 0x0f) << 16 | -				     (info->ramcfg[9] & 0x0f) | -				     0x80000000; -			nv_wr32(device, 0x1005a0, unk5a0); -			nv_wr32(device, 0x1005a4, unk5a4); -			nv_wr32(device, 0x10f804, unk804); -			nv_mask(device, 0x10053c, 0x00001000, 0x00000000); -		} else { -			nv_mask(device, 0x10053c, 0x00001000, 0x00001000); -			nv_mask(device, 0x10f804, 0x80000000, 0x00000000); -			nv_mask(device, 0x100760, 0x22222222, info->r100760); -			nv_mask(device, 0x1007a0, 0x22222222, info->r100760); -			nv_mask(device, 0x1007e0, 0x22222222, info->r100760); -		} -	} - -	if (info->mclk.pll) { -		nv_mask(device, 0x1110e0, 0x00088000, 0x00011000); -		nv_wr32(device, 0x004000, (ctrl &= ~0x00000008)); -	} -} - -static void -mclk_timing_set(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nva3_pm_state *info = exec->priv; -	struct nouveau_pm_level *perflvl = info->perflvl; -	int i; - -	for (i = 0; i < 9; i++) -		nv_wr32(device, 0x100220 + (i * 4), perflvl->timing.reg[i]); - -	if (info->ramcfg) { -		u32 data = (info->ramcfg[2] & 0x08) ? 0x00000000 : 0x00001000; -		nv_mask(device, 0x100200, 0x00001000, data); -	} - -	if (info->ramcfg) { -		u32 unk714 = nv_rd32(device, 0x100714) & ~0xf0000010; -		u32 unk718 = nv_rd32(device, 0x100718) & ~0x00000100; -		u32 unk71c = nv_rd32(device, 0x10071c) & ~0x00000100; -		if ( (info->ramcfg[2] & 0x20)) -			unk714 |= 0xf0000000; -		if (!(info->ramcfg[2] & 0x04)) -			unk714 |= 0x00000010; -		nv_wr32(device, 0x100714, unk714); - -		if (info->ramcfg[2] & 0x01) -			unk71c |= 0x00000100; -		nv_wr32(device, 0x10071c, unk71c); - -		if (info->ramcfg[2] & 0x02) -			unk718 |= 0x00000100; -		nv_wr32(device, 0x100718, unk718); - -		if (info->ramcfg[2] & 0x10) -			nv_wr32(device, 0x111100, 0x48000000); /*XXX*/ -	} -} - -static void -prog_mem(struct drm_device *dev, struct nva3_pm_state *info) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_mem_exec_func exec = { -		.dev = dev, -		.precharge = mclk_precharge, -		.refresh = mclk_refresh, -		.refresh_auto = mclk_refresh_auto, -		.refresh_self = mclk_refresh_self, -		.wait = mclk_wait, -		.mrg = mclk_mrg, -		.mrs = mclk_mrs, -		.clock_set = mclk_clock_set, -		.timing_set = mclk_timing_set, -		.priv = info -	}; -	u32 ctrl; - -	/* XXX: where the fuck does 750MHz come from? */ -	if (info->perflvl->memory <= 750000) { -		info->r004018 = 0x10000000; -		info->r100760 = 0x22222222; -	} - -	ctrl = nv_rd32(device, 0x004000); -	if (ctrl & 0x00000008) { -		if (info->mclk.pll) { -			nv_mask(device, 0x004128, 0x00000101, 0x00000101); -			nv_wr32(device, 0x004004, info->mclk.pll); -			nv_wr32(device, 0x004000, (ctrl |= 0x00000001)); -			nv_wr32(device, 0x004000, (ctrl &= 0xffffffef)); -			nv_wait(device, 0x004000, 0x00020000, 0x00020000); -			nv_wr32(device, 0x004000, (ctrl |= 0x00000010)); -			nv_wr32(device, 0x004018, 0x00005000 | info->r004018); -			nv_wr32(device, 0x004000, (ctrl |= 0x00000004)); -		} -	} else { -		u32 ssel = 0x00000101; -		if (info->mclk.clk) -			ssel |= info->mclk.clk; -		else -			ssel |= 0x00080000; /* 324MHz, shouldn't matter... */ -		nv_mask(device, 0x004168, 0x003f3141, ctrl); -	} - -	if (info->ramcfg) { -		if (info->ramcfg[2] & 0x10) { -			nv_mask(device, 0x111104, 0x00000600, 0x00000000); -		} else { -			nv_mask(device, 0x111100, 0x40000000, 0x40000000); -			nv_mask(device, 0x111104, 0x00000180, 0x00000000); -		} -	} -	if (info->rammap && !(info->rammap[4] & 0x02)) -		nv_mask(device, 0x100200, 0x00000800, 0x00000000); -	nv_wr32(device, 0x611200, 0x00003300); -	if (!(info->ramcfg[2] & 0x10)) -		nv_wr32(device, 0x111100, 0x4c020000); /*XXX*/ - -	nouveau_mem_exec(&exec, info->perflvl); - -	nv_wr32(device, 0x611200, 0x00003330); -	if (info->rammap && (info->rammap[4] & 0x02)) -		nv_mask(device, 0x100200, 0x00000800, 0x00000800); -	if (info->ramcfg) { -		if (info->ramcfg[2] & 0x10) { -			nv_mask(device, 0x111104, 0x00000180, 0x00000180); -			nv_mask(device, 0x111100, 0x40000000, 0x00000000); -		} else { -			nv_mask(device, 0x111104, 0x00000600, 0x00000600); -		} -	} - -	if (info->mclk.pll) { -		nv_mask(device, 0x004168, 0x00000001, 0x00000000); -		nv_mask(device, 0x004168, 0x00000100, 0x00000000); -	} else { -		nv_mask(device, 0x004000, 0x00000001, 0x00000000); -		nv_mask(device, 0x004128, 0x00000001, 0x00000000); -		nv_mask(device, 0x004128, 0x00000100, 0x00000000); -	} -} - -int -nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_drm *drm = nouveau_drm(dev); -	struct nva3_pm_state *info = pre_state; -	int ret = -EAGAIN; - -	/* prevent any new grctx switches from starting */ -	nv_wr32(device, 0x400324, 0x00000000); -	nv_wr32(device, 0x400328, 0x0050001c); /* wait flag 0x1c */ -	/* wait for any pending grctx switches to complete */ -	if (!nv_wait_cb(device, nva3_pm_grcp_idle, dev)) { -		NV_ERROR(drm, "pm: ctxprog didn't go idle\n"); -		goto cleanup; -	} -	/* freeze PFIFO */ -	nv_mask(device, 0x002504, 0x00000001, 0x00000001); -	if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010)) { -		NV_ERROR(drm, "pm: fifo didn't go idle\n"); -		goto cleanup; -	} - -	prog_pll(dev, 0x00, 0x004200, &info->nclk); -	prog_pll(dev, 0x01, 0x004220, &info->sclk); -	prog_clk(dev, 0x20, &info->unka0); -	prog_clk(dev, 0x21, &info->vdec); - -	if (info->mclk.clk || info->mclk.pll) -		prog_mem(dev, info); - -	ret = 0; - -cleanup: -	/* unfreeze PFIFO */ -	nv_mask(device, 0x002504, 0x00000001, 0x00000000); -	/* restore ctxprog to normal */ -	nv_wr32(device, 0x400324, 0x00000000); -	nv_wr32(device, 0x400328, 0x0070009c); /* set flag 0x1c */ -	/* unblock it if necessary */ -	if (nv_rd32(device, 0x400308) == 0x0050001c) -		nv_mask(device, 0x400824, 0x10000000, 0x10000000); -	kfree(info); -	return ret; -} diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c deleted file mode 100644 index 3b7041cb013..00000000000 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "nouveau_drm.h" -#include "nouveau_bios.h" -#include "nouveau_pm.h" - -#include <subdev/bios/pll.h> -#include <subdev/bios.h> -#include <subdev/clock.h> -#include <subdev/timer.h> -#include <subdev/fb.h> - -static u32 read_div(struct drm_device *, int, u32, u32); -static u32 read_pll(struct drm_device *, u32); - -static u32 -read_vco(struct drm_device *dev, u32 dsrc) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ssrc = nv_rd32(device, dsrc); -	if (!(ssrc & 0x00000100)) -		return read_pll(dev, 0x00e800); -	return read_pll(dev, 0x00e820); -} - -static u32 -read_pll(struct drm_device *dev, u32 pll) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ctrl = nv_rd32(device, pll + 0); -	u32 coef = nv_rd32(device, pll + 4); -	u32 P = (coef & 0x003f0000) >> 16; -	u32 N = (coef & 0x0000ff00) >> 8; -	u32 M = (coef & 0x000000ff) >> 0; -	u32 sclk, doff; - -	if (!(ctrl & 0x00000001)) -		return 0; - -	switch (pll & 0xfff000) { -	case 0x00e000: -		sclk = 27000; -		P = 1; -		break; -	case 0x137000: -		doff = (pll - 0x137000) / 0x20; -		sclk = read_div(dev, doff, 0x137120, 0x137140); -		break; -	case 0x132000: -		switch (pll) { -		case 0x132000: -			sclk = read_pll(dev, 0x132020); -			break; -		case 0x132020: -			sclk = read_div(dev, 0, 0x137320, 0x137330); -			break; -		default: -			return 0; -		} -		break; -	default: -		return 0; -	} - -	return sclk * N / M / P; -} - -static u32 -read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ssrc = nv_rd32(device, dsrc + (doff * 4)); -	u32 sctl = nv_rd32(device, dctl + (doff * 4)); - -	switch (ssrc & 0x00000003) { -	case 0: -		if ((ssrc & 0x00030000) != 0x00030000) -			return 27000; -		return 108000; -	case 2: -		return 100000; -	case 3: -		if (sctl & 0x80000000) { -			u32 sclk = read_vco(dev, dsrc + (doff * 4)); -			u32 sdiv = (sctl & 0x0000003f) + 2; -			return (sclk * 2) / sdiv; -		} - -		return read_vco(dev, dsrc + (doff * 4)); -	default: -		return 0; -	} -} - -static u32 -read_mem(struct drm_device *dev) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 ssel = nv_rd32(device, 0x1373f0); -	if (ssel & 0x00000001) -		return read_div(dev, 0, 0x137300, 0x137310); -	return read_pll(dev, 0x132000); -} - -static u32 -read_clk(struct drm_device *dev, int clk) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	u32 sctl = nv_rd32(device, 0x137250 + (clk * 4)); -	u32 ssel = nv_rd32(device, 0x137100); -	u32 sclk, sdiv; - -	if (ssel & (1 << clk)) { -		if (clk < 7) -			sclk = read_pll(dev, 0x137000 + (clk * 0x20)); -		else -			sclk = read_pll(dev, 0x1370e0); -		sdiv = ((sctl & 0x00003f00) >> 8) + 2; -	} else { -		sclk = read_div(dev, clk, 0x137160, 0x1371d0); -		sdiv = ((sctl & 0x0000003f) >> 0) + 2; -	} - -	if (sctl & 0x80000000) -		return (sclk * 2) / sdiv; -	return sclk; -} - -int -nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	perflvl->shader = read_clk(dev, 0x00); -	perflvl->core   = perflvl->shader / 2; -	perflvl->memory = read_mem(dev); -	perflvl->rop    = read_clk(dev, 0x01); -	perflvl->hub07  = read_clk(dev, 0x02); -	perflvl->hub06  = read_clk(dev, 0x07); -	perflvl->hub01  = read_clk(dev, 0x08); -	perflvl->copy   = read_clk(dev, 0x09); -	perflvl->daemon = read_clk(dev, 0x0c); -	perflvl->vdec   = read_clk(dev, 0x0e); -	return 0; -} - -struct nvc0_pm_clock { -	u32 freq; -	u32 ssel; -	u32 mdiv; -	u32 dsrc; -	u32 ddiv; -	u32 coef; -}; - -struct nvc0_pm_state { -	struct nouveau_pm_level *perflvl; -	struct nvc0_pm_clock eng[16]; -	struct nvc0_pm_clock mem; -}; - -static u32 -calc_div(struct drm_device *dev, int clk, u32 ref, u32 freq, u32 *ddiv) -{ -	u32 div = min((ref * 2) / freq, (u32)65); -	if (div < 2) -		div = 2; - -	*ddiv = div - 2; -	return (ref * 2) / div; -} - -static u32 -calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) -{ -	u32 sclk; - -	/* use one of the fixed frequencies if possible */ -	*ddiv = 0x00000000; -	switch (freq) { -	case  27000: -	case 108000: -		*dsrc = 0x00000000; -		if (freq == 108000) -			*dsrc |= 0x00030000; -		return freq; -	case 100000: -		*dsrc = 0x00000002; -		return freq; -	default: -		*dsrc = 0x00000003; -		break; -	} - -	/* otherwise, calculate the closest divider */ -	sclk = read_vco(dev, clk); -	if (clk < 7) -		sclk = calc_div(dev, clk, sclk, freq, ddiv); -	return sclk; -} - -static u32 -calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nvbios_pll limits; -	int N, M, P, ret; - -	ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); -	if (ret) -		return 0; - -	limits.refclk = read_div(dev, clk, 0x137120, 0x137140); -	if (!limits.refclk) -		return 0; - -	ret = nva3_calc_pll(dev, &limits, freq, &N, NULL, &M, &P); -	if (ret <= 0) -		return 0; - -	*coef = (P << 16) | (N << 8) | M; -	return ret; -} - -/* A (likely rather simplified and incomplete) view of the clock tree - * - * Key: - * - * S: source select - * D: divider - * P: pll - * F: switch - * - * Engine clocks: - * - * 137250(D) ---- 137100(F0) ---- 137160(S)/1371d0(D) ------------------- ref - *                      (F1) ---- 1370X0(P) ---- 137120(S)/137140(D) ---- ref - * - * Not all registers exist for all clocks.  For example: clocks >= 8 don't - * have their own PLL (all tied to clock 7's PLL when in PLL mode), nor do - * they have the divider at 1371d0, though the source selection at 137160 - * still exists.  You must use the divider at 137250 for these instead. - * - * Memory clock: - * - * TBD, read_mem() above is likely very wrong... - * - */ - -static int -calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) -{ -	u32 src0, div0, div1D, div1P = 0; -	u32 clk0, clk1 = 0; - -	/* invalid clock domain */ -	if (!freq) -		return 0; - -	/* first possible path, using only dividers */ -	clk0 = calc_src(dev, clk, freq, &src0, &div0); -	clk0 = calc_div(dev, clk, clk0, freq, &div1D); - -	/* see if we can get any closer using PLLs */ -	if (clk0 != freq && (0x00004387 & (1 << clk))) { -		if (clk < 7) -			clk1 = calc_pll(dev, clk, freq, &info->coef); -		else -			clk1 = read_pll(dev, 0x1370e0); -		clk1 = calc_div(dev, clk, clk1, freq, &div1P); -	} - -	/* select the method which gets closest to target freq */ -	if (abs((int)freq - clk0) <= abs((int)freq - clk1)) { -		info->dsrc = src0; -		if (div0) { -			info->ddiv |= 0x80000000; -			info->ddiv |= div0 << 8; -			info->ddiv |= div0; -		} -		if (div1D) { -			info->mdiv |= 0x80000000; -			info->mdiv |= div1D; -		} -		info->ssel = 0; -		info->freq = clk0; -	} else { -		if (div1P) { -			info->mdiv |= 0x80000000; -			info->mdiv |= div1P << 8; -		} -		info->ssel = (1 << clk); -		info->freq = clk1; -	} - -	return 0; -} - -static int -calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_bios *bios = nouveau_bios(device); -	struct nvbios_pll pll; -	int N, M, P, ret; -	u32 ctrl; - -	/* mclk pll input freq comes from another pll, make sure it's on */ -	ctrl = nv_rd32(device, 0x132020); -	if (!(ctrl & 0x00000001)) { -		/* if not, program it to 567MHz.  nfi where this value comes -		 * from - it looks like it's in the pll limits table for -		 * 132000 but the binary driver ignores all my attempts to -		 * change this value. -		 */ -		nv_wr32(device, 0x137320, 0x00000103); -		nv_wr32(device, 0x137330, 0x81200606); -		nv_wait(device, 0x132020, 0x00010000, 0x00010000); -		nv_wr32(device, 0x132024, 0x0001150f); -		nv_mask(device, 0x132020, 0x00000001, 0x00000001); -		nv_wait(device, 0x137390, 0x00020000, 0x00020000); -		nv_mask(device, 0x132020, 0x00000004, 0x00000004); -	} - -	/* for the moment, until the clock tree is better understood, use -	 * pll mode for all clock frequencies -	 */ -	ret = nvbios_pll_parse(bios, 0x132000, &pll); -	if (ret == 0) { -		pll.refclk = read_pll(dev, 0x132020); -		if (pll.refclk) { -			ret = nva3_calc_pll(dev, &pll, freq, &N, NULL, &M, &P); -			if (ret > 0) { -				info->coef = (P << 16) | (N << 8) | M; -				return 0; -			} -		} -	} - -	return -EINVAL; -} - -void * -nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nvc0_pm_state *info; -	int ret; - -	info = kzalloc(sizeof(*info), GFP_KERNEL); -	if (!info) -		return ERR_PTR(-ENOMEM); - -	/* NFI why this is still in the performance table, the ROPCs appear -	 * to get their clock from clock 2 ("hub07", actually hub05 on this -	 * chip, but, anyway...) as well.  nvatiming confirms hub05 and ROP -	 * are always the same freq with the binary driver even when the -	 * performance table says they should differ. -	 */ -	if (device->chipset == 0xd9) -		perflvl->rop = 0; - -	if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) || -	    (ret = calc_clk(dev, 0x01, &info->eng[0x01], perflvl->rop)) || -	    (ret = calc_clk(dev, 0x02, &info->eng[0x02], perflvl->hub07)) || -	    (ret = calc_clk(dev, 0x07, &info->eng[0x07], perflvl->hub06)) || -	    (ret = calc_clk(dev, 0x08, &info->eng[0x08], perflvl->hub01)) || -	    (ret = calc_clk(dev, 0x09, &info->eng[0x09], perflvl->copy)) || -	    (ret = calc_clk(dev, 0x0c, &info->eng[0x0c], perflvl->daemon)) || -	    (ret = calc_clk(dev, 0x0e, &info->eng[0x0e], perflvl->vdec))) { -		kfree(info); -		return ERR_PTR(ret); -	} - -	if (perflvl->memory) { -		ret = calc_mem(dev, &info->mem, perflvl->memory); -		if (ret) { -			kfree(info); -			return ERR_PTR(ret); -		} -	} - -	info->perflvl = perflvl; -	return info; -} - -static void -prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info) -{ -	struct nouveau_device *device = nouveau_dev(dev); - -	/* program dividers at 137160/1371d0 first */ -	if (clk < 7 && !info->ssel) { -		nv_mask(device, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); -		nv_wr32(device, 0x137160 + (clk * 0x04), info->dsrc); -	} - -	/* switch clock to non-pll mode */ -	nv_mask(device, 0x137100, (1 << clk), 0x00000000); -	nv_wait(device, 0x137100, (1 << clk), 0x00000000); - -	/* reprogram pll */ -	if (clk < 7) { -		/* make sure it's disabled first... */ -		u32 base = 0x137000 + (clk * 0x20); -		u32 ctrl = nv_rd32(device, base + 0x00); -		if (ctrl & 0x00000001) { -			nv_mask(device, base + 0x00, 0x00000004, 0x00000000); -			nv_mask(device, base + 0x00, 0x00000001, 0x00000000); -		} -		/* program it to new values, if necessary */ -		if (info->ssel) { -			nv_wr32(device, base + 0x04, info->coef); -			nv_mask(device, base + 0x00, 0x00000001, 0x00000001); -			nv_wait(device, base + 0x00, 0x00020000, 0x00020000); -			nv_mask(device, base + 0x00, 0x00020004, 0x00000004); -		} -	} - -	/* select pll/non-pll mode, and program final clock divider */ -	nv_mask(device, 0x137100, (1 << clk), info->ssel); -	nv_wait(device, 0x137100, (1 << clk), info->ssel); -	nv_mask(device, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); -} - -static void -mclk_precharge(struct nouveau_mem_exec_func *exec) -{ -} - -static void -mclk_refresh(struct nouveau_mem_exec_func *exec) -{ -} - -static void -mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	nv_wr32(device, 0x10f210, enable ? 0x80000000 : 0x00000000); -} - -static void -mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) -{ -} - -static void -mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) -{ -	udelay((nsec + 500) / 1000); -} - -static u32 -mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	if (pfb->ram->type != NV_MEM_TYPE_GDDR5) { -		if (mr <= 1) -			return nv_rd32(device, 0x10f300 + ((mr - 0) * 4)); -		return nv_rd32(device, 0x10f320 + ((mr - 2) * 4)); -	} else { -		if (mr == 0) -			return nv_rd32(device, 0x10f300 + (mr * 4)); -		else -		if (mr <= 7) -			return nv_rd32(device, 0x10f32c + (mr * 4)); -		return nv_rd32(device, 0x10f34c); -	} -} - -static void -mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nouveau_fb *pfb = nouveau_fb(device); -	if (pfb->ram->type != NV_MEM_TYPE_GDDR5) { -		if (mr <= 1) { -			nv_wr32(device, 0x10f300 + ((mr - 0) * 4), data); -			if (pfb->ram->ranks > 1) -				nv_wr32(device, 0x10f308 + ((mr - 0) * 4), data); -		} else -		if (mr <= 3) { -			nv_wr32(device, 0x10f320 + ((mr - 2) * 4), data); -			if (pfb->ram->ranks > 1) -				nv_wr32(device, 0x10f328 + ((mr - 2) * 4), data); -		} -	} else { -		if      (mr ==  0) nv_wr32(device, 0x10f300 + (mr * 4), data); -		else if (mr <=  7) nv_wr32(device, 0x10f32c + (mr * 4), data); -		else if (mr == 15) nv_wr32(device, 0x10f34c, data); -	} -} - -static void -mclk_clock_set(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nvc0_pm_state *info = exec->priv; -	u32 ctrl = nv_rd32(device, 0x132000); - -	nv_wr32(device, 0x137360, 0x00000001); -	nv_wr32(device, 0x137370, 0x00000000); -	nv_wr32(device, 0x137380, 0x00000000); -	if (ctrl & 0x00000001) -		nv_wr32(device, 0x132000, (ctrl &= ~0x00000001)); - -	nv_wr32(device, 0x132004, info->mem.coef); -	nv_wr32(device, 0x132000, (ctrl |= 0x00000001)); -	nv_wait(device, 0x137390, 0x00000002, 0x00000002); -	nv_wr32(device, 0x132018, 0x00005000); - -	nv_wr32(device, 0x137370, 0x00000001); -	nv_wr32(device, 0x137380, 0x00000001); -	nv_wr32(device, 0x137360, 0x00000000); -} - -static void -mclk_timing_set(struct nouveau_mem_exec_func *exec) -{ -	struct nouveau_device *device = nouveau_dev(exec->dev); -	struct nvc0_pm_state *info = exec->priv; -	struct nouveau_pm_level *perflvl = info->perflvl; -	int i; - -	for (i = 0; i < 5; i++) -		nv_wr32(device, 0x10f290 + (i * 4), perflvl->timing.reg[i]); -} - -static void -prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) -{ -	struct nouveau_device *device = nouveau_dev(dev); -	struct nouveau_mem_exec_func exec = { -		.dev = dev, -		.precharge = mclk_precharge, -		.refresh = mclk_refresh, -		.refresh_auto = mclk_refresh_auto, -		.refresh_self = mclk_refresh_self, -		.wait = mclk_wait, -		.mrg = mclk_mrg, -		.mrs = mclk_mrs, -		.clock_set = mclk_clock_set, -		.timing_set = mclk_timing_set, -		.priv = info -	}; - -	if (device->chipset < 0xd0) -		nv_wr32(device, 0x611200, 0x00003300); -	else -		nv_wr32(device, 0x62c000, 0x03030000); - -	nouveau_mem_exec(&exec, info->perflvl); - -	if (device->chipset < 0xd0) -		nv_wr32(device, 0x611200, 0x00003330); -	else -		nv_wr32(device, 0x62c000, 0x03030300); -} -int -nvc0_pm_clocks_set(struct drm_device *dev, void *data) -{ -	struct nvc0_pm_state *info = data; -	int i; - -	if (info->mem.coef) -		prog_mem(dev, info); - -	for (i = 0; i < 16; i++) { -		if (!info->eng[i].freq) -			continue; -		prog_clk(dev, i, &info->eng[i]); -	} - -	kfree(info); -	return 0; -}  | 
