1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright 2012 Red Hat 4 * 5 * Authors: Matthew Garrett 6 * Dave Airlie 7 */ 8 9 #include <linux/module.h> 10 #include <linux/pci.h> 11 12 #include <drm/drm_aperture.h> 13 #include <drm/drm_atomic_helper.h> 14 #include <drm/drm_drv.h> 15 #include <drm/drm_fbdev_shmem.h> 16 #include <drm/drm_file.h> 17 #include <drm/drm_ioctl.h> 18 #include <drm/drm_managed.h> 19 #include <drm/drm_module.h> 20 #include <drm/drm_pciids.h> 21 #include <drm/drm_vblank.h> 22 23 #include "mgag200_drv.h" 24 25 static int mgag200_modeset = -1; 26 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); 27 module_param_named(modeset, mgag200_modeset, int, 0400); 28 29 int mgag200_init_pci_options(struct pci_dev *pdev, u32 option, u32 option2) 30 { 31 struct device *dev = &pdev->dev; 32 int err; 33 34 err = pci_write_config_dword(pdev, PCI_MGA_OPTION, option); 35 if (err != PCIBIOS_SUCCESSFUL) { 36 dev_err(dev, "pci_write_config_dword(PCI_MGA_OPTION) failed: %d\n", err); 37 return pcibios_err_to_errno(err); 38 } 39 40 err = pci_write_config_dword(pdev, PCI_MGA_OPTION2, option2); 41 if (err != PCIBIOS_SUCCESSFUL) { 42 dev_err(dev, "pci_write_config_dword(PCI_MGA_OPTION2) failed: %d\n", err); 43 return pcibios_err_to_errno(err); 44 } 45 46 return 0; 47 } 48 49 resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size) 50 { 51 int offset; 52 int orig; 53 int test1, test2; 54 int orig1, orig2; 55 size_t vram_size; 56 57 /* Probe */ 58 orig = ioread16(mem); 59 iowrite16(0, mem); 60 61 vram_size = size; 62 63 for (offset = 0x100000; offset < vram_size; offset += 0x4000) { 64 orig1 = ioread8(mem + offset); 65 orig2 = ioread8(mem + offset + 0x100); 66 67 iowrite16(0xaa55, mem + offset); 68 iowrite16(0xaa55, mem + offset + 0x100); 69 70 test1 = ioread16(mem + offset); 71 test2 = ioread16(mem); 72 73 iowrite16(orig1, mem + offset); 74 iowrite16(orig2, mem + offset + 0x100); 75 76 if (test1 != 0xaa55) 77 break; 78 79 if (test2) 80 break; 81 } 82 83 iowrite16(orig, mem); 84 85 return offset - 65536; 86 } 87 88 static irqreturn_t mgag200_irq_handler(int irq, void *arg) 89 { 90 struct drm_device *dev = arg; 91 struct mga_device *mdev = to_mga_device(dev); 92 struct drm_crtc *crtc; 93 u32 status, ien; 94 95 status = RREG32(MGAREG_STATUS); 96 97 if (status & MGAREG_STATUS_VLINEPEN) { 98 ien = RREG32(MGAREG_IEN); 99 if (!(ien & MGAREG_IEN_VLINEIEN)) 100 goto out; 101 102 crtc = drm_crtc_from_index(dev, 0); 103 if (WARN_ON_ONCE(!crtc)) 104 goto out; 105 drm_crtc_handle_vblank(crtc); 106 107 WREG32(MGAREG_ICLEAR, MGAREG_ICLEAR_VLINEICLR); 108 109 return IRQ_HANDLED; 110 } 111 112 out: 113 return IRQ_NONE; 114 } 115 116 /* 117 * DRM driver 118 */ 119 120 DEFINE_DRM_GEM_FOPS(mgag200_driver_fops); 121 122 static const struct drm_driver mgag200_driver = { 123 .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET, 124 .fops = &mgag200_driver_fops, 125 .name = DRIVER_NAME, 126 .desc = DRIVER_DESC, 127 .date = DRIVER_DATE, 128 .major = DRIVER_MAJOR, 129 .minor = DRIVER_MINOR, 130 .patchlevel = DRIVER_PATCHLEVEL, 131 DRM_GEM_SHMEM_DRIVER_OPS, 132 }; 133 134 /* 135 * DRM device 136 */ 137 138 resource_size_t mgag200_device_probe_vram(struct mga_device *mdev) 139 { 140 return mgag200_probe_vram(mdev->vram, resource_size(mdev->vram_res)); 141 } 142 143 int mgag200_device_preinit(struct mga_device *mdev) 144 { 145 struct drm_device *dev = &mdev->base; 146 struct pci_dev *pdev = to_pci_dev(dev->dev); 147 resource_size_t start, len; 148 struct resource *res; 149 150 /* BAR 1 contains registers */ 151 152 start = pci_resource_start(pdev, 1); 153 len = pci_resource_len(pdev, 1); 154 155 res = devm_request_mem_region(dev->dev, start, len, "mgadrmfb_mmio"); 156 if (!res) { 157 drm_err(dev, "devm_request_mem_region(MMIO) failed\n"); 158 return -ENXIO; 159 } 160 mdev->rmmio_res = res; 161 162 mdev->rmmio = pcim_iomap(pdev, 1, 0); 163 if (!mdev->rmmio) 164 return -ENOMEM; 165 166 /* BAR 0 is VRAM */ 167 168 start = pci_resource_start(pdev, 0); 169 len = pci_resource_len(pdev, 0); 170 171 res = devm_request_mem_region(dev->dev, start, len, "mgadrmfb_vram"); 172 if (!res) { 173 drm_err(dev, "devm_request_mem_region(VRAM) failed\n"); 174 return -ENXIO; 175 } 176 mdev->vram_res = res; 177 178 #if defined(CONFIG_DRM_MGAG200_DISABLE_WRITECOMBINE) 179 mdev->vram = devm_ioremap(dev->dev, res->start, resource_size(res)); 180 if (!mdev->vram) 181 return -ENOMEM; 182 #else 183 mdev->vram = devm_ioremap_wc(dev->dev, res->start, resource_size(res)); 184 if (!mdev->vram) 185 return -ENOMEM; 186 187 /* Don't fail on errors, but performance might be reduced. */ 188 devm_arch_phys_wc_add(dev->dev, res->start, resource_size(res)); 189 #endif 190 191 return 0; 192 } 193 194 int mgag200_device_init(struct mga_device *mdev, 195 const struct mgag200_device_info *info, 196 const struct mgag200_device_funcs *funcs) 197 { 198 struct drm_device *dev = &mdev->base; 199 struct pci_dev *pdev = to_pci_dev(dev->dev); 200 u8 crtcext3, misc; 201 int ret; 202 203 mdev->info = info; 204 mdev->funcs = funcs; 205 206 ret = drmm_mutex_init(dev, &mdev->rmmio_lock); 207 if (ret) 208 return ret; 209 210 mutex_lock(&mdev->rmmio_lock); 211 212 RREG_ECRT(0x03, crtcext3); 213 crtcext3 |= MGAREG_CRTCEXT3_MGAMODE; 214 WREG_ECRT(0x03, crtcext3); 215 216 WREG_ECRT(0x04, 0x00); 217 218 misc = RREG8(MGA_MISC_IN); 219 misc |= MGAREG_MISC_RAMMAPEN | 220 MGAREG_MISC_HIGH_PG_SEL; 221 WREG8(MGA_MISC_OUT, misc); 222 223 mutex_unlock(&mdev->rmmio_lock); 224 225 WREG32(MGAREG_IEN, 0); 226 WREG32(MGAREG_ICLEAR, MGAREG_ICLEAR_VLINEICLR); 227 228 ret = devm_request_irq(&pdev->dev, pdev->irq, mgag200_irq_handler, IRQF_SHARED, 229 dev->driver->name, dev); 230 if (ret) { 231 drm_err(dev, "Failed to acquire interrupt, error %d\n", ret); 232 return ret; 233 } 234 235 return 0; 236 } 237 238 /* 239 * PCI driver 240 */ 241 242 static const struct pci_device_id mgag200_pciidlist[] = { 243 { PCI_VENDOR_ID_MATROX, 0x520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_PCI }, 244 { PCI_VENDOR_ID_MATROX, 0x521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_AGP }, 245 { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A }, 246 { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B }, 247 { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV }, 248 { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB }, 249 { PCI_VENDOR_ID_MATROX, 0x533, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH }, 250 { PCI_VENDOR_ID_MATROX, 0x534, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_ER }, 251 { PCI_VENDOR_ID_MATROX, 0x536, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EW3 }, 252 { PCI_VENDOR_ID_MATROX, 0x538, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH3 }, 253 {0,} 254 }; 255 256 MODULE_DEVICE_TABLE(pci, mgag200_pciidlist); 257 258 static int 259 mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 260 { 261 enum mga_type type = (enum mga_type)ent->driver_data; 262 struct mga_device *mdev; 263 struct drm_device *dev; 264 int ret; 265 266 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &mgag200_driver); 267 if (ret) 268 return ret; 269 270 ret = pcim_enable_device(pdev); 271 if (ret) 272 return ret; 273 274 switch (type) { 275 case G200_PCI: 276 case G200_AGP: 277 mdev = mgag200_g200_device_create(pdev, &mgag200_driver); 278 break; 279 case G200_SE_A: 280 case G200_SE_B: 281 mdev = mgag200_g200se_device_create(pdev, &mgag200_driver, type); 282 break; 283 case G200_WB: 284 mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver); 285 break; 286 case G200_EV: 287 mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver); 288 break; 289 case G200_EH: 290 mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver); 291 break; 292 case G200_EH3: 293 mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver); 294 break; 295 case G200_ER: 296 mdev = mgag200_g200er_device_create(pdev, &mgag200_driver); 297 break; 298 case G200_EW3: 299 mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver); 300 break; 301 default: 302 dev_err(&pdev->dev, "Device type %d is unsupported\n", type); 303 return -ENODEV; 304 } 305 if (IS_ERR(mdev)) 306 return PTR_ERR(mdev); 307 dev = &mdev->base; 308 309 ret = drm_dev_register(dev, 0); 310 if (ret) 311 return ret; 312 313 /* 314 * FIXME: A 24-bit color depth does not work with 24 bpp on 315 * G200ER. Force 32 bpp. 316 */ 317 drm_fbdev_shmem_setup(dev, 32); 318 319 return 0; 320 } 321 322 static void mgag200_pci_remove(struct pci_dev *pdev) 323 { 324 struct drm_device *dev = pci_get_drvdata(pdev); 325 326 drm_dev_unregister(dev); 327 drm_atomic_helper_shutdown(dev); 328 } 329 330 static void mgag200_pci_shutdown(struct pci_dev *pdev) 331 { 332 drm_atomic_helper_shutdown(pci_get_drvdata(pdev)); 333 } 334 335 static struct pci_driver mgag200_pci_driver = { 336 .name = DRIVER_NAME, 337 .id_table = mgag200_pciidlist, 338 .probe = mgag200_pci_probe, 339 .remove = mgag200_pci_remove, 340 .shutdown = mgag200_pci_shutdown, 341 }; 342 343 drm_module_pci_driver_if_modeset(mgag200_pci_driver, mgag200_modeset); 344 345 MODULE_AUTHOR(DRIVER_AUTHOR); 346 MODULE_DESCRIPTION(DRIVER_DESC); 347 MODULE_LICENSE("GPL"); 348