2009-12-11 19:24:15 +10:00
/*
* Copyright ( C ) 2007 Ben Skeggs .
* 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 ( 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 COPYRIGHT OWNER ( S ) AND / OR ITS 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 .
*
*/
# include "drmP.h"
# include "drm.h"
# include "nouveau_drv.h"
2010-09-01 15:24:31 +10:00
# include "nouveau_ramht.h"
2010-08-27 10:00:25 +10:00
# include "nouveau_vm.h"
2009-12-11 19:24:15 +10:00
static void
2010-07-08 15:28:48 +10:00
nv50_fifo_playlist_update ( struct drm_device * dev )
2009-12-11 19:24:15 +10:00
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
2010-07-08 15:28:48 +10:00
struct nouveau_fifo_engine * pfifo = & dev_priv - > engine . fifo ;
2010-09-01 15:24:31 +10:00
struct nouveau_gpuobj * cur ;
2009-12-11 19:24:15 +10:00
int i , nr ;
NV_DEBUG ( dev , " \n " ) ;
2010-07-08 15:28:48 +10:00
cur = pfifo - > playlist [ pfifo - > cur_playlist ] ;
pfifo - > cur_playlist = ! pfifo - > cur_playlist ;
2009-12-11 19:24:15 +10:00
/* We never schedule channel 0 or 127 */
for ( i = 1 , nr = 0 ; i < 127 ; i + + ) {
2010-10-06 16:16:59 +10:00
if ( dev_priv - > channels . ptr [ i ] & &
dev_priv - > channels . ptr [ i ] - > ramfc ) {
2010-09-01 15:24:31 +10:00
nv_wo32 ( cur , ( nr * 4 ) , i ) ;
2010-09-01 15:24:29 +10:00
nr + + ;
}
2009-12-11 19:24:15 +10:00
}
2010-07-08 11:29:10 +10:00
dev_priv - > engine . instmem . flush ( dev ) ;
2009-12-11 19:24:15 +10:00
2010-09-01 15:24:31 +10:00
nv_wr32 ( dev , 0x32f4 , cur - > vinst > > 12 ) ;
2009-12-11 19:24:15 +10:00
nv_wr32 ( dev , 0x32ec , nr ) ;
nv_wr32 ( dev , 0x2500 , 0x101 ) ;
}
2010-07-08 15:28:48 +10:00
static void
nv50_fifo_channel_enable ( struct drm_device * dev , int channel )
2009-12-11 19:24:15 +10:00
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
2010-10-06 16:16:59 +10:00
struct nouveau_channel * chan = dev_priv - > channels . ptr [ channel ] ;
2009-12-11 19:24:15 +10:00
uint32_t inst ;
NV_DEBUG ( dev , " ch%d \n " , channel ) ;
2010-07-08 15:28:48 +10:00
if ( dev_priv - > chipset = = 0x50 )
2010-09-01 15:24:31 +10:00
inst = chan - > ramfc - > vinst > > 12 ;
2009-12-11 19:24:15 +10:00
else
2010-09-01 15:24:31 +10:00
inst = chan - > ramfc - > vinst > > 8 ;
2009-12-11 19:24:15 +10:00
2010-07-08 15:28:48 +10:00
nv_wr32 ( dev , NV50_PFIFO_CTX_TABLE ( channel ) , inst |
NV50_PFIFO_CTX_TABLE_CHANNEL_ENABLED ) ;
2009-12-11 19:24:15 +10:00
}
static void
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_disable ( struct drm_device * dev , int channel )
2009-12-11 19:24:15 +10:00
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
uint32_t inst ;
2010-07-08 15:28:48 +10:00
NV_DEBUG ( dev , " ch%d \n " , channel ) ;
2009-12-11 19:24:15 +10:00
2010-07-08 15:28:48 +10:00
if ( dev_priv - > chipset = = 0x50 )
2009-12-11 19:24:15 +10:00
inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G80 ;
else
inst = NV50_PFIFO_CTX_TABLE_INSTANCE_MASK_G84 ;
nv_wr32 ( dev , NV50_PFIFO_CTX_TABLE ( channel ) , inst ) ;
}
static void
nv50_fifo_init_reset ( struct drm_device * dev )
{
uint32_t pmc_e = NV_PMC_ENABLE_PFIFO ;
NV_DEBUG ( dev , " \n " ) ;
nv_wr32 ( dev , NV03_PMC_ENABLE , nv_rd32 ( dev , NV03_PMC_ENABLE ) & ~ pmc_e ) ;
nv_wr32 ( dev , NV03_PMC_ENABLE , nv_rd32 ( dev , NV03_PMC_ENABLE ) | pmc_e ) ;
}
static void
nv50_fifo_init_intr ( struct drm_device * dev )
{
NV_DEBUG ( dev , " \n " ) ;
2010-11-03 10:56:05 +10:00
nouveau_irq_register ( dev , 8 , nv04_fifo_isr ) ;
2009-12-11 19:24:15 +10:00
nv_wr32 ( dev , NV03_PFIFO_INTR_0 , 0xFFFFFFFF ) ;
nv_wr32 ( dev , NV03_PFIFO_INTR_EN_0 , 0xFFFFFFFF ) ;
}
static void
nv50_fifo_init_context_table ( struct drm_device * dev )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
int i ;
NV_DEBUG ( dev , " \n " ) ;
for ( i = 0 ; i < NV50_PFIFO_CTX_TABLE__SIZE ; i + + ) {
2010-10-06 16:16:59 +10:00
if ( dev_priv - > channels . ptr [ i ] )
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_enable ( dev , i ) ;
2009-12-11 19:24:15 +10:00
else
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_disable ( dev , i ) ;
2009-12-11 19:24:15 +10:00
}
2010-07-08 15:28:48 +10:00
nv50_fifo_playlist_update ( dev ) ;
2009-12-11 19:24:15 +10:00
}
static void
nv50_fifo_init_regs__nv ( struct drm_device * dev )
{
NV_DEBUG ( dev , " \n " ) ;
nv_wr32 ( dev , 0x250c , 0x6f3cfc34 ) ;
}
static void
nv50_fifo_init_regs ( struct drm_device * dev )
{
NV_DEBUG ( dev , " \n " ) ;
nv_wr32 ( dev , 0x2500 , 0 ) ;
nv_wr32 ( dev , 0x3250 , 0 ) ;
nv_wr32 ( dev , 0x3220 , 0 ) ;
nv_wr32 ( dev , 0x3204 , 0 ) ;
nv_wr32 ( dev , 0x3210 , 0 ) ;
nv_wr32 ( dev , 0x3270 , 0 ) ;
/* Enable dummy channels setup by nv50_instmem.c */
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_enable ( dev , 0 ) ;
nv50_fifo_channel_enable ( dev , 127 ) ;
2009-12-11 19:24:15 +10:00
}
int
nv50_fifo_init ( struct drm_device * dev )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
2010-07-08 15:28:48 +10:00
struct nouveau_fifo_engine * pfifo = & dev_priv - > engine . fifo ;
2009-12-11 19:24:15 +10:00
int ret ;
NV_DEBUG ( dev , " \n " ) ;
2010-07-08 15:28:48 +10:00
if ( pfifo - > playlist [ 0 ] ) {
pfifo - > cur_playlist = ! pfifo - > cur_playlist ;
2009-12-11 19:24:15 +10:00
goto just_reset ;
}
2010-09-01 15:24:31 +10:00
ret = nouveau_gpuobj_new ( dev , NULL , 128 * 4 , 0x1000 ,
NVOBJ_FLAG_ZERO_ALLOC ,
& pfifo - > playlist [ 0 ] ) ;
2009-12-11 19:24:15 +10:00
if ( ret ) {
2010-07-08 15:28:48 +10:00
NV_ERROR ( dev , " error creating playlist 0: %d \n " , ret ) ;
2009-12-11 19:24:15 +10:00
return ret ;
}
2010-09-01 15:24:31 +10:00
ret = nouveau_gpuobj_new ( dev , NULL , 128 * 4 , 0x1000 ,
NVOBJ_FLAG_ZERO_ALLOC ,
& pfifo - > playlist [ 1 ] ) ;
2009-12-11 19:24:15 +10:00
if ( ret ) {
2010-09-01 15:24:31 +10:00
nouveau_gpuobj_ref ( NULL , & pfifo - > playlist [ 0 ] ) ;
2010-07-08 15:28:48 +10:00
NV_ERROR ( dev , " error creating playlist 1: %d \n " , ret ) ;
2009-12-11 19:24:15 +10:00
return ret ;
}
just_reset :
nv50_fifo_init_reset ( dev ) ;
nv50_fifo_init_intr ( dev ) ;
nv50_fifo_init_context_table ( dev ) ;
nv50_fifo_init_regs__nv ( dev ) ;
nv50_fifo_init_regs ( dev ) ;
dev_priv - > engine . fifo . enable ( dev ) ;
dev_priv - > engine . fifo . reassign ( dev , true ) ;
return 0 ;
}
void
nv50_fifo_takedown ( struct drm_device * dev )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
2010-07-08 15:28:48 +10:00
struct nouveau_fifo_engine * pfifo = & dev_priv - > engine . fifo ;
2009-12-11 19:24:15 +10:00
NV_DEBUG ( dev , " \n " ) ;
2010-07-08 15:28:48 +10:00
if ( ! pfifo - > playlist [ 0 ] )
2009-12-11 19:24:15 +10:00
return ;
2010-11-03 10:56:05 +10:00
nv_wr32 ( dev , 0x2140 , 0x00000000 ) ;
nouveau_irq_unregister ( dev , 8 ) ;
2010-09-01 15:24:31 +10:00
nouveau_gpuobj_ref ( NULL , & pfifo - > playlist [ 0 ] ) ;
nouveau_gpuobj_ref ( NULL , & pfifo - > playlist [ 1 ] ) ;
2009-12-11 19:24:15 +10:00
}
int
nv50_fifo_channel_id ( struct drm_device * dev )
{
return nv_rd32 ( dev , NV03_PFIFO_CACHE1_PUSH1 ) &
NV50_PFIFO_CACHE1_PUSH1_CHID_MASK ;
}
int
nv50_fifo_create_context ( struct nouveau_channel * chan )
{
struct drm_device * dev = chan - > dev ;
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
struct nouveau_gpuobj * ramfc = NULL ;
2010-02-01 20:58:27 +01:00
unsigned long flags ;
2009-12-11 19:24:15 +10:00
int ret ;
NV_DEBUG ( dev , " ch%d \n " , chan - > id ) ;
2010-07-08 15:28:48 +10:00
if ( dev_priv - > chipset = = 0x50 ) {
2010-09-01 15:24:31 +10:00
ret = nouveau_gpuobj_new_fake ( dev , chan - > ramin - > pinst ,
chan - > ramin - > vinst , 0x100 ,
2010-09-01 15:24:30 +10:00
NVOBJ_FLAG_ZERO_ALLOC |
2010-09-01 15:24:31 +10:00
NVOBJ_FLAG_ZERO_FREE ,
2009-12-11 19:24:15 +10:00
& chan - > ramfc ) ;
if ( ret )
return ret ;
2010-09-01 15:24:31 +10:00
ret = nouveau_gpuobj_new_fake ( dev , chan - > ramin - > pinst + 0x0400 ,
chan - > ramin - > vinst + 0x0400 ,
4096 , 0 , & chan - > cache ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
} else {
2010-09-01 15:24:31 +10:00
ret = nouveau_gpuobj_new ( dev , chan , 0x100 , 256 ,
NVOBJ_FLAG_ZERO_ALLOC |
NVOBJ_FLAG_ZERO_FREE , & chan - > ramfc ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2010-09-01 15:24:31 +10:00
ret = nouveau_gpuobj_new ( dev , chan , 4096 , 1024 ,
0 , & chan - > cache ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
}
2010-09-01 15:24:31 +10:00
ramfc = chan - > ramfc ;
2009-12-11 19:24:15 +10:00
2010-11-22 16:05:54 +10:00
chan - > user = ioremap ( pci_resource_start ( dev - > pdev , 0 ) +
NV50_USER ( chan - > id ) , PAGE_SIZE ) ;
if ( ! chan - > user )
return - ENOMEM ;
2010-02-01 20:58:27 +01:00
spin_lock_irqsave ( & dev_priv - > context_switch_lock , flags ) ;
2010-09-01 15:24:31 +10:00
nv_wo32 ( ramfc , 0x48 , chan - > pushbuf - > cinst > > 4 ) ;
2010-09-01 15:24:35 +10:00
nv_wo32 ( ramfc , 0x80 , ( ( chan - > ramht - > bits - 9 ) < < 27 ) |
2010-09-01 15:24:29 +10:00
( 4 < < 24 ) /* SEARCH_FULL */ |
2010-09-01 15:24:31 +10:00
( chan - > ramht - > gpuobj - > cinst > > 4 ) ) ;
2010-09-01 15:24:29 +10:00
nv_wo32 ( ramfc , 0x44 , 0x2101ffff ) ;
nv_wo32 ( ramfc , 0x60 , 0x7fffffff ) ;
nv_wo32 ( ramfc , 0x40 , 0x00000000 ) ;
nv_wo32 ( ramfc , 0x7c , 0x30000001 ) ;
nv_wo32 ( ramfc , 0x78 , 0x00000000 ) ;
nv_wo32 ( ramfc , 0x3c , 0x403f6078 ) ;
nv_wo32 ( ramfc , 0x50 , chan - > pushbuf_base + chan - > dma . ib_base * 4 ) ;
nv_wo32 ( ramfc , 0x54 , drm_order ( chan - > dma . ib_max + 1 ) < < 16 ) ;
2009-12-11 19:24:15 +10:00
2010-07-08 15:28:48 +10:00
if ( dev_priv - > chipset ! = 0x50 ) {
2010-09-01 15:24:31 +10:00
nv_wo32 ( chan - > ramin , 0 , chan - > id ) ;
nv_wo32 ( chan - > ramin , 4 , chan - > ramfc - > vinst > > 8 ) ;
2009-12-11 19:24:15 +10:00
2010-09-01 15:24:31 +10:00
nv_wo32 ( ramfc , 0x88 , chan - > cache - > vinst > > 10 ) ;
nv_wo32 ( ramfc , 0x98 , chan - > ramin - > vinst > > 12 ) ;
2009-12-11 19:24:15 +10:00
}
2010-07-08 11:29:10 +10:00
dev_priv - > engine . instmem . flush ( dev ) ;
2009-12-11 19:24:15 +10:00
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_enable ( dev , chan - > id ) ;
nv50_fifo_playlist_update ( dev ) ;
2010-02-01 20:58:27 +01:00
spin_unlock_irqrestore ( & dev_priv - > context_switch_lock , flags ) ;
2009-12-11 19:24:15 +10:00
return 0 ;
}
void
nv50_fifo_destroy_context ( struct nouveau_channel * chan )
{
struct drm_device * dev = chan - > dev ;
2010-10-18 03:53:39 +02:00
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
struct nouveau_fifo_engine * pfifo = & dev_priv - > engine . fifo ;
2010-09-01 15:24:31 +10:00
struct nouveau_gpuobj * ramfc = NULL ;
2010-10-18 03:53:39 +02:00
unsigned long flags ;
2009-12-11 19:24:15 +10:00
NV_DEBUG ( dev , " ch%d \n " , chan - > id ) ;
2010-10-18 03:53:39 +02:00
spin_lock_irqsave ( & dev_priv - > context_switch_lock , flags ) ;
pfifo - > reassign ( dev , false ) ;
/* Unload the context if it's the currently active one */
if ( pfifo - > channel_id ( dev ) = = chan - > id ) {
pfifo - > disable ( dev ) ;
pfifo - > unload_context ( dev ) ;
pfifo - > enable ( dev ) ;
}
2010-02-01 18:47:52 +01:00
/* This will ensure the channel is seen as disabled. */
2010-09-01 15:24:31 +10:00
nouveau_gpuobj_ref ( chan - > ramfc , & ramfc ) ;
nouveau_gpuobj_ref ( NULL , & chan - > ramfc ) ;
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_disable ( dev , chan - > id ) ;
2009-12-11 19:24:15 +10:00
/* Dummy channel, also used on ch 127 */
if ( chan - > id = = 0 )
2010-07-08 15:28:48 +10:00
nv50_fifo_channel_disable ( dev , 127 ) ;
nv50_fifo_playlist_update ( dev ) ;
2010-02-01 18:47:52 +01:00
2010-10-18 03:53:39 +02:00
pfifo - > reassign ( dev , true ) ;
spin_unlock_irqrestore ( & dev_priv - > context_switch_lock , flags ) ;
/* Free the channel resources */
2010-11-22 16:05:54 +10:00
if ( chan - > user ) {
iounmap ( chan - > user ) ;
chan - > user = NULL ;
}
2010-09-01 15:24:31 +10:00
nouveau_gpuobj_ref ( NULL , & ramfc ) ;
nouveau_gpuobj_ref ( NULL , & chan - > cache ) ;
2009-12-11 19:24:15 +10:00
}
int
nv50_fifo_load_context ( struct nouveau_channel * chan )
{
struct drm_device * dev = chan - > dev ;
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
2010-09-01 15:24:31 +10:00
struct nouveau_gpuobj * ramfc = chan - > ramfc ;
struct nouveau_gpuobj * cache = chan - > cache ;
2009-12-11 19:24:15 +10:00
int ptr , cnt ;
NV_DEBUG ( dev , " ch%d \n " , chan - > id ) ;
2010-09-01 15:24:29 +10:00
nv_wr32 ( dev , 0x3330 , nv_ro32 ( ramfc , 0x00 ) ) ;
nv_wr32 ( dev , 0x3334 , nv_ro32 ( ramfc , 0x04 ) ) ;
nv_wr32 ( dev , 0x3240 , nv_ro32 ( ramfc , 0x08 ) ) ;
nv_wr32 ( dev , 0x3320 , nv_ro32 ( ramfc , 0x0c ) ) ;
nv_wr32 ( dev , 0x3244 , nv_ro32 ( ramfc , 0x10 ) ) ;
nv_wr32 ( dev , 0x3328 , nv_ro32 ( ramfc , 0x14 ) ) ;
nv_wr32 ( dev , 0x3368 , nv_ro32 ( ramfc , 0x18 ) ) ;
nv_wr32 ( dev , 0x336c , nv_ro32 ( ramfc , 0x1c ) ) ;
nv_wr32 ( dev , 0x3370 , nv_ro32 ( ramfc , 0x20 ) ) ;
nv_wr32 ( dev , 0x3374 , nv_ro32 ( ramfc , 0x24 ) ) ;
nv_wr32 ( dev , 0x3378 , nv_ro32 ( ramfc , 0x28 ) ) ;
nv_wr32 ( dev , 0x337c , nv_ro32 ( ramfc , 0x2c ) ) ;
nv_wr32 ( dev , 0x3228 , nv_ro32 ( ramfc , 0x30 ) ) ;
nv_wr32 ( dev , 0x3364 , nv_ro32 ( ramfc , 0x34 ) ) ;
nv_wr32 ( dev , 0x32a0 , nv_ro32 ( ramfc , 0x38 ) ) ;
nv_wr32 ( dev , 0x3224 , nv_ro32 ( ramfc , 0x3c ) ) ;
nv_wr32 ( dev , 0x324c , nv_ro32 ( ramfc , 0x40 ) ) ;
nv_wr32 ( dev , 0x2044 , nv_ro32 ( ramfc , 0x44 ) ) ;
nv_wr32 ( dev , 0x322c , nv_ro32 ( ramfc , 0x48 ) ) ;
nv_wr32 ( dev , 0x3234 , nv_ro32 ( ramfc , 0x4c ) ) ;
nv_wr32 ( dev , 0x3340 , nv_ro32 ( ramfc , 0x50 ) ) ;
nv_wr32 ( dev , 0x3344 , nv_ro32 ( ramfc , 0x54 ) ) ;
nv_wr32 ( dev , 0x3280 , nv_ro32 ( ramfc , 0x58 ) ) ;
nv_wr32 ( dev , 0x3254 , nv_ro32 ( ramfc , 0x5c ) ) ;
nv_wr32 ( dev , 0x3260 , nv_ro32 ( ramfc , 0x60 ) ) ;
nv_wr32 ( dev , 0x3264 , nv_ro32 ( ramfc , 0x64 ) ) ;
nv_wr32 ( dev , 0x3268 , nv_ro32 ( ramfc , 0x68 ) ) ;
nv_wr32 ( dev , 0x326c , nv_ro32 ( ramfc , 0x6c ) ) ;
nv_wr32 ( dev , 0x32e4 , nv_ro32 ( ramfc , 0x70 ) ) ;
nv_wr32 ( dev , 0x3248 , nv_ro32 ( ramfc , 0x74 ) ) ;
nv_wr32 ( dev , 0x2088 , nv_ro32 ( ramfc , 0x78 ) ) ;
nv_wr32 ( dev , 0x2058 , nv_ro32 ( ramfc , 0x7c ) ) ;
nv_wr32 ( dev , 0x2210 , nv_ro32 ( ramfc , 0x80 ) ) ;
cnt = nv_ro32 ( ramfc , 0x84 ) ;
2009-12-11 19:24:15 +10:00
for ( ptr = 0 ; ptr < cnt ; ptr + + ) {
nv_wr32 ( dev , NV40_PFIFO_CACHE1_METHOD ( ptr ) ,
2010-09-01 15:24:29 +10:00
nv_ro32 ( cache , ( ptr * 8 ) + 0 ) ) ;
2009-12-11 19:24:15 +10:00
nv_wr32 ( dev , NV40_PFIFO_CACHE1_DATA ( ptr ) ,
2010-09-01 15:24:29 +10:00
nv_ro32 ( cache , ( ptr * 8 ) + 4 ) ) ;
2009-12-11 19:24:15 +10:00
}
2010-01-05 09:41:05 +10:00
nv_wr32 ( dev , NV03_PFIFO_CACHE1_PUT , cnt < < 2 ) ;
nv_wr32 ( dev , NV03_PFIFO_CACHE1_GET , 0 ) ;
2009-12-11 19:24:15 +10:00
/* guessing that all the 0x34xx regs aren't on NV50 */
2010-07-08 15:28:48 +10:00
if ( dev_priv - > chipset ! = 0x50 ) {
2010-09-01 15:24:29 +10:00
nv_wr32 ( dev , 0x340c , nv_ro32 ( ramfc , 0x88 ) ) ;
nv_wr32 ( dev , 0x3400 , nv_ro32 ( ramfc , 0x8c ) ) ;
nv_wr32 ( dev , 0x3404 , nv_ro32 ( ramfc , 0x90 ) ) ;
nv_wr32 ( dev , 0x3408 , nv_ro32 ( ramfc , 0x94 ) ) ;
nv_wr32 ( dev , 0x3410 , nv_ro32 ( ramfc , 0x98 ) ) ;
2009-12-11 19:24:15 +10:00
}
nv_wr32 ( dev , NV03_PFIFO_CACHE1_PUSH1 , chan - > id | ( 1 < < 16 ) ) ;
return 0 ;
}
int
nv50_fifo_unload_context ( struct drm_device * dev )
{
struct drm_nouveau_private * dev_priv = dev - > dev_private ;
struct nouveau_fifo_engine * pfifo = & dev_priv - > engine . fifo ;
struct nouveau_gpuobj * ramfc , * cache ;
struct nouveau_channel * chan = NULL ;
int chid , get , put , ptr ;
NV_DEBUG ( dev , " \n " ) ;
chid = pfifo - > channel_id ( dev ) ;
2009-12-16 14:51:13 +10:00
if ( chid < 1 | | chid > = dev_priv - > engine . fifo . channels - 1 )
2009-12-11 19:24:15 +10:00
return 0 ;
2010-10-06 16:16:59 +10:00
chan = dev_priv - > channels . ptr [ chid ] ;
2009-12-11 19:24:15 +10:00
if ( ! chan ) {
NV_ERROR ( dev , " Inactive channel on PFIFO: %d \n " , chid ) ;
return - EINVAL ;
}
NV_DEBUG ( dev , " ch%d \n " , chan - > id ) ;
2010-09-01 15:24:31 +10:00
ramfc = chan - > ramfc ;
cache = chan - > cache ;
2009-12-11 19:24:15 +10:00
2010-09-01 15:24:29 +10:00
nv_wo32 ( ramfc , 0x00 , nv_rd32 ( dev , 0x3330 ) ) ;
nv_wo32 ( ramfc , 0x04 , nv_rd32 ( dev , 0x3334 ) ) ;
nv_wo32 ( ramfc , 0x08 , nv_rd32 ( dev , 0x3240 ) ) ;
nv_wo32 ( ramfc , 0x0c , nv_rd32 ( dev , 0x3320 ) ) ;
nv_wo32 ( ramfc , 0x10 , nv_rd32 ( dev , 0x3244 ) ) ;
nv_wo32 ( ramfc , 0x14 , nv_rd32 ( dev , 0x3328 ) ) ;
nv_wo32 ( ramfc , 0x18 , nv_rd32 ( dev , 0x3368 ) ) ;
nv_wo32 ( ramfc , 0x1c , nv_rd32 ( dev , 0x336c ) ) ;
nv_wo32 ( ramfc , 0x20 , nv_rd32 ( dev , 0x3370 ) ) ;
nv_wo32 ( ramfc , 0x24 , nv_rd32 ( dev , 0x3374 ) ) ;
nv_wo32 ( ramfc , 0x28 , nv_rd32 ( dev , 0x3378 ) ) ;
nv_wo32 ( ramfc , 0x2c , nv_rd32 ( dev , 0x337c ) ) ;
nv_wo32 ( ramfc , 0x30 , nv_rd32 ( dev , 0x3228 ) ) ;
nv_wo32 ( ramfc , 0x34 , nv_rd32 ( dev , 0x3364 ) ) ;
nv_wo32 ( ramfc , 0x38 , nv_rd32 ( dev , 0x32a0 ) ) ;
nv_wo32 ( ramfc , 0x3c , nv_rd32 ( dev , 0x3224 ) ) ;
nv_wo32 ( ramfc , 0x40 , nv_rd32 ( dev , 0x324c ) ) ;
nv_wo32 ( ramfc , 0x44 , nv_rd32 ( dev , 0x2044 ) ) ;
nv_wo32 ( ramfc , 0x48 , nv_rd32 ( dev , 0x322c ) ) ;
nv_wo32 ( ramfc , 0x4c , nv_rd32 ( dev , 0x3234 ) ) ;
nv_wo32 ( ramfc , 0x50 , nv_rd32 ( dev , 0x3340 ) ) ;
nv_wo32 ( ramfc , 0x54 , nv_rd32 ( dev , 0x3344 ) ) ;
nv_wo32 ( ramfc , 0x58 , nv_rd32 ( dev , 0x3280 ) ) ;
nv_wo32 ( ramfc , 0x5c , nv_rd32 ( dev , 0x3254 ) ) ;
nv_wo32 ( ramfc , 0x60 , nv_rd32 ( dev , 0x3260 ) ) ;
nv_wo32 ( ramfc , 0x64 , nv_rd32 ( dev , 0x3264 ) ) ;
nv_wo32 ( ramfc , 0x68 , nv_rd32 ( dev , 0x3268 ) ) ;
nv_wo32 ( ramfc , 0x6c , nv_rd32 ( dev , 0x326c ) ) ;
nv_wo32 ( ramfc , 0x70 , nv_rd32 ( dev , 0x32e4 ) ) ;
nv_wo32 ( ramfc , 0x74 , nv_rd32 ( dev , 0x3248 ) ) ;
nv_wo32 ( ramfc , 0x78 , nv_rd32 ( dev , 0x2088 ) ) ;
nv_wo32 ( ramfc , 0x7c , nv_rd32 ( dev , 0x2058 ) ) ;
nv_wo32 ( ramfc , 0x80 , nv_rd32 ( dev , 0x2210 ) ) ;
2009-12-11 19:24:15 +10:00
put = ( nv_rd32 ( dev , NV03_PFIFO_CACHE1_PUT ) & 0x7ff ) > > 2 ;
get = ( nv_rd32 ( dev , NV03_PFIFO_CACHE1_GET ) & 0x7ff ) > > 2 ;
ptr = 0 ;
while ( put ! = get ) {
2010-09-01 15:24:29 +10:00
nv_wo32 ( cache , ptr + 0 ,
nv_rd32 ( dev , NV40_PFIFO_CACHE1_METHOD ( get ) ) ) ;
nv_wo32 ( cache , ptr + 4 ,
nv_rd32 ( dev , NV40_PFIFO_CACHE1_DATA ( get ) ) ) ;
2009-12-11 19:24:15 +10:00
get = ( get + 1 ) & 0x1ff ;
2010-09-01 15:24:29 +10:00
ptr + = 8 ;
2009-12-11 19:24:15 +10:00
}
/* guessing that all the 0x34xx regs aren't on NV50 */
2010-07-08 15:28:48 +10:00
if ( dev_priv - > chipset ! = 0x50 ) {
2010-09-01 15:24:29 +10:00
nv_wo32 ( ramfc , 0x84 , ptr > > 3 ) ;
nv_wo32 ( ramfc , 0x88 , nv_rd32 ( dev , 0x340c ) ) ;
nv_wo32 ( ramfc , 0x8c , nv_rd32 ( dev , 0x3400 ) ) ;
nv_wo32 ( ramfc , 0x90 , nv_rd32 ( dev , 0x3404 ) ) ;
nv_wo32 ( ramfc , 0x94 , nv_rd32 ( dev , 0x3408 ) ) ;
nv_wo32 ( ramfc , 0x98 , nv_rd32 ( dev , 0x3410 ) ) ;
2009-12-11 19:24:15 +10:00
}
2010-07-08 11:29:10 +10:00
dev_priv - > engine . instmem . flush ( dev ) ;
2009-12-11 19:24:15 +10:00
/*XXX: probably reload ch127 (NULL) state back too */
nv_wr32 ( dev , NV03_PFIFO_CACHE1_PUSH1 , 127 ) ;
return 0 ;
}
2010-10-22 10:26:24 +10:00
void
nv50_fifo_tlb_flush ( struct drm_device * dev )
{
2010-08-27 10:00:25 +10:00
nv50_vm_flush_engine ( dev , 5 ) ;
2010-10-22 10:26:24 +10:00
}