DRM part of Radeon DRI suspend/resume support (Charl Botha).

This commit is contained in:
David Dawes 2003-05-20 22:43:39 +00:00
parent 2134577e31
commit c0efa1a777
7 changed files with 368 additions and 0 deletions

View file

@ -1301,6 +1301,176 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
return 0;
}
/* This code will reinit the Radeon CP hardware after a resume from disc.
* AFAIK, it would be very difficult to pickle the state at suspend time, so
* here we make sure that all Radeon hardware initialisation is re-done without
* affecting running applications. This function is called radeon_do_resume_cp()
* as it was derived from radeon_init_cp, where most of the initialisation takes
* place during DRI init.
*
* This patch is NOT to be confused with my and Michel Daenzer's earlier DRI
* reinit work, which de- and re-initialised the complete DRI at every VT
* switch.
*
* Charl P. Botha <http://cpbotha.net>
*/
static int radeon_do_resume_cp( drm_device_t *dev)
{
drm_radeon_private_t *dev_priv;
u32 tmp;
DRM_DEBUG( "\n" );
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
/* get the existing dev_private */
dev_priv = dev->dev_private;
#if !defined(PCIGART_ENABLED)
/* PCI support is not 100% working, so we disable it here.
*/
if ( dev_priv->is_pci ) {
DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
#endif
if ( dev_priv->is_pci && !dev->sg ) {
DRM_ERROR( "PCI GART memory not allocated!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if ( dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
DRM_DEBUG( "TIMEOUT problem!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if ( ( dev_priv->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
( dev_priv->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
DRM_DEBUG( "BAD cp_mode (%x)!\n", dev_priv->cp_mode );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->fb) {
DRM_ERROR("could not find framebuffer!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->mmio) {
DRM_ERROR("could not find mmio region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->cp_ring) {
DRM_ERROR("could not find cp ring region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->buffers) {
DRM_ERROR("could not find dma buffer region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if ( !dev_priv->is_pci ) {
if(!dev_priv->agp_textures) {
DRM_ERROR("could not find agp texture region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
}
if ( !dev_priv->is_pci ) {
if(!dev_priv->cp_ring->handle ||
!dev_priv->ring_rptr->handle ||
!dev_priv->buffers->handle) {
DRM_ERROR("could not find ioremap agp regions!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
} else {
DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
dev_priv->cp_ring->handle );
DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
dev_priv->ring_rptr->handle );
DRM_DEBUG( "dev_priv->buffers->handle %p\n",
dev_priv->buffers->handle );
}
DRM_DEBUG( "dev_priv->agp_size %d\n",
dev_priv->agp_size );
DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
dev_priv->agp_vm_start );
DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
dev_priv->agp_buffers_offset );
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
/* Turn off PCI GART
*/
tmp = RADEON_READ( RADEON_AIC_CNTL )
& ~RADEON_PCIGART_TRANSLATE_EN;
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
} else
#endif
{
/* I'm not so sure about this ati_picgart_init after at resume-time... */
if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
&dev_priv->bus_pci_gart)) {
DRM_ERROR( "failed to init PCI GART!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM);
}
tmp = RADEON_READ( RADEON_AIC_CNTL )
| RADEON_PCIGART_TRANSLATE_EN;
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
/* set PCI GART page-table base address
*/
RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
/* set address range for PCI address translate
*/
RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
+ dev_priv->agp_size - 1);
/* Turn off AGP aperture -- is this required for PCIGART?
*/
RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
}
radeon_cp_load_microcode( dev_priv );
radeon_cp_init_ring_buffer( dev, dev_priv );
radeon_do_engine_reset( dev );
return 0;
}
int radeon_cp_init( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@ -1456,6 +1626,16 @@ int radeon_cp_idle( DRM_IOCTL_ARGS )
return radeon_do_cp_idle( dev_priv );
}
/* Added by Charl P. Botha to call radeon_do_resume_cp().
*/
int radeon_cp_resume( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
return radeon_do_resume_cp(dev);
}
int radeon_engine_reset( DRM_IOCTL_ARGS )
{
DRM_DEVICE;

View file

@ -385,6 +385,8 @@ typedef struct {
#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
/* added by Charl P. Botha - see radeon_cp.c for details */
#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58)
typedef struct drm_radeon_init {
enum {

View file

@ -159,6 +159,7 @@ extern int radeon_cp_start( DRM_IOCTL_ARGS );
extern int radeon_cp_stop( DRM_IOCTL_ARGS );
extern int radeon_cp_reset( DRM_IOCTL_ARGS );
extern int radeon_cp_idle( DRM_IOCTL_ARGS );
extern int radeon_cp_resume( DRM_IOCTL_ARGS );
extern int radeon_engine_reset( DRM_IOCTL_ARGS );
extern int radeon_fullscreen( DRM_IOCTL_ARGS );
extern int radeon_cp_buffers( DRM_IOCTL_ARGS );

View file

@ -79,6 +79,7 @@
* R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian)
* 1.8 - Remove need to call cleanup ioctls on last client exit (keith)
* Add 'GET' queries for starting additional clients on different VT's.
* Add DRM_IOCTL_RADEON_CP_RESUME ioctl.
*/
#define DRIVER_IOCTLS \
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \
@ -87,6 +88,7 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_STOP)] = { radeon_cp_stop, 1, 1 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESET)] = { radeon_cp_reset, 1, 1 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_IDLE)] = { radeon_cp_idle, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_CP_RESUME)] = { radeon_cp_resume, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_RESET)] = { radeon_engine_reset, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_FULLSCREEN)] = { radeon_fullscreen, 1, 0 }, \
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_SWAP)] = { radeon_cp_swap, 1, 0 }, \

