Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2015 Nouveau Project
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  */
0022 #include "agp.h"
0023 #ifdef __NVKM_PCI_AGP_H__
0024 #include <core/option.h>
0025 
0026 struct nvkm_device_agp_quirk {
0027     u16 hostbridge_vendor;
0028     u16 hostbridge_device;
0029     u16 chip_vendor;
0030     u16 chip_device;
0031     int mode;
0032 };
0033 
0034 static const struct nvkm_device_agp_quirk
0035 nvkm_device_agp_quirks[] = {
0036     /* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */
0037     { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
0038     /* SiS 761 does not support AGP cards, use PCI mode */
0039     { PCI_VENDOR_ID_SI, 0x0761, PCI_ANY_ID, PCI_ANY_ID, 0 },
0040     {},
0041 };
0042 
0043 void
0044 nvkm_agp_fini(struct nvkm_pci *pci)
0045 {
0046     if (pci->agp.acquired) {
0047         agp_backend_release(pci->agp.bridge);
0048         pci->agp.acquired = false;
0049     }
0050 }
0051 
0052 /* Ensure AGP controller is in a consistent state in case we need to
0053  * execute the VBIOS DEVINIT scripts.
0054  */
0055 void
0056 nvkm_agp_preinit(struct nvkm_pci *pci)
0057 {
0058     struct nvkm_device *device = pci->subdev.device;
0059     u32 mode = nvkm_pci_rd32(pci, 0x004c);
0060     u32 save[2];
0061 
0062     /* First of all, disable fast writes, otherwise if it's already
0063      * enabled in the AGP bridge and we disable the card's AGP
0064      * controller we might be locking ourselves out of it.
0065      */
0066     if ((mode | pci->agp.mode) & PCI_AGP_COMMAND_FW) {
0067         mode = pci->agp.mode & ~PCI_AGP_COMMAND_FW;
0068         agp_enable(pci->agp.bridge, mode);
0069     }
0070 
0071     /* clear busmaster bit, and disable AGP */
0072     save[0] = nvkm_pci_rd32(pci, 0x0004);
0073     nvkm_pci_wr32(pci, 0x0004, save[0] & ~0x00000004);
0074     nvkm_pci_wr32(pci, 0x004c, 0x00000000);
0075 
0076     /* reset PGRAPH, PFIFO and PTIMER */
0077     save[1] = nvkm_mask(device, 0x000200, 0x00011100, 0x00000000);
0078     nvkm_mask(device, 0x000200, 0x00011100, save[1]);
0079 
0080     /* and restore busmaster bit (gives effect of resetting AGP) */
0081     nvkm_pci_wr32(pci, 0x0004, save[0]);
0082 }
0083 
0084 int
0085 nvkm_agp_init(struct nvkm_pci *pci)
0086 {
0087     if (!agp_backend_acquire(pci->pdev)) {
0088         nvkm_error(&pci->subdev, "failed to acquire agp\n");
0089         return -ENODEV;
0090     }
0091 
0092     agp_enable(pci->agp.bridge, pci->agp.mode);
0093     pci->agp.acquired = true;
0094     return 0;
0095 }
0096 
0097 void
0098 nvkm_agp_dtor(struct nvkm_pci *pci)
0099 {
0100     arch_phys_wc_del(pci->agp.mtrr);
0101 }
0102 
0103 void
0104 nvkm_agp_ctor(struct nvkm_pci *pci)
0105 {
0106     const struct nvkm_device_agp_quirk *quirk = nvkm_device_agp_quirks;
0107     struct nvkm_subdev *subdev = &pci->subdev;
0108     struct nvkm_device *device = subdev->device;
0109     struct agp_kern_info info;
0110     int mode = -1;
0111 
0112 #ifdef __powerpc__
0113     /* Disable AGP by default on all PowerPC machines for now -- At
0114      * least some UniNorth-2 AGP bridges are known to be broken:
0115      * DMA from the host to the card works just fine, but writeback
0116      * from the card to the host goes straight to memory
0117      * untranslated bypassing that GATT somehow, making them quite
0118      * painful to deal with...
0119      */
0120     mode = 0;
0121 #endif
0122     mode = nvkm_longopt(device->cfgopt, "NvAGP", mode);
0123 
0124     /* acquire bridge temporarily, so that we can copy its info */
0125     if (!(pci->agp.bridge = agp_backend_acquire(pci->pdev))) {
0126         nvkm_warn(subdev, "failed to acquire agp\n");
0127         return;
0128     }
0129     agp_copy_info(pci->agp.bridge, &info);
0130     agp_backend_release(pci->agp.bridge);
0131 
0132     pci->agp.mode = info.mode;
0133     pci->agp.base = info.aper_base;
0134     pci->agp.size = info.aper_size * 1024 * 1024;
0135     pci->agp.cma  = info.cant_use_aperture;
0136     pci->agp.mtrr = -1;
0137 
0138     /* determine if bridge + chipset combination needs a workaround */
0139     while (quirk->hostbridge_vendor) {
0140         if (info.device->vendor == quirk->hostbridge_vendor &&
0141             info.device->device == quirk->hostbridge_device &&
0142             (quirk->chip_vendor == (u16)PCI_ANY_ID ||
0143             pci->pdev->vendor == quirk->chip_vendor) &&
0144             (quirk->chip_device == (u16)PCI_ANY_ID ||
0145             pci->pdev->device == quirk->chip_device)) {
0146             nvkm_info(subdev, "forcing default agp mode to %dX, "
0147                       "use NvAGP=<mode> to override\n",
0148                   quirk->mode);
0149             mode = quirk->mode;
0150             break;
0151         }
0152         quirk++;
0153     }
0154 
0155     /* apply quirk / user-specified mode */
0156     if (mode >= 1) {
0157         if (pci->agp.mode & 0x00000008)
0158             mode /= 4; /* AGPv3 */
0159         pci->agp.mode &= ~0x00000007;
0160         pci->agp.mode |= (mode & 0x7);
0161     } else
0162     if (mode == 0) {
0163         pci->agp.bridge = NULL;
0164         return;
0165     }
0166 
0167     /* fast writes appear to be broken on nv18, they make the card
0168      * lock up randomly.
0169      */
0170     if (device->chipset == 0x18)
0171         pci->agp.mode &= ~PCI_AGP_COMMAND_FW;
0172 
0173     pci->agp.mtrr = arch_phys_wc_add(pci->agp.base, pci->agp.size);
0174 }
0175 #endif