2011-11-03 18:22:04 +00:00
/**************************************************************************
* Copyright ( c ) 2007 - 2011 , Intel Corporation .
* All Rights Reserved .
* Copyright ( c ) 2008 , Tungsten Graphics , Inc . Cedar Park , TX . , USA .
* All Rights Reserved .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <drm/drmP.h>
# include <drm/drm.h>
2011-11-16 22:39:45 +00:00
# include "gma_drm.h"
2011-11-03 18:22:04 +00:00
# include "psb_drv.h"
# include "framebuffer.h"
# include "psb_reg.h"
# include "psb_intel_reg.h"
# include "intel_bios.h"
# include "mid_bios.h"
# include <drm/drm_pciids.h>
# include "power.h"
# include <linux/cpu.h>
# include <linux/notifier.h>
# include <linux/spinlock.h>
# include <linux/pm_runtime.h>
# include <acpi/video.h>
2011-11-16 12:13:30 +00:00
# include <linux/module.h>
2011-11-03 18:22:04 +00:00
static int drm_psb_trap_pagefaults ;
int drm_psb_no_fb ;
static int psb_probe ( struct pci_dev * pdev , const struct pci_device_id * ent ) ;
MODULE_PARM_DESC ( no_fb , " Disable FBdev " ) ;
MODULE_PARM_DESC ( trap_pagefaults , " Error and reset on MMU pagefaults " ) ;
module_param_named ( no_fb , drm_psb_no_fb , int , 0600 ) ;
module_param_named ( trap_pagefaults , drm_psb_trap_pagefaults , int , 0600 ) ;
static DEFINE_PCI_DEVICE_TABLE ( pciidlist ) = {
{ 0x8086 , 0x8108 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & psb_chip_ops } ,
{ 0x8086 , 0x8109 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & psb_chip_ops } ,
# if defined(CONFIG_DRM_OAKTRAIL)
{ 0x8086 , 0x4100 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4101 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4102 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4103 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4104 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4105 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4106 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
{ 0x8086 , 0x4107 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & oaktrail_chip_ops } ,
# endif
# if defined(CONFIG_DRM_CDV)
{ 0x8086 , 0x0be0 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be1 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be2 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be3 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be4 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be5 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be6 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
{ 0x8086 , 0x0be7 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , ( long ) & cdv_chip_ops } ,
# endif
{ 0 , 0 , 0 }
} ;
MODULE_DEVICE_TABLE ( pci , pciidlist ) ;
/*
* Standard IOCTLs .
*/
# define DRM_IOCTL_PSB_ADB \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_ADB + DRM_COMMAND_BASE , uint32_t )
2011-11-03 18:22:04 +00:00
# define DRM_IOCTL_PSB_MODE_OPERATION \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
struct drm_psb_mode_operation_arg )
# define DRM_IOCTL_PSB_STOLEN_MEMORY \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
struct drm_psb_stolen_memory_arg )
# define DRM_IOCTL_PSB_GAMMA \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_GAMMA + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
struct drm_psb_dpst_lut_arg )
# define DRM_IOCTL_PSB_DPST_BL \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_DPST_BL + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
uint32_t )
# define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
struct drm_psb_get_pipe_from_crtc_id_arg )
# define DRM_IOCTL_PSB_GEM_CREATE \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
struct drm_psb_gem_create )
# define DRM_IOCTL_PSB_GEM_MMAP \
2011-11-16 22:39:18 +00:00
DRM_IOWR ( DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE , \
2011-11-03 18:22:04 +00:00
struct drm_psb_gem_mmap )
static int psb_adb_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
static int psb_mode_operation_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
static int psb_stolen_memory_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
static int psb_gamma_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
static int psb_dpst_bl_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv ) ;
# define PSB_IOCTL_DEF(ioctl, func, flags) \
[ DRM_IOCTL_NR ( ioctl ) - DRM_COMMAND_BASE ] = { ioctl , flags , func }
static struct drm_ioctl_desc psb_ioctls [ ] = {
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_ADB , psb_adb_ioctl , DRM_AUTH ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_MODE_OPERATION , psb_mode_operation_ioctl ,
DRM_AUTH ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_STOLEN_MEMORY , psb_stolen_memory_ioctl ,
DRM_AUTH ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_GAMMA , psb_gamma_ioctl , DRM_AUTH ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_DPST_BL , psb_dpst_bl_ioctl , DRM_AUTH ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID ,
psb_intel_get_pipe_from_crtc_id , 0 ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_GEM_CREATE , psb_gem_create_ioctl ,
DRM_UNLOCKED | DRM_AUTH ) ,
PSB_IOCTL_DEF ( DRM_IOCTL_PSB_GEM_MMAP , psb_gem_mmap_ioctl ,
DRM_UNLOCKED | DRM_AUTH ) ,
} ;
static void psb_lastclose ( struct drm_device * dev )
{
return ;
}
static void psb_do_takedown ( struct drm_device * dev )
{
/* FIXME: do we need to clean up the gtt here ? */
}
static int psb_do_init ( struct drm_device * dev )
{
struct drm_psb_private * dev_priv = dev - > dev_private ;
struct psb_gtt * pg = & dev_priv - > gtt ;
uint32_t stolen_gtt ;
int ret = - ENOMEM ;
if ( pg - > mmu_gatt_start & 0x0FFFFFFF ) {
dev_err ( dev - > dev , " Gatt must be 256M aligned. This is a bug. \n " ) ;
ret = - EINVAL ;
goto out_err ;
}
stolen_gtt = ( pg - > stolen_size > > PAGE_SHIFT ) * 4 ;
stolen_gtt = ( stolen_gtt + PAGE_SIZE - 1 ) > > PAGE_SHIFT ;
stolen_gtt =
( stolen_gtt < pg - > gtt_pages ) ? stolen_gtt : pg - > gtt_pages ;
dev_priv - > gatt_free_offset = pg - > mmu_gatt_start +
( stolen_gtt < < PAGE_SHIFT ) * 1024 ;
if ( 1 | | drm_debug ) {
uint32_t core_id = PSB_RSGX32 ( PSB_CR_CORE_ID ) ;
uint32_t core_rev = PSB_RSGX32 ( PSB_CR_CORE_REVISION ) ;
DRM_INFO ( " SGX core id = 0x%08x \n " , core_id ) ;
DRM_INFO ( " SGX core rev major = 0x%02x, minor = 0x%02x \n " ,
( core_rev & _PSB_CC_REVISION_MAJOR_MASK ) > >
_PSB_CC_REVISION_MAJOR_SHIFT ,
( core_rev & _PSB_CC_REVISION_MINOR_MASK ) > >
_PSB_CC_REVISION_MINOR_SHIFT ) ;
DRM_INFO
( " SGX core rev maintenance = 0x%02x, designer = 0x%02x \n " ,
( core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK ) > >
_PSB_CC_REVISION_MAINTENANCE_SHIFT ,
( core_rev & _PSB_CC_REVISION_DESIGNER_MASK ) > >
_PSB_CC_REVISION_DESIGNER_SHIFT ) ;
}
spin_lock_init ( & dev_priv - > irqmask_lock ) ;
mutex_init ( & dev_priv - > mutex_2d ) ;
PSB_WSGX32 ( 0x00000000 , PSB_CR_BIF_BANK0 ) ;
PSB_WSGX32 ( 0x00000000 , PSB_CR_BIF_BANK1 ) ;
PSB_RSGX32 ( PSB_CR_BIF_BANK1 ) ;
PSB_WSGX32 ( PSB_RSGX32 ( PSB_CR_BIF_CTRL ) | _PSB_MMU_ER_MASK ,
PSB_CR_BIF_CTRL ) ;
psb_spank ( dev_priv ) ;
/* mmu_gatt ?? */
PSB_WSGX32 ( pg - > gatt_start , PSB_CR_BIF_TWOD_REQ_BASE ) ;
return 0 ;
out_err :
psb_do_takedown ( dev ) ;
return ret ;
}
static int psb_driver_unload ( struct drm_device * dev )
{
struct drm_psb_private * dev_priv = dev - > dev_private ;
/* Kill vblank etc here */
gma_backlight_exit ( dev ) ;
if ( drm_psb_no_fb = = 0 )
psb_modeset_cleanup ( dev ) ;
if ( dev_priv ) {
psb_lid_timer_takedown ( dev_priv ) ;
gma_intel_opregion_exit ( dev ) ;
if ( dev_priv - > ops - > chip_teardown )
dev_priv - > ops - > chip_teardown ( dev ) ;
psb_do_takedown ( dev ) ;
if ( dev_priv - > pf_pd ) {
psb_mmu_free_pagedir ( dev_priv - > pf_pd ) ;
dev_priv - > pf_pd = NULL ;
}
if ( dev_priv - > mmu ) {
struct psb_gtt * pg = & dev_priv - > gtt ;
down_read ( & pg - > sem ) ;
psb_mmu_remove_pfn_sequence (
psb_mmu_get_default_pd
( dev_priv - > mmu ) ,
pg - > mmu_gatt_start ,
dev_priv - > vram_stolen_size > > PAGE_SHIFT ) ;
up_read ( & pg - > sem ) ;
psb_mmu_driver_takedown ( dev_priv - > mmu ) ;
dev_priv - > mmu = NULL ;
}
psb_gtt_takedown ( dev ) ;
if ( dev_priv - > scratch_page ) {
__free_page ( dev_priv - > scratch_page ) ;
dev_priv - > scratch_page = NULL ;
}
if ( dev_priv - > vdc_reg ) {
iounmap ( dev_priv - > vdc_reg ) ;
dev_priv - > vdc_reg = NULL ;
}
if ( dev_priv - > sgx_reg ) {
iounmap ( dev_priv - > sgx_reg ) ;
dev_priv - > sgx_reg = NULL ;
}
kfree ( dev_priv ) ;
dev - > dev_private = NULL ;
/*destroy VBT data*/
psb_intel_destroy_bios ( dev ) ;
}
gma_power_uninit ( dev ) ;
return 0 ;
}
static int psb_driver_load ( struct drm_device * dev , unsigned long chipset )
{
struct drm_psb_private * dev_priv ;
unsigned long resource_start ;
struct psb_gtt * pg ;
unsigned long irqflags ;
int ret = - ENOMEM ;
uint32_t tt_pages ;
struct drm_connector * connector ;
struct psb_intel_output * psb_intel_output ;
dev_priv = kzalloc ( sizeof ( * dev_priv ) , GFP_KERNEL ) ;
if ( dev_priv = = NULL )
return - ENOMEM ;
dev_priv - > ops = ( struct psb_ops * ) chipset ;
dev_priv - > dev = dev ;
dev - > dev_private = ( void * ) dev_priv ;
dev_priv - > num_pipe = dev_priv - > ops - > pipes ;
resource_start = pci_resource_start ( dev - > pdev , PSB_MMIO_RESOURCE ) ;
dev_priv - > vdc_reg =
ioremap ( resource_start + PSB_VDC_OFFSET , PSB_VDC_SIZE ) ;
if ( ! dev_priv - > vdc_reg )
goto out_err ;
dev_priv - > sgx_reg = ioremap ( resource_start + dev_priv - > ops - > sgx_offset ,
PSB_SGX_SIZE ) ;
if ( ! dev_priv - > sgx_reg )
goto out_err ;
ret = dev_priv - > ops - > chip_setup ( dev ) ;
if ( ret )
goto out_err ;
/* Init OSPM support */
gma_power_init ( dev ) ;
ret = - ENOMEM ;
dev_priv - > scratch_page = alloc_page ( GFP_DMA32 | __GFP_ZERO ) ;
if ( ! dev_priv - > scratch_page )
goto out_err ;
set_pages_uc ( dev_priv - > scratch_page , 1 ) ;
ret = psb_gtt_init ( dev , 0 ) ;
if ( ret )
goto out_err ;
dev_priv - > mmu = psb_mmu_driver_init ( ( void * ) 0 ,
drm_psb_trap_pagefaults , 0 ,
dev_priv ) ;
if ( ! dev_priv - > mmu )
goto out_err ;
pg = & dev_priv - > gtt ;
tt_pages = ( pg - > gatt_pages < PSB_TT_PRIV0_PLIMIT ) ?
( pg - > gatt_pages ) : PSB_TT_PRIV0_PLIMIT ;
dev_priv - > pf_pd = psb_mmu_alloc_pd ( dev_priv - > mmu , 1 , 0 ) ;
if ( ! dev_priv - > pf_pd )
goto out_err ;
psb_mmu_set_pd_context ( psb_mmu_get_default_pd ( dev_priv - > mmu ) , 0 ) ;
psb_mmu_set_pd_context ( dev_priv - > pf_pd , 1 ) ;
ret = psb_do_init ( dev ) ;
if ( ret )
return ret ;
PSB_WSGX32 ( 0x20000000 , PSB_CR_PDS_EXEC_BASE ) ;
PSB_WSGX32 ( 0x30000000 , PSB_CR_BIF_3D_REQ_BASE ) ;
/* igd_opregion_init(&dev_priv->opregion_dev); */
acpi_video_register ( ) ;
if ( dev_priv - > lid_state )
psb_lid_timer_init ( dev_priv ) ;
ret = drm_vblank_init ( dev , dev_priv - > num_pipe ) ;
if ( ret )
goto out_err ;
/*
* Install interrupt handlers prior to powering off SGX or else we will
* crash .
*/
dev_priv - > vdc_irq_mask = 0 ;
dev_priv - > pipestat [ 0 ] = 0 ;
dev_priv - > pipestat [ 1 ] = 0 ;
dev_priv - > pipestat [ 2 ] = 0 ;
spin_lock_irqsave ( & dev_priv - > irqmask_lock , irqflags ) ;
PSB_WVDC32 ( 0xFFFFFFFF , PSB_HWSTAM ) ;
PSB_WVDC32 ( 0x00000000 , PSB_INT_ENABLE_R ) ;
PSB_WVDC32 ( 0xFFFFFFFF , PSB_INT_MASK_R ) ;
spin_unlock_irqrestore ( & dev_priv - > irqmask_lock , irqflags ) ;
2011-11-29 22:20:07 +00:00
if ( IS_PSB ( dev ) & & drm_core_check_feature ( dev , DRIVER_MODESET ) )
2011-11-03 18:22:04 +00:00
drm_irq_install ( dev ) ;
dev - > vblank_disable_allowed = 1 ;
dev - > max_vblank_count = 0xffffff ; /* only 24 bits of frame count */
dev - > driver - > get_vblank_counter = psb_get_vblank_counter ;
if ( drm_psb_no_fb = = 0 ) {
psb_modeset_init ( dev ) ;
psb_fbdev_init ( dev ) ;
drm_kms_helper_poll_init ( dev ) ;
}
/* Only add backlight support if we have LVDS output */
list_for_each_entry ( connector , & dev - > mode_config . connector_list ,
head ) {
psb_intel_output = to_psb_intel_output ( connector ) ;
switch ( psb_intel_output - > type ) {
case INTEL_OUTPUT_LVDS :
case INTEL_OUTPUT_MIPI :
ret = gma_backlight_init ( dev ) ;
break ;
}
}
if ( ret )
return ret ;
#if 0
/*enable runtime pm at last*/
pm_runtime_enable ( & dev - > pdev - > dev ) ;
pm_runtime_set_active ( & dev - > pdev - > dev ) ;
# endif
/*Intel drm driver load is done, continue doing pvr load*/
return 0 ;
out_err :
psb_driver_unload ( dev ) ;
return ret ;
}
int psb_driver_device_is_agp ( struct drm_device * dev )
{
return 0 ;
}
static inline void get_brightness ( struct backlight_device * bd )
{
# ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
if ( bd ) {
bd - > props . brightness = bd - > ops - > get_brightness ( bd ) ;
backlight_update_status ( bd ) ;
}
# endif
}
static int psb_dpst_bl_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_psb_private * dev_priv = psb_priv ( dev ) ;
uint32_t * arg = data ;
dev_priv - > blc_adj2 = * arg ;
get_brightness ( dev_priv - > backlight_device ) ;
return 0 ;
}
static int psb_adb_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_psb_private * dev_priv = psb_priv ( dev ) ;
uint32_t * arg = data ;
dev_priv - > blc_adj1 = * arg ;
get_brightness ( dev_priv - > backlight_device ) ;
return 0 ;
}
static int psb_gamma_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_psb_dpst_lut_arg * lut_arg = data ;
struct drm_mode_object * obj ;
struct drm_crtc * crtc ;
struct drm_connector * connector ;
struct psb_intel_crtc * psb_intel_crtc ;
int i = 0 ;
int32_t obj_id ;
obj_id = lut_arg - > output_id ;
obj = drm_mode_object_find ( dev , obj_id , DRM_MODE_OBJECT_CONNECTOR ) ;
if ( ! obj ) {
dev_dbg ( dev - > dev , " Invalid Connector object. \n " ) ;
return - EINVAL ;
}
connector = obj_to_connector ( obj ) ;
crtc = connector - > encoder - > crtc ;
psb_intel_crtc = to_psb_intel_crtc ( crtc ) ;
for ( i = 0 ; i < 256 ; i + + )
psb_intel_crtc - > lut_adj [ i ] = lut_arg - > lut [ i ] ;
psb_intel_crtc_load_lut ( crtc ) ;
return 0 ;
}
static int psb_mode_operation_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
uint32_t obj_id ;
uint16_t op ;
struct drm_mode_modeinfo * umode ;
struct drm_display_mode * mode = NULL ;
struct drm_psb_mode_operation_arg * arg ;
struct drm_mode_object * obj ;
struct drm_connector * connector ;
struct drm_connector_helper_funcs * connector_funcs ;
int ret = 0 ;
int resp = MODE_OK ;
arg = ( struct drm_psb_mode_operation_arg * ) data ;
obj_id = arg - > obj_id ;
op = arg - > operation ;
switch ( op ) {
case PSB_MODE_OPERATION_MODE_VALID :
umode = & arg - > mode ;
mutex_lock ( & dev - > mode_config . mutex ) ;
obj = drm_mode_object_find ( dev , obj_id ,
DRM_MODE_OBJECT_CONNECTOR ) ;
if ( ! obj ) {
ret = - EINVAL ;
goto mode_op_out ;
}
connector = obj_to_connector ( obj ) ;
mode = drm_mode_create ( dev ) ;
if ( ! mode ) {
ret = - ENOMEM ;
goto mode_op_out ;
}
/* drm_crtc_convert_umode(mode, umode); */
{
mode - > clock = umode - > clock ;
mode - > hdisplay = umode - > hdisplay ;
mode - > hsync_start = umode - > hsync_start ;
mode - > hsync_end = umode - > hsync_end ;
mode - > htotal = umode - > htotal ;
mode - > hskew = umode - > hskew ;
mode - > vdisplay = umode - > vdisplay ;
mode - > vsync_start = umode - > vsync_start ;
mode - > vsync_end = umode - > vsync_end ;
mode - > vtotal = umode - > vtotal ;
mode - > vscan = umode - > vscan ;
mode - > vrefresh = umode - > vrefresh ;
mode - > flags = umode - > flags ;
mode - > type = umode - > type ;
strncpy ( mode - > name , umode - > name , DRM_DISPLAY_MODE_LEN ) ;
mode - > name [ DRM_DISPLAY_MODE_LEN - 1 ] = 0 ;
}
connector_funcs = ( struct drm_connector_helper_funcs * )
connector - > helper_private ;
if ( connector_funcs - > mode_valid ) {
resp = connector_funcs - > mode_valid ( connector , mode ) ;
2011-11-16 22:38:42 +00:00
arg - > data = resp ;
2011-11-03 18:22:04 +00:00
}
/*do some clean up work*/
if ( mode )
drm_mode_destroy ( dev , mode ) ;
mode_op_out :
mutex_unlock ( & dev - > mode_config . mutex ) ;
return ret ;
default :
dev_dbg ( dev - > dev , " Unsupported psb mode operation \n " ) ;
return - EOPNOTSUPP ;
}
return 0 ;
}
static int psb_stolen_memory_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_psb_private * dev_priv = psb_priv ( dev ) ;
struct drm_psb_stolen_memory_arg * arg = data ;
arg - > base = dev_priv - > stolen_base ;
arg - > size = dev_priv - > vram_stolen_size ;
return 0 ;
}
static int psb_driver_open ( struct drm_device * dev , struct drm_file * priv )
{
return 0 ;
}
static void psb_driver_close ( struct drm_device * dev , struct drm_file * priv )
{
}
static long psb_unlocked_ioctl ( struct file * filp , unsigned int cmd ,
unsigned long arg )
{
struct drm_file * file_priv = filp - > private_data ;
struct drm_device * dev = file_priv - > minor - > dev ;
struct drm_psb_private * dev_priv = dev - > dev_private ;
static unsigned int runtime_allowed ;
if ( runtime_allowed = = 1 & & dev_priv - > is_lvds_on ) {
runtime_allowed + + ;
pm_runtime_allow ( & dev - > pdev - > dev ) ;
dev_priv - > rpm_enabled = 1 ;
}
return drm_ioctl ( filp , cmd , arg ) ;
/* FIXME: do we need to wrap the other side of this */
}
/* When a client dies:
* - Check for and clean up flipped page state
*/
void psb_driver_preclose ( struct drm_device * dev , struct drm_file * priv )
{
}
static void psb_remove ( struct pci_dev * pdev )
{
struct drm_device * dev = pci_get_drvdata ( pdev ) ;
drm_put_dev ( dev ) ;
}
static const struct dev_pm_ops psb_pm_ops = {
. resume = gma_power_resume ,
. suspend = gma_power_suspend ,
. runtime_suspend = psb_runtime_suspend ,
. runtime_resume = psb_runtime_resume ,
. runtime_idle = psb_runtime_idle ,
} ;
static struct vm_operations_struct psb_gem_vm_ops = {
. fault = psb_gem_fault ,
. open = drm_gem_vm_open ,
. close = drm_gem_vm_close ,
} ;
2011-11-27 11:08:33 -05:00
static const struct file_operations psb_gem_fops = {
. owner = THIS_MODULE ,
. open = drm_open ,
. release = drm_release ,
. unlocked_ioctl = psb_unlocked_ioctl ,
. mmap = drm_gem_mmap ,
. poll = drm_poll ,
. fasync = drm_fasync ,
. read = drm_read ,
} ;
2011-11-03 18:22:04 +00:00
static struct drm_driver driver = {
. driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
. load = psb_driver_load ,
. unload = psb_driver_unload ,
. ioctls = psb_ioctls ,
. num_ioctls = DRM_ARRAY_SIZE ( psb_ioctls ) ,
. device_is_agp = psb_driver_device_is_agp ,
. irq_preinstall = psb_irq_preinstall ,
. irq_postinstall = psb_irq_postinstall ,
. irq_uninstall = psb_irq_uninstall ,
. irq_handler = psb_irq_handler ,
. enable_vblank = psb_enable_vblank ,
. disable_vblank = psb_disable_vblank ,
. get_vblank_counter = psb_get_vblank_counter ,
. lastclose = psb_lastclose ,
. open = psb_driver_open ,
. preclose = psb_driver_preclose ,
. postclose = psb_driver_close ,
. reclaim_buffers = drm_core_reclaim_buffers ,
. gem_init_object = psb_gem_init_object ,
. gem_free_object = psb_gem_free_object ,
. gem_vm_ops = & psb_gem_vm_ops ,
. dumb_create = psb_gem_dumb_create ,
. dumb_map_offset = psb_gem_dumb_map_gtt ,
. dumb_destroy = psb_gem_dumb_destroy ,
2011-11-27 11:08:33 -05:00
. fops = & psb_gem_fops ,
2011-11-03 18:22:04 +00:00
. name = DRIVER_NAME ,
. desc = DRIVER_DESC ,
. date = PSB_DRM_DRIVER_DATE ,
. major = PSB_DRM_DRIVER_MAJOR ,
. minor = PSB_DRM_DRIVER_MINOR ,
. patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
} ;
static struct pci_driver psb_pci_driver = {
. name = DRIVER_NAME ,
. id_table = pciidlist ,
. probe = psb_probe ,
. remove = psb_remove ,
. driver . pm = & psb_pm_ops ,
} ;
static int psb_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
{
/* MLD Added this from Inaky's patch */
if ( pci_enable_msi ( pdev ) )
dev_warn ( & pdev - > dev , " Enable MSI failed! \n " ) ;
return drm_get_pci_dev ( pdev , ent , & driver ) ;
}
static int __init psb_init ( void )
{
return drm_pci_init ( & driver , & psb_pci_driver ) ;
}
static void __exit psb_exit ( void )
{
drm_pci_exit ( & driver , & psb_pci_driver ) ;
}
late_initcall ( psb_init ) ;
module_exit ( psb_exit ) ;
MODULE_AUTHOR ( " Alan Cox <alan@linux.intel.com> and others " ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL " ) ;