162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc. 362306a36Sopenharmony_ci * Copyright 2009 Jerome Glisse. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 662306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 762306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 862306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 962306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 1062306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1362306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1862306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1962306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2062306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2162306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Authors: 2462306a36Sopenharmony_ci * Dave Airlie 2562306a36Sopenharmony_ci * Jerome Glisse <glisse@freedesktop.org> 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <linux/pci.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <drm/drm_device.h> 3162306a36Sopenharmony_ci#include <drm/radeon_drm.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "radeon.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AGP) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct radeon_agpmode_quirk { 3862306a36Sopenharmony_ci u32 hostbridge_vendor; 3962306a36Sopenharmony_ci u32 hostbridge_device; 4062306a36Sopenharmony_ci u32 chip_vendor; 4162306a36Sopenharmony_ci u32 chip_device; 4262306a36Sopenharmony_ci u32 subsys_vendor; 4362306a36Sopenharmony_ci u32 subsys_device; 4462306a36Sopenharmony_ci u32 default_mode; 4562306a36Sopenharmony_ci}; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { 4862306a36Sopenharmony_ci /* Intel E7505 Memory Controller Hub / RV350 AR [Radeon 9600XT] Needs AGPMode 4 (deb #515326) */ 4962306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x2550, PCI_VENDOR_ID_ATI, 0x4152, 0x1458, 0x4038, 4}, 5062306a36Sopenharmony_ci /* Intel 82865G/PE/P DRAM Controller/Host-Hub / Mobility 9800 Needs AGPMode 4 (deb #462590) */ 5162306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x4a4e, PCI_VENDOR_ID_DELL, 0x5106, 4}, 5262306a36Sopenharmony_ci /* Intel 82865G/PE/P DRAM Controller/Host-Hub / RV280 [Radeon 9200 SE] Needs AGPMode 4 (lp #300304) */ 5362306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x5964, 5462306a36Sopenharmony_ci 0x148c, 0x2073, 4}, 5562306a36Sopenharmony_ci /* Intel 82855PM Processor to I/O Controller / Mobility M6 LY Needs AGPMode 1 (deb #467235) */ 5662306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c59, 5762306a36Sopenharmony_ci PCI_VENDOR_ID_IBM, 0x052f, 1}, 5862306a36Sopenharmony_ci /* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */ 5962306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50, 6062306a36Sopenharmony_ci PCI_VENDOR_ID_IBM, 0x0550, 1}, 6162306a36Sopenharmony_ci /* Intel 82855PM host bridge / RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] needs AGPMode 1 (Thinkpad T40p) */ 6262306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, 6362306a36Sopenharmony_ci PCI_VENDOR_ID_IBM, 0x054d, 1}, 6462306a36Sopenharmony_ci /* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */ 6562306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57, 6662306a36Sopenharmony_ci PCI_VENDOR_ID_IBM, 0x0530, 1}, 6762306a36Sopenharmony_ci /* Intel 82855PM host bridge / FireGL Mobility T2 RV350 Needs AGPMode 2 (fdo #20647) */ 6862306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e54, 6962306a36Sopenharmony_ci PCI_VENDOR_ID_IBM, 0x054f, 2}, 7062306a36Sopenharmony_ci /* Intel 82855PM host bridge / Mobility M9+ / VaioPCG-V505DX Needs AGPMode 2 (fdo #17928) */ 7162306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61, 7262306a36Sopenharmony_ci PCI_VENDOR_ID_SONY, 0x816b, 2}, 7362306a36Sopenharmony_ci /* Intel 82855PM Processor to I/O Controller / Mobility M9+ Needs AGPMode 8 (phoronix forum) */ 7462306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61, 7562306a36Sopenharmony_ci PCI_VENDOR_ID_SONY, 0x8195, 8}, 7662306a36Sopenharmony_ci /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ 7762306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, 7862306a36Sopenharmony_ci PCI_VENDOR_ID_DELL, 0x00e3, 2}, 7962306a36Sopenharmony_ci /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ 8062306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, 8162306a36Sopenharmony_ci PCI_VENDOR_ID_DELL, 0x0149, 1}, 8262306a36Sopenharmony_ci /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ 8362306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, 8462306a36Sopenharmony_ci PCI_VENDOR_ID_IBM, 0x0531, 1}, 8562306a36Sopenharmony_ci /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ 8662306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 8762306a36Sopenharmony_ci 0x1025, 0x0061, 1}, 8862306a36Sopenharmony_ci /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #203007) */ 8962306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 9062306a36Sopenharmony_ci 0x1025, 0x0064, 1}, 9162306a36Sopenharmony_ci /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #141551) */ 9262306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 9362306a36Sopenharmony_ci PCI_VENDOR_ID_ASUSTEK, 0x1942, 1}, 9462306a36Sopenharmony_ci /* Intel 82852/82855 host bridge / Mobility 9600/9700 Needs AGPMode 1 (deb #510208) */ 9562306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 9662306a36Sopenharmony_ci 0x10cf, 0x127f, 1}, 9762306a36Sopenharmony_ci /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */ 9862306a36Sopenharmony_ci { 0x1849, 0x3189, PCI_VENDOR_ID_ATI, 0x5960, 9962306a36Sopenharmony_ci 0x1787, 0x5960, 4}, 10062306a36Sopenharmony_ci /* VIA K8M800 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (fdo #12544) */ 10162306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x0204, PCI_VENDOR_ID_ATI, 0x5960, 10262306a36Sopenharmony_ci 0x17af, 0x2020, 4}, 10362306a36Sopenharmony_ci /* VIA KT880 Host Bridge / RV350 [Radeon 9550] Needs AGPMode 4 (fdo #19981) */ 10462306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x0269, PCI_VENDOR_ID_ATI, 0x4153, 10562306a36Sopenharmony_ci PCI_VENDOR_ID_ASUSTEK, 0x003c, 4}, 10662306a36Sopenharmony_ci /* VIA VT8363 Host Bridge / R200 QL [Radeon 8500] Needs AGPMode 2 (lp #141551) */ 10762306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x0305, PCI_VENDOR_ID_ATI, 0x514c, 10862306a36Sopenharmony_ci PCI_VENDOR_ID_ATI, 0x013a, 2}, 10962306a36Sopenharmony_ci /* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 (deb #515512) */ 11062306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960, 11162306a36Sopenharmony_ci PCI_VENDOR_ID_ASUSTEK, 0x004c, 2}, 11262306a36Sopenharmony_ci /* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 */ 11362306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960, 11462306a36Sopenharmony_ci PCI_VENDOR_ID_ASUSTEK, 0x0054, 2}, 11562306a36Sopenharmony_ci /* VIA VT8377 Host Bridge / R200 QM [Radeon 9100] Needs AGPMode 4 (deb #461144) */ 11662306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x514d, 11762306a36Sopenharmony_ci 0x174b, 0x7149, 4}, 11862306a36Sopenharmony_ci /* VIA VT8377 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (lp #312693) */ 11962306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5960, 12062306a36Sopenharmony_ci 0x1462, 0x0380, 4}, 12162306a36Sopenharmony_ci /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (ati ML) */ 12262306a36Sopenharmony_ci { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5964, 12362306a36Sopenharmony_ci 0x148c, 0x2073, 4}, 12462306a36Sopenharmony_ci /* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */ 12562306a36Sopenharmony_ci { PCI_VENDOR_ID_ATI, 0xcbb2, PCI_VENDOR_ID_ATI, 0x5c61, 12662306a36Sopenharmony_ci PCI_VENDOR_ID_SONY, 0x8175, 1}, 12762306a36Sopenharmony_ci { 0, 0, 0, 0, 0, 0, 0 }, 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistruct radeon_agp_head *radeon_agp_head_init(struct drm_device *dev) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev->dev); 13362306a36Sopenharmony_ci struct radeon_agp_head *head; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci head = kzalloc(sizeof(*head), GFP_KERNEL); 13662306a36Sopenharmony_ci if (!head) 13762306a36Sopenharmony_ci return NULL; 13862306a36Sopenharmony_ci head->bridge = agp_find_bridge(pdev); 13962306a36Sopenharmony_ci if (!head->bridge) { 14062306a36Sopenharmony_ci head->bridge = agp_backend_acquire(pdev); 14162306a36Sopenharmony_ci if (!head->bridge) { 14262306a36Sopenharmony_ci kfree(head); 14362306a36Sopenharmony_ci return NULL; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci agp_copy_info(head->bridge, &head->agp_info); 14662306a36Sopenharmony_ci agp_backend_release(head->bridge); 14762306a36Sopenharmony_ci } else { 14862306a36Sopenharmony_ci agp_copy_info(head->bridge, &head->agp_info); 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci if (head->agp_info.chipset == NOT_SUPPORTED) { 15162306a36Sopenharmony_ci kfree(head); 15262306a36Sopenharmony_ci return NULL; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci INIT_LIST_HEAD(&head->memory); 15562306a36Sopenharmony_ci head->cant_use_aperture = head->agp_info.cant_use_aperture; 15662306a36Sopenharmony_ci head->page_mask = head->agp_info.page_mask; 15762306a36Sopenharmony_ci head->base = head->agp_info.aper_base; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci return head; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic int radeon_agp_head_acquire(struct radeon_device *rdev) 16362306a36Sopenharmony_ci{ 16462306a36Sopenharmony_ci struct drm_device *dev = rdev->ddev; 16562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev->dev); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (!rdev->agp) 16862306a36Sopenharmony_ci return -ENODEV; 16962306a36Sopenharmony_ci if (rdev->agp->acquired) 17062306a36Sopenharmony_ci return -EBUSY; 17162306a36Sopenharmony_ci rdev->agp->bridge = agp_backend_acquire(pdev); 17262306a36Sopenharmony_ci if (!rdev->agp->bridge) 17362306a36Sopenharmony_ci return -ENODEV; 17462306a36Sopenharmony_ci rdev->agp->acquired = 1; 17562306a36Sopenharmony_ci return 0; 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic int radeon_agp_head_release(struct radeon_device *rdev) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci if (!rdev->agp || !rdev->agp->acquired) 18162306a36Sopenharmony_ci return -EINVAL; 18262306a36Sopenharmony_ci agp_backend_release(rdev->agp->bridge); 18362306a36Sopenharmony_ci rdev->agp->acquired = 0; 18462306a36Sopenharmony_ci return 0; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic int radeon_agp_head_enable(struct radeon_device *rdev, struct radeon_agp_mode mode) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci if (!rdev->agp || !rdev->agp->acquired) 19062306a36Sopenharmony_ci return -EINVAL; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci rdev->agp->mode = mode.mode; 19362306a36Sopenharmony_ci agp_enable(rdev->agp->bridge, mode.mode); 19462306a36Sopenharmony_ci rdev->agp->enabled = 1; 19562306a36Sopenharmony_ci return 0; 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic int radeon_agp_head_info(struct radeon_device *rdev, struct radeon_agp_info *info) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci struct agp_kern_info *kern; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci if (!rdev->agp || !rdev->agp->acquired) 20362306a36Sopenharmony_ci return -EINVAL; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci kern = &rdev->agp->agp_info; 20662306a36Sopenharmony_ci info->agp_version_major = kern->version.major; 20762306a36Sopenharmony_ci info->agp_version_minor = kern->version.minor; 20862306a36Sopenharmony_ci info->mode = kern->mode; 20962306a36Sopenharmony_ci info->aperture_base = kern->aper_base; 21062306a36Sopenharmony_ci info->aperture_size = kern->aper_size * 1024 * 1024; 21162306a36Sopenharmony_ci info->memory_allowed = kern->max_memory << PAGE_SHIFT; 21262306a36Sopenharmony_ci info->memory_used = kern->current_memory << PAGE_SHIFT; 21362306a36Sopenharmony_ci info->id_vendor = kern->device->vendor; 21462306a36Sopenharmony_ci info->id_device = kern->device->device; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci#endif 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ciint radeon_agp_init(struct radeon_device *rdev) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AGP) 22362306a36Sopenharmony_ci struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list; 22462306a36Sopenharmony_ci struct radeon_agp_mode mode; 22562306a36Sopenharmony_ci struct radeon_agp_info info; 22662306a36Sopenharmony_ci uint32_t agp_status; 22762306a36Sopenharmony_ci int default_mode; 22862306a36Sopenharmony_ci bool is_v3; 22962306a36Sopenharmony_ci int ret; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* Acquire AGP. */ 23262306a36Sopenharmony_ci ret = radeon_agp_head_acquire(rdev); 23362306a36Sopenharmony_ci if (ret) { 23462306a36Sopenharmony_ci DRM_ERROR("Unable to acquire AGP: %d\n", ret); 23562306a36Sopenharmony_ci return ret; 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci ret = radeon_agp_head_info(rdev, &info); 23962306a36Sopenharmony_ci if (ret) { 24062306a36Sopenharmony_ci radeon_agp_head_release(rdev); 24162306a36Sopenharmony_ci DRM_ERROR("Unable to get AGP info: %d\n", ret); 24262306a36Sopenharmony_ci return ret; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (rdev->agp->agp_info.aper_size < 32) { 24662306a36Sopenharmony_ci radeon_agp_head_release(rdev); 24762306a36Sopenharmony_ci dev_warn(rdev->dev, "AGP aperture too small (%zuM) " 24862306a36Sopenharmony_ci "need at least 32M, disabling AGP\n", 24962306a36Sopenharmony_ci rdev->agp->agp_info.aper_size); 25062306a36Sopenharmony_ci return -EINVAL; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci mode.mode = info.mode; 25462306a36Sopenharmony_ci /* chips with the agp to pcie bridge don't have the AGP_STATUS register 25562306a36Sopenharmony_ci * Just use the whatever mode the host sets up. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if (rdev->family <= CHIP_RV350) 25862306a36Sopenharmony_ci agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode; 25962306a36Sopenharmony_ci else 26062306a36Sopenharmony_ci agp_status = mode.mode; 26162306a36Sopenharmony_ci is_v3 = !!(agp_status & RADEON_AGPv3_MODE); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (is_v3) { 26462306a36Sopenharmony_ci default_mode = (agp_status & RADEON_AGPv3_8X_MODE) ? 8 : 4; 26562306a36Sopenharmony_ci } else { 26662306a36Sopenharmony_ci if (agp_status & RADEON_AGP_4X_MODE) { 26762306a36Sopenharmony_ci default_mode = 4; 26862306a36Sopenharmony_ci } else if (agp_status & RADEON_AGP_2X_MODE) { 26962306a36Sopenharmony_ci default_mode = 2; 27062306a36Sopenharmony_ci } else { 27162306a36Sopenharmony_ci default_mode = 1; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* Apply AGPMode Quirks */ 27662306a36Sopenharmony_ci while (p && p->chip_device != 0) { 27762306a36Sopenharmony_ci if (info.id_vendor == p->hostbridge_vendor && 27862306a36Sopenharmony_ci info.id_device == p->hostbridge_device && 27962306a36Sopenharmony_ci rdev->pdev->vendor == p->chip_vendor && 28062306a36Sopenharmony_ci rdev->pdev->device == p->chip_device && 28162306a36Sopenharmony_ci rdev->pdev->subsystem_vendor == p->subsys_vendor && 28262306a36Sopenharmony_ci rdev->pdev->subsystem_device == p->subsys_device) { 28362306a36Sopenharmony_ci default_mode = p->default_mode; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci ++p; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (radeon_agpmode > 0) { 28962306a36Sopenharmony_ci if ((radeon_agpmode < (is_v3 ? 4 : 1)) || 29062306a36Sopenharmony_ci (radeon_agpmode > (is_v3 ? 8 : 4)) || 29162306a36Sopenharmony_ci (radeon_agpmode & (radeon_agpmode - 1))) { 29262306a36Sopenharmony_ci DRM_ERROR("Illegal AGP Mode: %d (valid %s), leaving at %d\n", 29362306a36Sopenharmony_ci radeon_agpmode, is_v3 ? "4, 8" : "1, 2, 4", 29462306a36Sopenharmony_ci default_mode); 29562306a36Sopenharmony_ci radeon_agpmode = default_mode; 29662306a36Sopenharmony_ci } else { 29762306a36Sopenharmony_ci DRM_INFO("AGP mode requested: %d\n", radeon_agpmode); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci } else { 30062306a36Sopenharmony_ci radeon_agpmode = default_mode; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci mode.mode &= ~RADEON_AGP_MODE_MASK; 30462306a36Sopenharmony_ci if (is_v3) { 30562306a36Sopenharmony_ci switch (radeon_agpmode) { 30662306a36Sopenharmony_ci case 8: 30762306a36Sopenharmony_ci mode.mode |= RADEON_AGPv3_8X_MODE; 30862306a36Sopenharmony_ci break; 30962306a36Sopenharmony_ci case 4: 31062306a36Sopenharmony_ci default: 31162306a36Sopenharmony_ci mode.mode |= RADEON_AGPv3_4X_MODE; 31262306a36Sopenharmony_ci break; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci } else { 31562306a36Sopenharmony_ci switch (radeon_agpmode) { 31662306a36Sopenharmony_ci case 4: 31762306a36Sopenharmony_ci mode.mode |= RADEON_AGP_4X_MODE; 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci case 2: 32062306a36Sopenharmony_ci mode.mode |= RADEON_AGP_2X_MODE; 32162306a36Sopenharmony_ci break; 32262306a36Sopenharmony_ci case 1: 32362306a36Sopenharmony_ci default: 32462306a36Sopenharmony_ci mode.mode |= RADEON_AGP_1X_MODE; 32562306a36Sopenharmony_ci break; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci mode.mode &= ~RADEON_AGP_FW_MODE; /* disable fw */ 33062306a36Sopenharmony_ci ret = radeon_agp_head_enable(rdev, mode); 33162306a36Sopenharmony_ci if (ret) { 33262306a36Sopenharmony_ci DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); 33362306a36Sopenharmony_ci radeon_agp_head_release(rdev); 33462306a36Sopenharmony_ci return ret; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci rdev->mc.agp_base = rdev->agp->agp_info.aper_base; 33862306a36Sopenharmony_ci rdev->mc.gtt_size = rdev->agp->agp_info.aper_size << 20; 33962306a36Sopenharmony_ci rdev->mc.gtt_start = rdev->mc.agp_base; 34062306a36Sopenharmony_ci rdev->mc.gtt_end = rdev->mc.gtt_start + rdev->mc.gtt_size - 1; 34162306a36Sopenharmony_ci dev_info(rdev->dev, "GTT: %lluM 0x%08llX - 0x%08llX\n", 34262306a36Sopenharmony_ci rdev->mc.gtt_size >> 20, rdev->mc.gtt_start, rdev->mc.gtt_end); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* workaround some hw issues */ 34562306a36Sopenharmony_ci if (rdev->family < CHIP_R200) { 34662306a36Sopenharmony_ci WREG32(RADEON_AGP_CNTL, RREG32(RADEON_AGP_CNTL) | 0x000e0000); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci return 0; 34962306a36Sopenharmony_ci#else 35062306a36Sopenharmony_ci return 0; 35162306a36Sopenharmony_ci#endif 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_civoid radeon_agp_resume(struct radeon_device *rdev) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AGP) 35762306a36Sopenharmony_ci int r; 35862306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 35962306a36Sopenharmony_ci r = radeon_agp_init(rdev); 36062306a36Sopenharmony_ci if (r) 36162306a36Sopenharmony_ci dev_warn(rdev->dev, "radeon AGP reinit failed\n"); 36262306a36Sopenharmony_ci } 36362306a36Sopenharmony_ci#endif 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_civoid radeon_agp_fini(struct radeon_device *rdev) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_AGP) 36962306a36Sopenharmony_ci if (rdev->agp && rdev->agp->acquired) { 37062306a36Sopenharmony_ci radeon_agp_head_release(rdev); 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci#endif 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_civoid radeon_agp_suspend(struct radeon_device *rdev) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci radeon_agp_fini(rdev); 37862306a36Sopenharmony_ci} 379