Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the
0006  * "Software"), to deal in the Software without restriction, including
0007  * without limitation the rights to use, copy, modify, merge, publish,
0008  * distribute, sub license, and/or sell copies of the Software, and to
0009  * permit persons to whom the Software is furnished to do so, subject to
0010  * the following conditions:
0011  *
0012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0013  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0014  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
0015  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
0016  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
0017  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
0018  * USE OR OTHER DEALINGS IN THE SOFTWARE.
0019  *
0020  * The above copyright notice and this permission notice (including the
0021  * next paragraph) shall be included in all copies or substantial portions
0022  * of the Software.
0023  *
0024  */
0025 /*
0026  * Authors: Dave Airlie <airlied@redhat.com>
0027  */
0028 
0029 #include <linux/module.h>
0030 #include <linux/pci.h>
0031 
0032 #include <drm/drm_aperture.h>
0033 #include <drm/drm_atomic_helper.h>
0034 #include <drm/drm_crtc_helper.h>
0035 #include <drm/drm_drv.h>
0036 #include <drm/drm_gem_vram_helper.h>
0037 #include <drm/drm_module.h>
0038 #include <drm/drm_probe_helper.h>
0039 
0040 #include "ast_drv.h"
0041 
0042 int ast_modeset = -1;
0043 
0044 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
0045 module_param_named(modeset, ast_modeset, int, 0400);
0046 
0047 /*
0048  * DRM driver
0049  */
0050 
0051 DEFINE_DRM_GEM_FOPS(ast_fops);
0052 
0053 static const struct drm_driver ast_driver = {
0054     .driver_features = DRIVER_ATOMIC |
0055                DRIVER_GEM |
0056                DRIVER_MODESET,
0057 
0058     .fops = &ast_fops,
0059     .name = DRIVER_NAME,
0060     .desc = DRIVER_DESC,
0061     .date = DRIVER_DATE,
0062     .major = DRIVER_MAJOR,
0063     .minor = DRIVER_MINOR,
0064     .patchlevel = DRIVER_PATCHLEVEL,
0065 
0066     DRM_GEM_VRAM_DRIVER
0067 };
0068 
0069 /*
0070  * PCI driver
0071  */
0072 
0073 #define PCI_VENDOR_ASPEED 0x1a03
0074 
0075 #define AST_VGA_DEVICE(id, info) {      \
0076     .class = PCI_BASE_CLASS_DISPLAY << 16,  \
0077     .class_mask = 0xff0000,         \
0078     .vendor = PCI_VENDOR_ASPEED,            \
0079     .device = id,               \
0080     .subvendor = PCI_ANY_ID,        \
0081     .subdevice = PCI_ANY_ID,        \
0082     .driver_data = (unsigned long) info }
0083 
0084 static const struct pci_device_id ast_pciidlist[] = {
0085     AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL),
0086     AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL),
0087     {0, 0, 0},
0088 };
0089 
0090 MODULE_DEVICE_TABLE(pci, ast_pciidlist);
0091 
0092 static int ast_remove_conflicting_framebuffers(struct pci_dev *pdev)
0093 {
0094     bool primary = false;
0095     resource_size_t base, size;
0096 
0097     base = pci_resource_start(pdev, 0);
0098     size = pci_resource_len(pdev, 0);
0099 #ifdef CONFIG_X86
0100     primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
0101 #endif
0102 
0103     return drm_aperture_remove_conflicting_framebuffers(base, size, primary, &ast_driver);
0104 }
0105 
0106 static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0107 {
0108     struct ast_private *ast;
0109     struct drm_device *dev;
0110     int ret;
0111 
0112     ret = ast_remove_conflicting_framebuffers(pdev);
0113     if (ret)
0114         return ret;
0115 
0116     ret = pcim_enable_device(pdev);
0117     if (ret)
0118         return ret;
0119 
0120     ast = ast_device_create(&ast_driver, pdev, ent->driver_data);
0121     if (IS_ERR(ast))
0122         return PTR_ERR(ast);
0123     dev = &ast->base;
0124 
0125     ret = drm_dev_register(dev, ent->driver_data);
0126     if (ret)
0127         return ret;
0128 
0129     drm_fbdev_generic_setup(dev, 32);
0130 
0131     return 0;
0132 }
0133 
0134 static void ast_pci_remove(struct pci_dev *pdev)
0135 {
0136     struct drm_device *dev = pci_get_drvdata(pdev);
0137 
0138     drm_dev_unregister(dev);
0139     drm_atomic_helper_shutdown(dev);
0140 }
0141 
0142 static int ast_drm_freeze(struct drm_device *dev)
0143 {
0144     int error;
0145 
0146     error = drm_mode_config_helper_suspend(dev);
0147     if (error)
0148         return error;
0149     pci_save_state(to_pci_dev(dev->dev));
0150     return 0;
0151 }
0152 
0153 static int ast_drm_thaw(struct drm_device *dev)
0154 {
0155     ast_post_gpu(dev);
0156 
0157     return drm_mode_config_helper_resume(dev);
0158 }
0159 
0160 static int ast_drm_resume(struct drm_device *dev)
0161 {
0162     if (pci_enable_device(to_pci_dev(dev->dev)))
0163         return -EIO;
0164 
0165     return ast_drm_thaw(dev);
0166 }
0167 
0168 static int ast_pm_suspend(struct device *dev)
0169 {
0170     struct pci_dev *pdev = to_pci_dev(dev);
0171     struct drm_device *ddev = pci_get_drvdata(pdev);
0172     int error;
0173 
0174     error = ast_drm_freeze(ddev);
0175     if (error)
0176         return error;
0177 
0178     pci_disable_device(pdev);
0179     pci_set_power_state(pdev, PCI_D3hot);
0180     return 0;
0181 }
0182 
0183 static int ast_pm_resume(struct device *dev)
0184 {
0185     struct pci_dev *pdev = to_pci_dev(dev);
0186     struct drm_device *ddev = pci_get_drvdata(pdev);
0187     return ast_drm_resume(ddev);
0188 }
0189 
0190 static int ast_pm_freeze(struct device *dev)
0191 {
0192     struct pci_dev *pdev = to_pci_dev(dev);
0193     struct drm_device *ddev = pci_get_drvdata(pdev);
0194     return ast_drm_freeze(ddev);
0195 }
0196 
0197 static int ast_pm_thaw(struct device *dev)
0198 {
0199     struct pci_dev *pdev = to_pci_dev(dev);
0200     struct drm_device *ddev = pci_get_drvdata(pdev);
0201     return ast_drm_thaw(ddev);
0202 }
0203 
0204 static int ast_pm_poweroff(struct device *dev)
0205 {
0206     struct pci_dev *pdev = to_pci_dev(dev);
0207     struct drm_device *ddev = pci_get_drvdata(pdev);
0208 
0209     return ast_drm_freeze(ddev);
0210 }
0211 
0212 static const struct dev_pm_ops ast_pm_ops = {
0213     .suspend = ast_pm_suspend,
0214     .resume = ast_pm_resume,
0215     .freeze = ast_pm_freeze,
0216     .thaw = ast_pm_thaw,
0217     .poweroff = ast_pm_poweroff,
0218     .restore = ast_pm_resume,
0219 };
0220 
0221 static struct pci_driver ast_pci_driver = {
0222     .name = DRIVER_NAME,
0223     .id_table = ast_pciidlist,
0224     .probe = ast_pci_probe,
0225     .remove = ast_pci_remove,
0226     .driver.pm = &ast_pm_ops,
0227 };
0228 
0229 drm_module_pci_driver_if_modeset(ast_pci_driver, ast_modeset);
0230 
0231 MODULE_AUTHOR(DRIVER_AUTHOR);
0232 MODULE_DESCRIPTION(DRIVER_DESC);
0233 MODULE_LICENSE("GPL and additional rights");