2005-06-28 16:48:56 +04:00
/*
2006-08-07 16:03:22 +04:00
* Copyright 2006 Tungsten Graphics Inc . , Bismarck , ND . , USA .
* All rights reserved .
2005-06-28 16:48:56 +04:00
*
* 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 , sub license ,
* 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 NON - INFRINGEMENT . IN NO EVENT SHALL
2006-08-07 16:03:22 +04:00
* THE AUTHORS OR COPYRIGHT HOLDERS AND / OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM ,
* DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
2005-06-28 16:48:56 +04:00
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*/
2006-08-07 16:03:22 +04:00
/*
2007-10-20 01:21:04 +04:00
* Authors : Thomas Hellström < thomas - at - tungstengraphics - dot - com >
2006-08-07 16:03:22 +04:00
*/
2005-06-28 16:48:56 +04:00
# include "drmP.h"
# include "via_drm.h"
# include "via_drv.h"
2006-08-07 16:03:22 +04:00
# include "drm_sman.h"
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
# define VIA_MM_ALIGN_SHIFT 4
# define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1)
2005-06-28 16:48:56 +04:00
2007-09-03 06:06:45 +04:00
int via_agp_init ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-06-28 16:48:56 +04:00
{
2007-09-03 06:06:45 +04:00
drm_via_agp_t * agp = data ;
2006-08-07 16:03:22 +04:00
drm_via_private_t * dev_priv = ( drm_via_private_t * ) dev - > dev_private ;
int ret ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
mutex_lock ( & dev - > struct_mutex ) ;
ret = drm_sman_set_range ( & dev_priv - > sman , VIA_MEM_AGP , 0 ,
2007-09-03 06:06:45 +04:00
agp - > size > > VIA_MM_ALIGN_SHIFT ) ;
2006-08-07 16:03:22 +04:00
if ( ret ) {
DRM_ERROR ( " AGP memory manager initialisation error \n " ) ;
mutex_unlock ( & dev - > struct_mutex ) ;
return ret ;
}
2005-06-28 16:48:56 +04:00
2006-08-19 11:40:50 +04:00
dev_priv - > agp_initialized = 1 ;
2007-09-03 06:06:45 +04:00
dev_priv - > agp_offset = agp - > offset ;
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
2005-06-28 16:48:56 +04:00
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " offset = %u, size = %u \n " , agp - > offset , agp - > size ) ;
2005-06-28 16:48:56 +04:00
return 0 ;
}
2007-09-03 06:06:45 +04:00
int via_fb_init ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-06-28 16:48:56 +04:00
{
2007-09-03 06:06:45 +04:00
drm_via_fb_t * fb = data ;
2006-08-07 16:03:22 +04:00
drm_via_private_t * dev_priv = ( drm_via_private_t * ) dev - > dev_private ;
int ret ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
mutex_lock ( & dev - > struct_mutex ) ;
ret = drm_sman_set_range ( & dev_priv - > sman , VIA_MEM_VIDEO , 0 ,
2007-09-03 06:06:45 +04:00
fb - > size > > VIA_MM_ALIGN_SHIFT ) ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
if ( ret ) {
DRM_ERROR ( " VRAM memory manager initialisation error \n " ) ;
mutex_unlock ( & dev - > struct_mutex ) ;
return ret ;
}
2005-06-28 16:48:56 +04:00
2006-08-19 11:40:50 +04:00
dev_priv - > vram_initialized = 1 ;
2007-09-03 06:06:45 +04:00
dev_priv - > vram_offset = fb - > offset ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " offset = %u, size = %u \n " , fb - > offset , fb - > size ) ;
2006-08-07 16:03:22 +04:00
return 0 ;
2005-06-28 16:48:56 +04:00
}
int via_final_context ( struct drm_device * dev , int context )
2005-09-25 08:28:13 +04:00
{
2005-06-28 16:48:56 +04:00
drm_via_private_t * dev_priv = ( drm_via_private_t * ) dev - > dev_private ;
2005-09-25 08:28:13 +04:00
via_release_futex ( dev_priv , context ) ;
2005-06-28 16:48:56 +04:00
/* Linux specific until context tracking code gets ported to BSD */
/* Last context, perform cleanup */
if ( dev - > ctx_count = = 1 & & dev - > dev_private ) {
2005-09-25 08:28:13 +04:00
DRM_DEBUG ( " Last Context \n " ) ;
2005-06-28 16:48:56 +04:00
if ( dev - > irq )
drm_irq_uninstall ( dev ) ;
via_cleanup_futex ( dev_priv ) ;
via_do_cleanup_map ( dev ) ;
}
return 1 ;
}
2006-08-07 16:03:22 +04:00
void via_lastclose ( struct drm_device * dev )
{
drm_via_private_t * dev_priv = ( drm_via_private_t * ) dev - > dev_private ;
if ( ! dev_priv )
return ;
mutex_lock ( & dev - > struct_mutex ) ;
drm_sman_cleanup ( & dev_priv - > sman ) ;
2006-08-14 05:35:15 +04:00
dev_priv - > vram_initialized = 0 ;
dev_priv - > agp_initialized = 0 ;
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
2007-11-05 05:50:58 +03:00
}
2006-08-07 16:03:22 +04:00
2007-09-03 06:06:45 +04:00
int via_mem_alloc ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
2005-06-28 16:48:56 +04:00
{
2007-09-03 06:06:45 +04:00
drm_via_mem_t * mem = data ;
2006-08-07 16:03:22 +04:00
int retval = 0 ;
2007-07-12 04:21:05 +04:00
struct drm_memblock_item * item ;
2006-08-07 16:03:22 +04:00
drm_via_private_t * dev_priv = ( drm_via_private_t * ) dev - > dev_private ;
unsigned long tmpSize ;
2005-06-28 16:48:56 +04:00
2007-09-03 06:06:45 +04:00
if ( mem - > type > VIA_MEM_AGP ) {
2006-08-07 16:03:22 +04:00
DRM_ERROR ( " Unknown memory type allocation \n " ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-06-28 16:48:56 +04:00
}
2006-08-07 16:03:22 +04:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-09-03 06:06:45 +04:00
if ( 0 = = ( ( mem - > type = = VIA_MEM_VIDEO ) ? dev_priv - > vram_initialized :
2006-08-07 16:03:22 +04:00
dev_priv - > agp_initialized ) ) {
DRM_ERROR
( " Attempt to allocate from uninitialized memory manager. \n " ) ;
mutex_unlock ( & dev - > struct_mutex ) ;
2007-08-25 13:22:43 +04:00
return - EINVAL ;
2005-06-28 16:48:56 +04:00
}
2007-09-03 06:06:45 +04:00
tmpSize = ( mem - > size + VIA_MM_ALIGN_MASK ) > > VIA_MM_ALIGN_SHIFT ;
item = drm_sman_alloc ( & dev_priv - > sman , mem - > type , tmpSize , 0 ,
2007-08-25 14:23:09 +04:00
( unsigned long ) file_priv ) ;
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
if ( item ) {
2007-09-03 06:06:45 +04:00
mem - > offset = ( ( mem - > type = = VIA_MEM_VIDEO ) ?
2006-08-07 16:03:22 +04:00
dev_priv - > vram_offset : dev_priv - > agp_offset ) +
( item - > mm - >
offset ( item - > mm , item - > mm_info ) < < VIA_MM_ALIGN_SHIFT ) ;
2007-09-03 06:06:45 +04:00
mem - > index = item - > user_hash . key ;
2005-06-28 16:48:56 +04:00
} else {
2007-09-03 06:06:45 +04:00
mem - > offset = 0 ;
mem - > size = 0 ;
mem - > index = 0 ;
2006-08-07 16:03:22 +04:00
DRM_DEBUG ( " Video memory allocation failed \n " ) ;
2007-08-25 13:22:43 +04:00
retval = - ENOMEM ;
2005-06-28 16:48:56 +04:00
}
return retval ;
}
2007-09-03 06:06:45 +04:00
int via_mem_free ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-06-28 16:48:56 +04:00
{
2006-08-07 16:03:22 +04:00
drm_via_private_t * dev_priv = dev - > dev_private ;
2007-09-03 06:06:45 +04:00
drm_via_mem_t * mem = data ;
2006-08-07 16:03:22 +04:00
int ret ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-09-03 06:06:45 +04:00
ret = drm_sman_free_key ( & dev_priv - > sman , mem - > index ) ;
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
2007-09-03 06:06:45 +04:00
DRM_DEBUG ( " free = 0x%lx \n " , mem - > index ) ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
return ret ;
2005-06-28 16:48:56 +04:00
}
2007-08-25 14:23:09 +04:00
void via_reclaim_buffers_locked ( struct drm_device * dev ,
struct drm_file * file_priv )
2005-06-28 16:48:56 +04:00
{
2006-08-07 16:03:22 +04:00
drm_via_private_t * dev_priv = dev - > dev_private ;
2005-06-28 16:48:56 +04:00
2006-08-07 16:03:22 +04:00
mutex_lock ( & dev - > struct_mutex ) ;
2007-08-25 14:23:09 +04:00
if ( drm_sman_owner_clean ( & dev_priv - > sman , ( unsigned long ) file_priv ) ) {
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
return ;
2005-06-28 16:48:56 +04:00
}
2006-08-07 16:03:22 +04:00
if ( dev - > driver - > dma_quiescent ) {
dev - > driver - > dma_quiescent ( dev ) ;
}
2005-06-28 16:48:56 +04:00
2007-08-25 14:23:09 +04:00
drm_sman_owner_cleanup ( & dev_priv - > sman , ( unsigned long ) file_priv ) ;
2006-08-07 16:03:22 +04:00
mutex_unlock ( & dev - > struct_mutex ) ;
return ;
2005-06-28 16:48:56 +04:00
}