2018-10-18 17:03:32 +02:00
// SPDX-License-Identifier: MIT
2017-07-06 16:06:01 +02:00
/*
* Copyright ( C ) 2013 - 2017 Oracle Corporation
* This file is based on ast_drv . c
* Copyright 2012 Red Hat Inc .
* Authors : Dave Airlie < airlied @ redhat . com >
* Michael Thayer < michael . thayer @ oracle . com ,
* Hans de Goede < hdegoede @ redhat . com >
*/
2019-01-26 13:25:23 +01:00
# include <linux/module.h>
# include <linux/pci.h>
2017-07-06 16:06:01 +02:00
# include <linux/vt_kern.h>
2021-04-12 15:10:42 +02:00
# include <drm/drm_aperture.h>
2019-01-26 13:25:23 +01:00
# include <drm/drm_drv.h>
2022-11-03 16:14:44 +01:00
# include <drm/drm_fbdev_generic.h>
2019-01-26 13:25:23 +01:00
# include <drm/drm_file.h>
# include <drm/drm_ioctl.h>
2020-03-23 15:49:17 +01:00
# include <drm/drm_managed.h>
2023-01-16 14:12:34 +01:00
# include <drm/drm_modeset_helper.h>
2021-12-17 15:46:14 +01:00
# include <drm/drm_module.h>
2017-07-06 16:06:01 +02:00
# include "vbox_drv.h"
2017-07-19 10:36:16 +01:00
static int vbox_modeset = - 1 ;
2017-07-06 16:06:01 +02:00
MODULE_PARM_DESC ( modeset , " Disable/Enable modesetting " ) ;
module_param_named ( modeset , vbox_modeset , int , 0400 ) ;
2020-11-04 11:04:24 +01:00
static const struct drm_driver driver ;
2017-07-06 16:06:01 +02:00
static const struct pci_device_id pciidlist [ ] = {
2018-10-22 16:57:46 +02:00
{ PCI_DEVICE ( 0x80ee , 0xbeef ) } ,
{ }
2017-07-06 16:06:01 +02:00
} ;
MODULE_DEVICE_TABLE ( pci , pciidlist ) ;
static int vbox_pci_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox ;
2018-06-03 23:24:45 -03:00
int ret = 0 ;
2018-09-18 19:44:29 +02:00
if ( ! vbox_check_supported ( VBE_DISPI_ID_HGSMI ) )
return - ENODEV ;
2021-06-29 15:58:33 +02:00
ret = drm_aperture_remove_conflicting_pci_framebuffers ( pdev , & driver ) ;
2020-03-25 15:43:10 +01:00
if ( ret )
return ret ;
2020-04-15 09:39:38 +02:00
vbox = devm_drm_dev_alloc ( & pdev - > dev , & driver ,
struct vbox_private , ddev ) ;
if ( IS_ERR ( vbox ) )
return PTR_ERR ( vbox ) ;
2018-09-18 19:44:29 +02:00
2018-09-18 19:44:30 +02:00
pci_set_drvdata ( pdev , vbox ) ;
2018-09-18 19:44:29 +02:00
mutex_init ( & vbox - > hw_mutex ) ;
2020-04-15 09:39:40 +02:00
ret = pcim_enable_device ( pdev ) ;
2018-09-18 19:44:30 +02:00
if ( ret )
2020-04-15 09:39:38 +02:00
return ret ;
2018-09-18 19:44:30 +02:00
2018-09-18 19:44:29 +02:00
ret = vbox_hw_init ( vbox ) ;
2018-06-03 23:24:45 -03:00
if ( ret )
2020-04-15 09:39:40 +02:00
return ret ;
2018-06-03 23:24:45 -03:00
2018-09-18 19:44:29 +02:00
ret = vbox_mm_init ( vbox ) ;
2018-06-03 23:24:45 -03:00
if ( ret )
2018-09-18 19:44:29 +02:00
goto err_hw_fini ;
2018-06-03 23:24:45 -03:00
2018-09-18 19:44:30 +02:00
ret = vbox_mode_init ( vbox ) ;
2018-09-18 19:44:29 +02:00
if ( ret )
2021-09-16 20:16:01 +02:00
goto err_hw_fini ;
2018-09-18 19:44:29 +02:00
ret = vbox_irq_init ( vbox ) ;
if ( ret )
goto err_mode_fini ;
2018-09-18 19:44:30 +02:00
ret = drm_dev_register ( & vbox - > ddev , 0 ) ;
2018-09-18 19:44:29 +02:00
if ( ret )
2019-10-11 15:48:06 +02:00
goto err_irq_fini ;
2018-09-18 19:44:29 +02:00
2020-04-08 10:26:40 +02:00
drm_fbdev_generic_setup ( & vbox - > ddev , 32 ) ;
2018-09-18 19:44:29 +02:00
return 0 ;
err_irq_fini :
vbox_irq_fini ( vbox ) ;
err_mode_fini :
2018-09-18 19:44:30 +02:00
vbox_mode_fini ( vbox ) ;
2018-09-18 19:44:29 +02:00
err_hw_fini :
vbox_hw_fini ( vbox ) ;
2018-06-03 23:24:45 -03:00
return ret ;
2017-07-06 16:06:01 +02:00
}
static void vbox_pci_remove ( struct pci_dev * pdev )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox = pci_get_drvdata ( pdev ) ;
2017-07-06 16:06:01 +02:00
2018-09-18 19:44:30 +02:00
drm_dev_unregister ( & vbox - > ddev ) ;
2018-09-18 19:44:29 +02:00
vbox_irq_fini ( vbox ) ;
2018-09-18 19:44:30 +02:00
vbox_mode_fini ( vbox ) ;
2018-09-18 19:44:29 +02:00
vbox_hw_fini ( vbox ) ;
2017-07-06 16:06:01 +02:00
}
static int vbox_pm_suspend ( struct device * dev )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox = dev_get_drvdata ( dev ) ;
2020-12-01 11:35:39 +01:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2017-07-06 16:06:01 +02:00
int error ;
2018-09-29 14:18:19 +02:00
error = drm_mode_config_helper_suspend ( & vbox - > ddev ) ;
2017-07-06 16:06:01 +02:00
if ( error )
return error ;
2020-12-01 11:35:39 +01:00
pci_save_state ( pdev ) ;
pci_disable_device ( pdev ) ;
pci_set_power_state ( pdev , PCI_D3hot ) ;
2017-07-06 16:06:01 +02:00
return 0 ;
}
static int vbox_pm_resume ( struct device * dev )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox = dev_get_drvdata ( dev ) ;
2020-12-01 11:35:39 +01:00
struct pci_dev * pdev = to_pci_dev ( dev ) ;
2017-07-06 16:06:01 +02:00
2020-12-01 11:35:39 +01:00
if ( pci_enable_device ( pdev ) )
2018-09-18 19:44:31 +02:00
return - EIO ;
2018-09-29 14:18:19 +02:00
return drm_mode_config_helper_resume ( & vbox - > ddev ) ;
2017-07-06 16:06:01 +02:00
}
static int vbox_pm_freeze ( struct device * dev )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox = dev_get_drvdata ( dev ) ;
2017-07-06 16:06:01 +02:00
2018-09-29 14:18:19 +02:00
return drm_mode_config_helper_suspend ( & vbox - > ddev ) ;
2017-07-06 16:06:01 +02:00
}
static int vbox_pm_thaw ( struct device * dev )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox = dev_get_drvdata ( dev ) ;
2017-07-06 16:06:01 +02:00
2018-09-29 14:18:19 +02:00
return drm_mode_config_helper_resume ( & vbox - > ddev ) ;
2017-07-06 16:06:01 +02:00
}
static int vbox_pm_poweroff ( struct device * dev )
{
2018-09-18 19:44:30 +02:00
struct vbox_private * vbox = dev_get_drvdata ( dev ) ;
2017-07-06 16:06:01 +02:00
2018-09-29 14:18:19 +02:00
return drm_mode_config_helper_suspend ( & vbox - > ddev ) ;
2017-07-06 16:06:01 +02:00
}
static const struct dev_pm_ops vbox_pm_ops = {
. suspend = vbox_pm_suspend ,
. resume = vbox_pm_resume ,
. freeze = vbox_pm_freeze ,
. thaw = vbox_pm_thaw ,
. poweroff = vbox_pm_poweroff ,
. restore = vbox_pm_resume ,
} ;
static struct pci_driver vbox_pci_driver = {
. name = DRIVER_NAME ,
. id_table = pciidlist ,
. probe = vbox_pci_probe ,
. remove = vbox_pci_remove ,
2022-11-29 19:19:38 +00:00
. driver . pm = pm_sleep_ptr ( & vbox_pm_ops ) ,
2017-07-06 16:06:01 +02:00
} ;
2019-10-16 13:52:03 +02:00
DEFINE_DRM_GEM_FOPS ( vbox_fops ) ;
2017-07-06 16:06:01 +02:00
2020-11-04 11:04:24 +01:00
static const struct drm_driver driver = {
2017-07-06 16:06:01 +02:00
. driver_features =
2019-06-17 17:39:24 +02:00
DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC ,
2017-07-06 16:06:01 +02:00
. fops = & vbox_fops ,
. name = DRIVER_NAME ,
. desc = DRIVER_DESC ,
. date = DRIVER_DATE ,
. major = DRIVER_MAJOR ,
. minor = DRIVER_MINOR ,
. patchlevel = DRIVER_PATCHLEVEL ,
2019-05-08 10:26:28 +02:00
DRM_GEM_VRAM_DRIVER ,
2017-07-06 16:06:01 +02:00
} ;
2021-12-17 15:46:14 +01:00
drm_module_pci_driver_if_modeset ( vbox_pci_driver , vbox_modeset ) ;
2017-07-06 16:06:01 +02:00
MODULE_AUTHOR ( " Oracle Corporation " ) ;
2018-10-22 16:57:48 +02:00
MODULE_AUTHOR ( " Hans de Goede <hdegoede@redhat.com> " ) ;
2017-07-06 16:06:01 +02:00
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL and additional rights " ) ;