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