1 1.2 riastrad /* $NetBSD: ast_drv.c,v 1.4 2021/12/18 23:45:27 riastradh Exp $ */ 2 1.2 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2012 Red Hat Inc. 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the 8 1.1 riastrad * "Software"), to deal in the Software without restriction, including 9 1.1 riastrad * without limitation the rights to use, copy, modify, merge, publish, 10 1.1 riastrad * distribute, sub license, and/or sell copies of the Software, and to 11 1.1 riastrad * permit persons to whom the Software is furnished to do so, subject to 12 1.1 riastrad * the following conditions: 13 1.1 riastrad * 14 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 1.1 riastrad * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 1.1 riastrad * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 1.1 riastrad * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 1.1 riastrad * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 1.1 riastrad * 22 1.1 riastrad * The above copyright notice and this permission notice (including the 23 1.1 riastrad * next paragraph) shall be included in all copies or substantial portions 24 1.1 riastrad * of the Software. 25 1.1 riastrad * 26 1.1 riastrad */ 27 1.1 riastrad /* 28 1.1 riastrad * Authors: Dave Airlie <airlied (at) redhat.com> 29 1.1 riastrad */ 30 1.4 riastrad 31 1.2 riastrad #include <sys/cdefs.h> 32 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: ast_drv.c,v 1.4 2021/12/18 23:45:27 riastradh Exp $"); 33 1.2 riastrad 34 1.4 riastrad #include <linux/console.h> 35 1.1 riastrad #include <linux/module.h> 36 1.4 riastrad #include <linux/pci.h> 37 1.1 riastrad 38 1.1 riastrad #include <drm/drm_crtc_helper.h> 39 1.4 riastrad #include <drm/drm_drv.h> 40 1.4 riastrad #include <drm/drm_gem_vram_helper.h> 41 1.4 riastrad #include <drm/drm_probe_helper.h> 42 1.1 riastrad 43 1.1 riastrad #include "ast_drv.h" 44 1.1 riastrad 45 1.1 riastrad int ast_modeset = -1; 46 1.1 riastrad 47 1.1 riastrad MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); 48 1.1 riastrad module_param_named(modeset, ast_modeset, int, 0400); 49 1.1 riastrad 50 1.1 riastrad #define PCI_VENDOR_ASPEED 0x1a03 51 1.1 riastrad 52 1.1 riastrad static struct drm_driver driver; 53 1.1 riastrad 54 1.1 riastrad #define AST_VGA_DEVICE(id, info) { \ 55 1.1 riastrad .class = PCI_BASE_CLASS_DISPLAY << 16, \ 56 1.1 riastrad .class_mask = 0xff0000, \ 57 1.1 riastrad .vendor = PCI_VENDOR_ASPEED, \ 58 1.1 riastrad .device = id, \ 59 1.1 riastrad .subvendor = PCI_ANY_ID, \ 60 1.1 riastrad .subdevice = PCI_ANY_ID, \ 61 1.1 riastrad .driver_data = (unsigned long) info } 62 1.1 riastrad 63 1.2 riastrad static const struct pci_device_id pciidlist[] = { 64 1.1 riastrad AST_VGA_DEVICE(PCI_CHIP_AST2000, NULL), 65 1.1 riastrad AST_VGA_DEVICE(PCI_CHIP_AST2100, NULL), 66 1.1 riastrad /* AST_VGA_DEVICE(PCI_CHIP_AST1180, NULL), - don't bind to 1180 for now */ 67 1.1 riastrad {0, 0, 0}, 68 1.1 riastrad }; 69 1.1 riastrad 70 1.1 riastrad MODULE_DEVICE_TABLE(pci, pciidlist); 71 1.1 riastrad 72 1.4 riastrad static void ast_kick_out_firmware_fb(struct pci_dev *pdev) 73 1.4 riastrad { 74 1.4 riastrad struct apertures_struct *ap; 75 1.4 riastrad bool primary = false; 76 1.4 riastrad 77 1.4 riastrad ap = alloc_apertures(1); 78 1.4 riastrad if (!ap) 79 1.4 riastrad return; 80 1.4 riastrad 81 1.4 riastrad ap->ranges[0].base = pci_resource_start(pdev, 0); 82 1.4 riastrad ap->ranges[0].size = pci_resource_len(pdev, 0); 83 1.4 riastrad 84 1.4 riastrad #ifdef CONFIG_X86 85 1.4 riastrad primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; 86 1.4 riastrad #endif 87 1.4 riastrad drm_fb_helper_remove_conflicting_framebuffers(ap, "astdrmfb", primary); 88 1.4 riastrad kfree(ap); 89 1.4 riastrad } 90 1.4 riastrad 91 1.1 riastrad static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 92 1.1 riastrad { 93 1.4 riastrad struct drm_device *dev; 94 1.4 riastrad int ret; 95 1.4 riastrad 96 1.4 riastrad ast_kick_out_firmware_fb(pdev); 97 1.4 riastrad 98 1.4 riastrad ret = pci_enable_device(pdev); 99 1.4 riastrad if (ret) 100 1.4 riastrad return ret; 101 1.4 riastrad 102 1.4 riastrad dev = drm_dev_alloc(&driver, &pdev->dev); 103 1.4 riastrad if (IS_ERR(dev)) { 104 1.4 riastrad ret = PTR_ERR(dev); 105 1.4 riastrad goto err_pci_disable_device; 106 1.4 riastrad } 107 1.4 riastrad 108 1.4 riastrad dev->pdev = pdev; 109 1.4 riastrad pci_set_drvdata(pdev, dev); 110 1.4 riastrad 111 1.4 riastrad ret = ast_driver_load(dev, ent->driver_data); 112 1.4 riastrad if (ret) 113 1.4 riastrad goto err_drm_dev_put; 114 1.4 riastrad 115 1.4 riastrad ret = drm_dev_register(dev, ent->driver_data); 116 1.4 riastrad if (ret) 117 1.4 riastrad goto err_ast_driver_unload; 118 1.4 riastrad 119 1.4 riastrad return 0; 120 1.4 riastrad 121 1.4 riastrad err_ast_driver_unload: 122 1.4 riastrad ast_driver_unload(dev); 123 1.4 riastrad err_drm_dev_put: 124 1.4 riastrad drm_dev_put(dev); 125 1.4 riastrad err_pci_disable_device: 126 1.4 riastrad pci_disable_device(pdev); 127 1.4 riastrad return ret; 128 1.4 riastrad 129 1.1 riastrad } 130 1.1 riastrad 131 1.1 riastrad static void 132 1.1 riastrad ast_pci_remove(struct pci_dev *pdev) 133 1.1 riastrad { 134 1.1 riastrad struct drm_device *dev = pci_get_drvdata(pdev); 135 1.1 riastrad 136 1.4 riastrad drm_dev_unregister(dev); 137 1.4 riastrad ast_driver_unload(dev); 138 1.4 riastrad drm_dev_put(dev); 139 1.1 riastrad } 140 1.1 riastrad 141 1.1 riastrad static int ast_drm_freeze(struct drm_device *dev) 142 1.1 riastrad { 143 1.4 riastrad int error; 144 1.1 riastrad 145 1.4 riastrad error = drm_mode_config_helper_suspend(dev); 146 1.4 riastrad if (error) 147 1.4 riastrad return error; 148 1.1 riastrad pci_save_state(dev->pdev); 149 1.1 riastrad return 0; 150 1.1 riastrad } 151 1.1 riastrad 152 1.1 riastrad static int ast_drm_thaw(struct drm_device *dev) 153 1.1 riastrad { 154 1.1 riastrad ast_post_gpu(dev); 155 1.1 riastrad 156 1.4 riastrad return drm_mode_config_helper_resume(dev); 157 1.1 riastrad } 158 1.1 riastrad 159 1.1 riastrad static int ast_drm_resume(struct drm_device *dev) 160 1.1 riastrad { 161 1.1 riastrad int ret; 162 1.1 riastrad 163 1.1 riastrad if (pci_enable_device(dev->pdev)) 164 1.1 riastrad return -EIO; 165 1.1 riastrad 166 1.1 riastrad ret = ast_drm_thaw(dev); 167 1.1 riastrad if (ret) 168 1.1 riastrad return ret; 169 1.1 riastrad return 0; 170 1.1 riastrad } 171 1.1 riastrad 172 1.1 riastrad static int ast_pm_suspend(struct device *dev) 173 1.1 riastrad { 174 1.1 riastrad struct pci_dev *pdev = to_pci_dev(dev); 175 1.1 riastrad struct drm_device *ddev = pci_get_drvdata(pdev); 176 1.1 riastrad int error; 177 1.1 riastrad 178 1.1 riastrad error = ast_drm_freeze(ddev); 179 1.1 riastrad if (error) 180 1.1 riastrad return error; 181 1.1 riastrad 182 1.1 riastrad pci_disable_device(pdev); 183 1.1 riastrad pci_set_power_state(pdev, PCI_D3hot); 184 1.1 riastrad return 0; 185 1.1 riastrad } 186 1.4 riastrad 187 1.1 riastrad static int ast_pm_resume(struct device *dev) 188 1.1 riastrad { 189 1.1 riastrad struct pci_dev *pdev = to_pci_dev(dev); 190 1.1 riastrad struct drm_device *ddev = pci_get_drvdata(pdev); 191 1.1 riastrad return ast_drm_resume(ddev); 192 1.1 riastrad } 193 1.1 riastrad 194 1.1 riastrad static int ast_pm_freeze(struct device *dev) 195 1.1 riastrad { 196 1.1 riastrad struct pci_dev *pdev = to_pci_dev(dev); 197 1.1 riastrad struct drm_device *ddev = pci_get_drvdata(pdev); 198 1.1 riastrad 199 1.1 riastrad if (!ddev || !ddev->dev_private) 200 1.1 riastrad return -ENODEV; 201 1.1 riastrad return ast_drm_freeze(ddev); 202 1.1 riastrad } 203 1.1 riastrad 204 1.1 riastrad static int ast_pm_thaw(struct device *dev) 205 1.1 riastrad { 206 1.1 riastrad struct pci_dev *pdev = to_pci_dev(dev); 207 1.1 riastrad struct drm_device *ddev = pci_get_drvdata(pdev); 208 1.1 riastrad return ast_drm_thaw(ddev); 209 1.1 riastrad } 210 1.1 riastrad 211 1.1 riastrad static int ast_pm_poweroff(struct device *dev) 212 1.1 riastrad { 213 1.1 riastrad struct pci_dev *pdev = to_pci_dev(dev); 214 1.1 riastrad struct drm_device *ddev = pci_get_drvdata(pdev); 215 1.1 riastrad 216 1.1 riastrad return ast_drm_freeze(ddev); 217 1.1 riastrad } 218 1.1 riastrad 219 1.1 riastrad static const struct dev_pm_ops ast_pm_ops = { 220 1.1 riastrad .suspend = ast_pm_suspend, 221 1.1 riastrad .resume = ast_pm_resume, 222 1.1 riastrad .freeze = ast_pm_freeze, 223 1.1 riastrad .thaw = ast_pm_thaw, 224 1.1 riastrad .poweroff = ast_pm_poweroff, 225 1.1 riastrad .restore = ast_pm_resume, 226 1.1 riastrad }; 227 1.1 riastrad 228 1.1 riastrad static struct pci_driver ast_pci_driver = { 229 1.1 riastrad .name = DRIVER_NAME, 230 1.1 riastrad .id_table = pciidlist, 231 1.1 riastrad .probe = ast_pci_probe, 232 1.1 riastrad .remove = ast_pci_remove, 233 1.1 riastrad .driver.pm = &ast_pm_ops, 234 1.1 riastrad }; 235 1.1 riastrad 236 1.4 riastrad DEFINE_DRM_GEM_FOPS(ast_fops); 237 1.1 riastrad 238 1.1 riastrad static struct drm_driver driver = { 239 1.4 riastrad .driver_features = DRIVER_ATOMIC | 240 1.4 riastrad DRIVER_GEM | 241 1.4 riastrad DRIVER_MODESET, 242 1.1 riastrad 243 1.1 riastrad .fops = &ast_fops, 244 1.1 riastrad .name = DRIVER_NAME, 245 1.1 riastrad .desc = DRIVER_DESC, 246 1.1 riastrad .date = DRIVER_DATE, 247 1.1 riastrad .major = DRIVER_MAJOR, 248 1.1 riastrad .minor = DRIVER_MINOR, 249 1.1 riastrad .patchlevel = DRIVER_PATCHLEVEL, 250 1.1 riastrad 251 1.4 riastrad DRM_GEM_VRAM_DRIVER 252 1.1 riastrad }; 253 1.1 riastrad 254 1.1 riastrad static int __init ast_init(void) 255 1.1 riastrad { 256 1.1 riastrad if (vgacon_text_force() && ast_modeset == -1) 257 1.1 riastrad return -EINVAL; 258 1.1 riastrad 259 1.1 riastrad if (ast_modeset == 0) 260 1.1 riastrad return -EINVAL; 261 1.4 riastrad return pci_register_driver(&ast_pci_driver); 262 1.1 riastrad } 263 1.1 riastrad static void __exit ast_exit(void) 264 1.1 riastrad { 265 1.4 riastrad pci_unregister_driver(&ast_pci_driver); 266 1.1 riastrad } 267 1.1 riastrad 268 1.1 riastrad module_init(ast_init); 269 1.1 riastrad module_exit(ast_exit); 270 1.1 riastrad 271 1.1 riastrad MODULE_AUTHOR(DRIVER_AUTHOR); 272 1.1 riastrad MODULE_DESCRIPTION(DRIVER_DESC); 273 1.1 riastrad MODULE_LICENSE("GPL and additional rights"); 274 1.1 riastrad 275