View file

@ -1301,6 +1301,176 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
return 0;
}
/* This code will reinit the Radeon CP hardware after a resume from disc.
* AFAIK, it would be very difficult to pickle the state at suspend time, so
* here we make sure that all Radeon hardware initialisation is re-done without
* affecting running applications. This function is called radeon_do_resume_cp()
* as it was derived from radeon_init_cp, where most of the initialisation takes
* place during DRI init.
*
* This patch is NOT to be confused with my and Michel Daenzer's earlier DRI
* reinit work, which de- and re-initialised the complete DRI at every VT
* switch.
*
* Charl P. Botha <http://cpbotha.net>
*/
static int radeon_do_resume_cp( drm_device_t *dev)
{
drm_radeon_private_t *dev_priv;
u32 tmp;
DRM_DEBUG( "\n" );
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
/* get the existing dev_private */
dev_priv = dev->dev_private;
#if !defined(PCIGART_ENABLED)
/* PCI support is not 100% working, so we disable it here.
*/
if ( dev_priv->is_pci ) {
DRM_ERROR( "PCI GART not yet supported for Radeon!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
#endif
if ( dev_priv->is_pci && !dev->sg ) {
DRM_ERROR( "PCI GART memory not allocated!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if ( dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT ) {
DRM_DEBUG( "TIMEOUT problem!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if ( ( dev_priv->cp_mode != RADEON_CSQ_PRIBM_INDDIS ) &&
( dev_priv->cp_mode != RADEON_CSQ_PRIBM_INDBM ) ) {
DRM_DEBUG( "BAD cp_mode (%x)!\n", dev_priv->cp_mode );
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->fb) {
DRM_ERROR("could not find framebuffer!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->mmio) {
DRM_ERROR("could not find mmio region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->cp_ring) {
DRM_ERROR("could not find cp ring region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if(!dev_priv->buffers) {
DRM_ERROR("could not find dma buffer region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
if ( !dev_priv->is_pci ) {
if(!dev_priv->agp_textures) {
DRM_ERROR("could not find agp texture region!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
}
if ( !dev_priv->is_pci ) {
if(!dev_priv->cp_ring->handle ||
!dev_priv->ring_rptr->handle ||
!dev_priv->buffers->handle) {
DRM_ERROR("could not find ioremap agp regions!\n");
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
} else {
DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
dev_priv->cp_ring->handle );
DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
dev_priv->ring_rptr->handle );
DRM_DEBUG( "dev_priv->buffers->handle %p\n",
dev_priv->buffers->handle );
}
DRM_DEBUG( "dev_priv->agp_size %d\n",
dev_priv->agp_size );
DRM_DEBUG( "dev_priv->agp_vm_start 0x%x\n",
dev_priv->agp_vm_start );
DRM_DEBUG( "dev_priv->agp_buffers_offset 0x%lx\n",
dev_priv->agp_buffers_offset );
#if __REALLY_HAVE_AGP
if ( !dev_priv->is_pci ) {
/* Turn off PCI GART
*/
tmp = RADEON_READ( RADEON_AIC_CNTL )
& ~RADEON_PCIGART_TRANSLATE_EN;
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
} else
#endif
{
/* I'm not so sure about this ati_picgart_init after at resume-time... */
if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
&dev_priv->bus_pci_gart)) {
DRM_ERROR( "failed to init PCI GART!\n" );
radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM);
}
tmp = RADEON_READ( RADEON_AIC_CNTL )
| RADEON_PCIGART_TRANSLATE_EN;
RADEON_WRITE( RADEON_AIC_CNTL, tmp );
/* set PCI GART page-table base address
*/
RADEON_WRITE( RADEON_AIC_PT_BASE, dev_priv->bus_pci_gart );
/* set address range for PCI address translate
*/
RADEON_WRITE( RADEON_AIC_LO_ADDR, dev_priv->agp_vm_start );
RADEON_WRITE( RADEON_AIC_HI_ADDR, dev_priv->agp_vm_start
+ dev_priv->agp_size - 1);
/* Turn off AGP aperture -- is this required for PCIGART?
*/
RADEON_WRITE( RADEON_MC_AGP_LOCATION, 0xffffffc0 ); /* ?? */
RADEON_WRITE( RADEON_AGP_COMMAND, 0 ); /* clear AGP_COMMAND */
}
radeon_cp_load_microcode( dev_priv );
radeon_cp_init_ring_buffer( dev, dev_priv );
radeon_do_engine_reset( dev );
return 0;
}
int radeon_cp_init( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
@ -1456,6 +1626,16 @@ int radeon_cp_idle( DRM_IOCTL_ARGS )
return radeon_do_cp_idle( dev_priv );
}
/* Added by Charl P. Botha to call radeon_do_resume_cp().
*/
int radeon_cp_resume( DRM_IOCTL_ARGS )
{
DRM_DEVICE;
return radeon_do_resume_cp(dev);
}
int radeon_engine_reset( DRM_IOCTL_ARGS )
{
DRM_DEVICE;

View file

@ -385,6 +385,8 @@ typedef struct {
#define DRM_IOCTL_RADEON_INIT_HEAP DRM_IOW( 0x55, drm_radeon_mem_init_heap_t)
#define DRM_IOCTL_RADEON_IRQ_EMIT DRM_IOWR( 0x56, drm_radeon_irq_emit_t)
#define DRM_IOCTL_RADEON_IRQ_WAIT DRM_IOW( 0x57, drm_radeon_irq_wait_t)
/* added by Charl P. Botha - see radeon_cp.c for details */
#define DRM_IOCTL_RADEON_CP_RESUME DRM_IO(0x58)
typedef struct drm_radeon_init {
enum {

View file

@ -159,6 +159,7 @@ extern int radeon_cp_start( DRM_IOCTL_ARGS );
extern int radeon_cp_stop( DRM_IOCTL_ARGS );
extern int radeon_cp_reset( DRM_IOCTL_ARGS );
extern int radeon_cp_idle( DRM_IOCTL_ARGS );
extern int radeon_cp_resume( DRM_IOCTL_ARGS );
extern int radeon_engine_reset( DRM_IOCTL_ARGS );
extern int radeon_fullscreen( DRM_IOCTL_ARGS );
extern int radeon_cp_buffers( DRM_IOCTL_ARGS );