2006-01-21 01:08:59 +03:00
2005-04-17 02:20:36 +04:00
/*
* drm_sysfs . c - Modifications to drm_sysfs_class . c to support
* extra sysfs attribute from DRM . Normal drm_sysfs_class
* does not allow adding attributes .
*
* Copyright ( c ) 2004 Jon Smirl < jonsmirl @ gmail . com >
* Copyright ( c ) 2003 - 2004 Greg Kroah - Hartman < greg @ kroah . com >
* Copyright ( c ) 2003 - 2004 IBM Corp .
*
* This file is released under the GPLv2
*
*/
# include <linux/device.h>
# include <linux/kdev_t.h>
# include <linux/err.h>
# include "drm_core.h"
2005-09-05 15:33:44 +04:00
# include "drmP.h"
2005-04-17 02:20:36 +04:00
2007-11-22 07:02:38 +03:00
# define to_drm_device(d) container_of(d, struct drm_device, dev)
/**
* drm_sysfs_suspend - DRM class suspend hook
* @ dev : Linux device to suspend
* @ state : power state to enter
*
* Just figures out what the actual struct drm_device associated with
* @ dev is and calls its suspend hook , if present .
*/
static int drm_sysfs_suspend ( struct device * dev , pm_message_t state )
{
struct drm_device * drm_dev = to_drm_device ( dev ) ;
printk ( KERN_ERR " %s \n " , __FUNCTION__ ) ;
if ( drm_dev - > driver - > suspend )
2008-02-20 03:02:20 +03:00
return drm_dev - > driver - > suspend ( drm_dev , state ) ;
2007-11-22 07:02:38 +03:00
return 0 ;
}
/**
* drm_sysfs_resume - DRM class resume hook
* @ dev : Linux device to resume
*
* Just figures out what the actual struct drm_device associated with
* @ dev is and calls its resume hook , if present .
*/
static int drm_sysfs_resume ( struct device * dev )
{
struct drm_device * drm_dev = to_drm_device ( dev ) ;
if ( drm_dev - > driver - > resume )
return drm_dev - > driver - > resume ( drm_dev ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
/* Display the version of drm_core. This doesn't work right in current design */
static ssize_t version_show ( struct class * dev , char * buf )
{
return sprintf ( buf , " %s %d.%d.%d %s \n " , CORE_NAME , CORE_MAJOR ,
CORE_MINOR , CORE_PATCHLEVEL , CORE_DATE ) ;
}
static CLASS_ATTR ( version , S_IRUGO , version_show , NULL ) ;
/**
* drm_sysfs_create - create a struct drm_sysfs_class structure
* @ owner : pointer to the module that is to " own " this struct drm_sysfs_class
* @ name : pointer to a string for the name of this class .
*
2007-11-22 07:02:38 +03:00
* This is used to create DRM class pointer that can then be used
2005-04-17 02:20:36 +04:00
* in calls to drm_sysfs_device_add ( ) .
*
* Note , the pointer created here is to be destroyed when finished by making a
* call to drm_sysfs_destroy ( ) .
*/
2006-01-21 01:08:59 +03:00
struct class * drm_sysfs_create ( struct module * owner , char * name )
2005-04-17 02:20:36 +04:00
{
2006-01-21 01:08:59 +03:00
struct class * class ;
2006-10-11 01:23:37 +04:00
int err ;
2006-01-21 01:08:59 +03:00
class = class_create ( owner , name ) ;
2006-12-09 02:49:47 +03:00
if ( IS_ERR ( class ) ) {
err = PTR_ERR ( class ) ;
2006-10-11 01:23:37 +04:00
goto err_out ;
}
2007-11-22 07:02:38 +03:00
class - > suspend = drm_sysfs_suspend ;
class - > resume = drm_sysfs_resume ;
2006-10-11 01:23:37 +04:00
err = class_create_file ( class , & class_attr_version ) ;
if ( err )
goto err_out_class ;
2006-01-21 01:08:59 +03:00
return class ;
2006-10-11 01:23:37 +04:00
err_out_class :
class_destroy ( class ) ;
err_out :
return ERR_PTR ( err ) ;
2005-04-17 02:20:36 +04:00
}
/**
2007-11-22 07:02:38 +03:00
* drm_sysfs_destroy - destroys DRM class
2005-04-17 02:20:36 +04:00
*
2007-11-22 07:02:38 +03:00
* Destroy the DRM device class .
2005-04-17 02:20:36 +04:00
*/
2007-11-22 07:02:38 +03:00
void drm_sysfs_destroy ( void )
2005-04-17 02:20:36 +04:00
{
2007-11-22 07:02:38 +03:00
if ( ( drm_class = = NULL ) | | ( IS_ERR ( drm_class ) ) )
2005-04-17 02:20:36 +04:00
return ;
2007-11-22 07:02:38 +03:00
class_remove_file ( drm_class , & class_attr_version ) ;
class_destroy ( drm_class ) ;
2005-04-17 02:20:36 +04:00
}
2007-11-22 07:02:38 +03:00
static ssize_t show_dri ( struct device * device , struct device_attribute * attr ,
char * buf )
2005-11-11 14:07:35 +03:00
{
2007-11-22 07:02:38 +03:00
struct drm_device * dev = to_drm_device ( device ) ;
2005-11-11 14:07:35 +03:00
if ( dev - > driver - > dri_library_name )
return dev - > driver - > dri_library_name ( dev , buf ) ;
return snprintf ( buf , PAGE_SIZE , " %s \n " , dev - > driver - > pci_driver . name ) ;
}
2007-11-22 07:02:38 +03:00
static struct device_attribute device_attrs [ ] = {
2005-11-11 14:07:35 +03:00
__ATTR ( dri_library_name , S_IRUGO , show_dri , NULL ) ,
} ;
2007-11-22 07:02:38 +03:00
/**
* drm_sysfs_device_release - do nothing
* @ dev : Linux device
*
* Normally , this would free the DRM device associated with @ dev , along
* with cleaning up any other stuff . But we do that in the DRM core , so
* this function can just return and hope that the core does its job .
*/
static void drm_sysfs_device_release ( struct device * dev )
{
return ;
}
2005-04-17 02:20:36 +04:00
/**
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
2007-11-22 07:02:38 +03:00
* @ dev : DRM device to be added
* @ head : DRM head in question
2005-04-17 02:20:36 +04:00
*
2007-11-22 07:02:38 +03:00
* Add a DRM device to the DRM ' s device model class . We use @ dev ' s PCI device
* as the parent for the Linux device , and make sure it has a file containing
* the driver we ' re using ( for userspace compatibility ) .
2005-04-17 02:20:36 +04:00
*/
2007-11-22 07:02:38 +03:00
int drm_sysfs_device_add ( struct drm_device * dev , struct drm_head * head )
2005-04-17 02:20:36 +04:00
{
2007-11-22 07:02:38 +03:00
int err ;
int i , j ;
dev - > dev . parent = & dev - > pdev - > dev ;
dev - > dev . class = drm_class ;
dev - > dev . release = drm_sysfs_device_release ;
2007-11-29 02:48:20 +03:00
dev - > dev . devt = head - > device ;
2007-11-22 07:02:38 +03:00
snprintf ( dev - > dev . bus_id , BUS_ID_SIZE , " card%d " , head - > minor ) ;
err = device_register ( & dev - > dev ) ;
if ( err ) {
DRM_ERROR ( " device add failed: %d \n " , err ) ;
2006-10-11 01:23:37 +04:00
goto err_out ;
}
2005-04-17 02:20:36 +04:00
2007-11-22 07:02:38 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( device_attrs ) ; i + + ) {
err = device_create_file ( & dev - > dev , & device_attrs [ i ] ) ;
2006-10-11 01:23:37 +04:00
if ( err )
goto err_out_files ;
}
2007-11-22 07:02:38 +03:00
return 0 ;
2006-10-11 01:23:37 +04:00
err_out_files :
if ( i > 0 )
for ( j = 0 ; j < i ; j + + )
2007-11-22 07:02:38 +03:00
device_remove_file ( & dev - > dev , & device_attrs [ i ] ) ;
device_unregister ( & dev - > dev ) ;
2006-10-11 01:23:37 +04:00
err_out :
2007-11-22 07:02:38 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
/**
2007-11-22 07:02:38 +03:00
* drm_sysfs_device_remove - remove DRM device
* @ dev : DRM device to remove
2005-04-17 02:20:36 +04:00
*
* This call unregisters and cleans up a class device that was created with a
* call to drm_sysfs_device_add ( )
*/
2007-11-22 07:02:38 +03:00
void drm_sysfs_device_remove ( struct drm_device * dev )
2005-04-17 02:20:36 +04:00
{
2005-11-11 14:07:35 +03:00
int i ;
2007-11-22 07:02:38 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( device_attrs ) ; i + + )
device_remove_file ( & dev - > dev , & device_attrs [ i ] ) ;
device_unregister ( & dev - > dev ) ;
2005-04-17 02:20:36 +04:00
}