2019-05-31 01:09:37 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2012-04-17 15:01:25 +01:00
/*
* Copyright 2012 Red Hat
*
* Authors : Matthew Garrett
* Dave Airlie
*/
2019-06-23 12:35:42 +02:00
2012-04-17 15:01:25 +01:00
# include <linux/console.h>
2019-12-05 10:02:52 +01:00
# include <linux/module.h>
# include <linux/pci.h>
2012-04-17 15:01:25 +01:00
2019-06-23 12:35:42 +02:00
# include <drm/drm_drv.h>
# include <drm/drm_file.h>
# include <drm/drm_ioctl.h>
2012-10-02 18:01:07 +01:00
# include <drm/drm_pciids.h>
2012-04-17 15:01:25 +01:00
2019-06-23 12:35:42 +02:00
# include "mgag200_drv.h"
2020-05-15 10:32:33 +02:00
int mgag200_modeset = - 1 ;
2012-04-17 15:01:25 +01:00
MODULE_PARM_DESC ( modeset , " Disable/Enable modesetting " ) ;
module_param_named ( modeset , mgag200_modeset , int , 0400 ) ;
2020-06-05 15:57:57 +02:00
/*
* DRM driver
*/
DEFINE_DRM_GEM_FOPS ( mgag200_driver_fops ) ;
2020-06-05 15:57:58 +02:00
static struct drm_driver mgag200_driver = {
2020-06-05 15:57:57 +02:00
. driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET ,
. fops = & mgag200_driver_fops ,
. name = DRIVER_NAME ,
. desc = DRIVER_DESC ,
. date = DRIVER_DATE ,
. major = DRIVER_MAJOR ,
. minor = DRIVER_MINOR ,
. patchlevel = DRIVER_PATCHLEVEL ,
2020-07-30 12:28:37 +02:00
. gem_create_object = drm_gem_shmem_create_object_cached ,
2020-06-05 15:57:57 +02:00
DRM_GEM_SHMEM_DRIVER_OPS ,
} ;
2020-06-05 15:57:59 +02:00
/*
* DRM device
*/
2020-07-30 12:28:38 +02:00
static bool mgag200_has_sgram ( struct mga_device * mdev )
2020-06-05 15:57:59 +02:00
{
2020-06-05 15:58:02 +02:00
struct drm_device * dev = & mdev - > base ;
2020-07-30 12:28:38 +02:00
u32 option ;
int ret ;
2020-06-05 15:57:59 +02:00
2020-07-30 12:28:38 +02:00
ret = pci_read_config_dword ( dev - > pdev , PCI_MGA_OPTION , & option ) ;
if ( drm_WARN ( dev , ret , " failed to read PCI config dword: %d \n " , ret ) )
return false ;
return ! ! ( option & PCI_MGA_OPTION_HARDPWMSK ) ;
}
2020-06-05 15:57:59 +02:00
2020-07-30 12:28:38 +02:00
static int mgag200_regs_init ( struct mga_device * mdev )
{
struct drm_device * dev = & mdev - > base ;
mdev - > has_sdram = ! mgag200_has_sgram ( mdev ) ;
2020-06-05 15:57:59 +02:00
2020-07-30 12:28:38 +02:00
/* BAR 1 contains registers */
2020-06-05 15:57:59 +02:00
mdev - > rmmio_base = pci_resource_start ( dev - > pdev , 1 ) ;
mdev - > rmmio_size = pci_resource_len ( dev - > pdev , 1 ) ;
if ( ! devm_request_mem_region ( dev - > dev , mdev - > rmmio_base ,
mdev - > rmmio_size , " mgadrmfb_mmio " ) ) {
drm_err ( dev , " can't reserve mmio registers \n " ) ;
return - ENOMEM ;
}
mdev - > rmmio = pcim_iomap ( dev - > pdev , 1 , 0 ) ;
if ( mdev - > rmmio = = NULL )
return - ENOMEM ;
2020-07-30 12:28:38 +02:00
return 0 ;
}
static int mgag200_device_init ( struct mga_device * mdev , unsigned long flags )
{
struct drm_device * dev = & mdev - > base ;
int ret ;
mdev - > flags = mgag200_flags_from_driver_data ( flags ) ;
mdev - > type = mgag200_type_from_driver_data ( flags ) ;
ret = mgag200_regs_init ( mdev ) ;
if ( ret )
return ret ;
2020-06-05 15:57:59 +02:00
/* stash G200 SE model number for later use */
if ( IS_G200_SE ( mdev ) ) {
mdev - > unique_rev_id = RREG32 ( 0x1e24 ) ;
drm_dbg ( dev , " G200 SE unique revision id is 0x%x \n " ,
mdev - > unique_rev_id ) ;
}
ret = mgag200_mm_init ( mdev ) ;
if ( ret )
2020-06-05 15:58:00 +02:00
return ret ;
2020-06-05 15:57:59 +02:00
ret = mgag200_modeset_init ( mdev ) ;
if ( ret ) {
drm_err ( dev , " Fatal error during modeset init: %d \n " , ret ) ;
2020-06-05 15:58:00 +02:00
return ret ;
2020-06-05 15:57:59 +02:00
}
return 0 ;
2020-06-05 15:58:00 +02:00
}
2020-06-05 15:58:01 +02:00
static struct mga_device *
2020-06-05 15:58:02 +02:00
mgag200_device_create ( struct pci_dev * pdev , unsigned long flags )
2020-06-05 15:58:00 +02:00
{
2020-06-05 15:58:01 +02:00
struct drm_device * dev ;
2020-06-05 15:58:00 +02:00
struct mga_device * mdev ;
int ret ;
2020-06-05 15:58:03 +02:00
mdev = devm_drm_dev_alloc ( & pdev - > dev , & mgag200_driver ,
struct mga_device , base ) ;
if ( IS_ERR ( mdev ) )
return mdev ;
2020-06-05 15:58:02 +02:00
dev = & mdev - > base ;
2020-06-05 15:58:01 +02:00
dev - > pdev = pdev ;
pci_set_drvdata ( pdev , dev ) ;
2020-06-05 15:58:00 +02:00
ret = mgag200_device_init ( mdev , flags ) ;
if ( ret )
2020-06-05 15:58:03 +02:00
return ERR_PTR ( ret ) ;
2020-06-05 15:58:00 +02:00
2020-06-05 15:58:01 +02:00
return mdev ;
2020-06-05 15:57:59 +02:00
}
2020-06-05 15:57:57 +02:00
/*
* PCI driver
*/
2012-04-17 15:01:25 +01:00
2020-06-05 15:57:58 +02:00
static const struct pci_device_id mgag200_pciidlist [ ] = {
2019-12-06 09:19:01 +01:00
{ PCI_VENDOR_ID_MATROX , 0x522 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 ,
2019-11-26 11:15:29 +01:00
G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD } ,
2012-04-17 15:01:25 +01:00
{ PCI_VENDOR_ID_MATROX , 0x524 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_SE_B } ,
{ PCI_VENDOR_ID_MATROX , 0x530 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_EV } ,
{ PCI_VENDOR_ID_MATROX , 0x532 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_WB } ,
{ PCI_VENDOR_ID_MATROX , 0x533 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_EH } ,
{ PCI_VENDOR_ID_MATROX , 0x534 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_ER } ,
2015-08-21 09:24:05 -04:00
{ PCI_VENDOR_ID_MATROX , 0x536 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_EW3 } ,
2016-10-21 12:47:07 -04:00
{ PCI_VENDOR_ID_MATROX , 0x538 , PCI_ANY_ID , PCI_ANY_ID , 0 , 0 , G200_EH3 } ,
2012-04-17 15:01:25 +01:00
{ 0 , }
} ;
2020-06-05 15:57:58 +02:00
MODULE_DEVICE_TABLE ( pci , mgag200_pciidlist ) ;
2012-04-17 15:01:25 +01:00
2020-06-05 15:57:58 +02:00
static int
mgag200_pci_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
2012-04-17 15:01:25 +01:00
{
2020-06-05 15:58:01 +02:00
struct mga_device * mdev ;
2019-12-05 10:02:52 +01:00
struct drm_device * dev ;
int ret ;
2019-08-22 11:06:44 +02:00
drm_fb_helper_remove_conflicting_pci_framebuffers ( pdev , " mgag200drmfb " ) ;
2012-06-01 11:12:39 +01:00
2020-06-05 15:57:52 +02:00
ret = pcim_enable_device ( pdev ) ;
2019-12-05 10:02:52 +01:00
if ( ret )
return ret ;
2020-06-05 15:58:02 +02:00
mdev = mgag200_device_create ( pdev , ent - > driver_data ) ;
2020-06-05 15:58:03 +02:00
if ( IS_ERR ( mdev ) )
return PTR_ERR ( mdev ) ;
2020-06-05 15:58:02 +02:00
dev = & mdev - > base ;
2019-12-05 10:02:52 +01:00
ret = drm_dev_register ( dev , ent - > driver_data ) ;
if ( ret )
2020-06-05 15:58:03 +02:00
return ret ;
2019-12-05 10:02:52 +01:00
2020-04-08 10:26:37 +02:00
drm_fbdev_generic_setup ( dev , 0 ) ;
2019-12-05 10:02:52 +01:00
return 0 ;
2012-04-17 15:01:25 +01:00
}
2020-06-05 15:57:58 +02:00
static void mgag200_pci_remove ( struct pci_dev * pdev )
2012-04-17 15:01:25 +01:00
{
struct drm_device * dev = pci_get_drvdata ( pdev ) ;
2019-12-05 10:02:52 +01:00
drm_dev_unregister ( dev ) ;
2012-04-17 15:01:25 +01:00
}
static struct pci_driver mgag200_pci_driver = {
. name = DRIVER_NAME ,
2020-06-05 15:57:58 +02:00
. id_table = mgag200_pciidlist ,
. probe = mgag200_pci_probe ,
. remove = mgag200_pci_remove ,
2012-04-17 15:01:25 +01:00
} ;
static int __init mgag200_init ( void )
{
if ( vgacon_text_force ( ) & & mgag200_modeset = = - 1 )
return - EINVAL ;
if ( mgag200_modeset = = 0 )
return - EINVAL ;
2017-05-24 16:51:40 +02:00
return pci_register_driver ( & mgag200_pci_driver ) ;
2012-04-17 15:01:25 +01:00
}
static void __exit mgag200_exit ( void )
{
2017-05-24 16:51:40 +02:00
pci_unregister_driver ( & mgag200_pci_driver ) ;
2012-04-17 15:01:25 +01:00
}
module_init ( mgag200_init ) ;
module_exit ( mgag200_exit ) ;
MODULE_AUTHOR ( DRIVER_AUTHOR ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL " ) ;