Subversion Repositories Kolibri OS

Rev

Rev 1129 | Rev 1221 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2008 Advanced Micro Devices, Inc.
  3.  * Copyright 2008 Red Hat Inc.
  4.  * Copyright 2009 Jerome Glisse.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included in
  14.  * all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors: Dave Airlie
  25.  *          Alex Deucher
  26.  *          Jerome Glisse
  27.  */
  28. #include "drmP.h"
  29. #include "radeon_reg.h"
  30. #include "radeon.h"
  31. #include "avivod.h"
  32.  
  33. #include "rs600_reg_safe.h"
  34.  
  35. /* rs600 depends on : */
  36. void r100_hdp_reset(struct radeon_device *rdev);
  37. int r100_gui_wait_for_idle(struct radeon_device *rdev);
  38. int r300_mc_wait_for_idle(struct radeon_device *rdev);
  39. void r420_pipes_init(struct radeon_device *rdev);
  40.  
  41. /* This files gather functions specifics to :
  42.  * rs600
  43.  *
  44.  * Some of these functions might be used by newer ASICs.
  45.  */
  46. void rs600_gpu_init(struct radeon_device *rdev);
  47. int rs600_mc_wait_for_idle(struct radeon_device *rdev);
  48. void rs600_disable_vga(struct radeon_device *rdev);
  49.  
  50.  
  51. /*
  52.  * GART.
  53.  */
  54. void rs600_gart_tlb_flush(struct radeon_device *rdev)
  55. {
  56.         uint32_t tmp;
  57.  
  58.         tmp = RREG32_MC(RS600_MC_PT0_CNTL);
  59.         tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
  60.         WREG32_MC(RS600_MC_PT0_CNTL, tmp);
  61.  
  62.         tmp = RREG32_MC(RS600_MC_PT0_CNTL);
  63.         tmp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE;
  64.         WREG32_MC(RS600_MC_PT0_CNTL, tmp);
  65.  
  66.         tmp = RREG32_MC(RS600_MC_PT0_CNTL);
  67.         tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE);
  68.         WREG32_MC(RS600_MC_PT0_CNTL, tmp);
  69.         tmp = RREG32_MC(RS600_MC_PT0_CNTL);
  70. }
  71.  
  72. int rs600_gart_enable(struct radeon_device *rdev)
  73. {
  74.         uint32_t tmp;
  75.         int i;
  76.         int r;
  77.  
  78.         /* Initialize common gart structure */
  79.         r = radeon_gart_init(rdev);
  80.         if (r) {
  81.                 return r;
  82.         }
  83.         rdev->gart.table_size = rdev->gart.num_gpu_pages * 8;
  84.         r = radeon_gart_table_vram_alloc(rdev);
  85.         if (r) {
  86.                 return r;
  87.         }
  88.         /* FIXME: setup default page */
  89.         WREG32_MC(RS600_MC_PT0_CNTL,
  90.                  (RS600_EFFECTIVE_L2_CACHE_SIZE(6) |
  91.                   RS600_EFFECTIVE_L2_QUEUE_SIZE(6)));
  92.         for (i = 0; i < 19; i++) {
  93.                 WREG32_MC(RS600_MC_PT0_CLIENT0_CNTL + i,
  94.                          (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE |
  95.                           RS600_SYSTEM_ACCESS_MODE_IN_SYS |
  96.                           RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE |
  97.                           RS600_EFFECTIVE_L1_CACHE_SIZE(3) |
  98.                           RS600_ENABLE_FRAGMENT_PROCESSING |
  99.                           RS600_EFFECTIVE_L1_QUEUE_SIZE(3)));
  100.         }
  101.  
  102.         /* System context map to GART space */
  103.         WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_location);
  104.         tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
  105.         WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, tmp);
  106.  
  107.         /* enable first context */
  108.         WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_location);
  109.         tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
  110.         WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, tmp);
  111.         WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL,
  112.                  (RS600_ENABLE_PAGE_TABLE | RS600_PAGE_TABLE_TYPE_FLAT));
  113.         /* disable all other contexts */
  114.         for (i = 1; i < 8; i++) {
  115.                 WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL + i, 0);
  116.         }
  117.  
  118.         /* setup the page table */
  119.         WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
  120.                  rdev->gart.table_addr);
  121.         WREG32_MC(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
  122.  
  123.         /* enable page tables */
  124.         tmp = RREG32_MC(RS600_MC_PT0_CNTL);
  125.         WREG32_MC(RS600_MC_PT0_CNTL, (tmp | RS600_ENABLE_PT));
  126.         tmp = RREG32_MC(RS600_MC_CNTL1);
  127.         WREG32_MC(RS600_MC_CNTL1, (tmp | RS600_ENABLE_PAGE_TABLES));
  128.         rs600_gart_tlb_flush(rdev);
  129.         rdev->gart.ready = true;
  130.         return 0;
  131. }
  132.  
  133. void rs600_gart_disable(struct radeon_device *rdev)
  134. {
  135.         uint32_t tmp;
  136.  
  137.         /* FIXME: disable out of gart access */
  138.         WREG32_MC(RS600_MC_PT0_CNTL, 0);
  139.         tmp = RREG32_MC(RS600_MC_CNTL1);
  140.         tmp &= ~RS600_ENABLE_PAGE_TABLES;
  141.         WREG32_MC(RS600_MC_CNTL1, tmp);
  142. //   radeon_object_kunmap(rdev->gart.table.vram.robj);
  143. //   radeon_object_unpin(rdev->gart.table.vram.robj);
  144. }
  145.  
  146. #define R600_PTE_VALID     (1 << 0)
  147. #define R600_PTE_SYSTEM    (1 << 1)
  148. #define R600_PTE_SNOOPED   (1 << 2)
  149. #define R600_PTE_READABLE  (1 << 5)
  150. #define R600_PTE_WRITEABLE (1 << 6)
  151.  
  152. int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
  153. {
  154.         void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
  155.  
  156.         if (i < 0 || i > rdev->gart.num_gpu_pages) {
  157.                 return -EINVAL;
  158.         }
  159.         addr = addr & 0xFFFFFFFFFFFFF000ULL;
  160.         addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
  161.         addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
  162.         writeq(addr, ((void __iomem *)ptr) + (i * 8));
  163.         return 0;
  164. }
  165.  
  166.  
  167. /*
  168.  * MC.
  169.  */
  170. void rs600_mc_disable_clients(struct radeon_device *rdev)
  171. {
  172.         unsigned tmp;
  173.  
  174.         if (r100_gui_wait_for_idle(rdev)) {
  175.                 printk(KERN_WARNING "Failed to wait GUI idle while "
  176.                        "programming pipes. Bad things might happen.\n");
  177.         }
  178.  
  179.         tmp = RREG32(AVIVO_D1VGA_CONTROL);
  180.         WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
  181.         tmp = RREG32(AVIVO_D2VGA_CONTROL);
  182.         WREG32(AVIVO_D2VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE);
  183.  
  184.         tmp = RREG32(AVIVO_D1CRTC_CONTROL);
  185.         WREG32(AVIVO_D1CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN);
  186.         tmp = RREG32(AVIVO_D2CRTC_CONTROL);
  187.         WREG32(AVIVO_D2CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN);
  188.  
  189.         /* make sure all previous write got through */
  190.         tmp = RREG32(AVIVO_D2CRTC_CONTROL);
  191.  
  192.         mdelay(1);
  193. }
  194.  
  195. int rs600_mc_init(struct radeon_device *rdev)
  196. {
  197.         uint32_t tmp;
  198.         int r;
  199.  
  200.         if (r100_debugfs_rbbm_init(rdev)) {
  201.                 DRM_ERROR("Failed to register debugfs file for RBBM !\n");
  202.         }
  203.  
  204.         rs600_gpu_init(rdev);
  205.         rs600_gart_disable(rdev);
  206.  
  207.         /* Setup GPU memory space */
  208.         rdev->mc.vram_location = 0xFFFFFFFFUL;
  209.         rdev->mc.gtt_location = 0xFFFFFFFFUL;
  210.         r = radeon_mc_setup(rdev);
  211.         if (r) {
  212.                 return r;
  213.         }
  214.  
  215.         /* Program GPU memory space */
  216.         /* Enable bus master */
  217.         tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
  218.         WREG32(RADEON_BUS_CNTL, tmp);
  219.         /* FIXME: What does AGP means for such chipset ? */
  220.         WREG32_MC(RS600_MC_AGP_LOCATION, 0x0FFFFFFF);
  221.         /* FIXME: are this AGP reg in indirect MC range ? */
  222.         WREG32_MC(RS600_MC_AGP_BASE, 0);
  223.         WREG32_MC(RS600_MC_AGP_BASE_2, 0);
  224.         rs600_mc_disable_clients(rdev);
  225.         if (rs600_mc_wait_for_idle(rdev)) {
  226.                 printk(KERN_WARNING "Failed to wait MC idle while "
  227.                        "programming pipes. Bad things might happen.\n");
  228.         }
  229.         tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
  230.         tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
  231.         tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
  232.         WREG32_MC(RS600_MC_FB_LOCATION, tmp);
  233.         WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
  234.         return 0;
  235. }
  236.  
  237. void rs600_mc_fini(struct radeon_device *rdev)
  238. {
  239.         rs600_gart_disable(rdev);
  240.         radeon_gart_table_vram_free(rdev);
  241.         radeon_gart_fini(rdev);
  242. }
  243.  
  244.  
  245. /*
  246.  * Global GPU functions
  247.  */
  248. void rs600_disable_vga(struct radeon_device *rdev)
  249. {
  250.         unsigned tmp;
  251.  
  252.         WREG32(0x330, 0);
  253.         WREG32(0x338, 0);
  254.         tmp = RREG32(0x300);
  255.         tmp &= ~(3 << 16);
  256.         WREG32(0x300, tmp);
  257.         WREG32(0x308, (1 << 8));
  258.         WREG32(0x310, rdev->mc.vram_location);
  259.         WREG32(0x594, 0);
  260. }
  261.  
  262. int rs600_mc_wait_for_idle(struct radeon_device *rdev)
  263. {
  264.         unsigned i;
  265.         uint32_t tmp;
  266.  
  267.         for (i = 0; i < rdev->usec_timeout; i++) {
  268.                 /* read MC_STATUS */
  269.                 tmp = RREG32_MC(RS600_MC_STATUS);
  270.                 if (tmp & RS600_MC_STATUS_IDLE) {
  271.                         return 0;
  272.                 }
  273.                 DRM_UDELAY(1);
  274.         }
  275.         return -1;
  276. }
  277.  
  278. void rs600_errata(struct radeon_device *rdev)
  279. {
  280.         rdev->pll_errata = 0;
  281. }
  282.  
  283. void rs600_gpu_init(struct radeon_device *rdev)
  284. {
  285.         /* FIXME: HDP same place on rs600 ? */
  286.         r100_hdp_reset(rdev);
  287.         rs600_disable_vga(rdev);
  288.         /* FIXME: is this correct ? */
  289.         r420_pipes_init(rdev);
  290.         if (rs600_mc_wait_for_idle(rdev)) {
  291.                 printk(KERN_WARNING "Failed to wait MC idle while "
  292.                        "programming pipes. Bad things might happen.\n");
  293.         }
  294. }
  295.  
  296.  
  297. /*
  298.  * VRAM info.
  299.  */
  300. void rs600_vram_info(struct radeon_device *rdev)
  301. {
  302.         /* FIXME: to do or is these values sane ? */
  303.         rdev->mc.vram_is_ddr = true;
  304.         rdev->mc.vram_width = 128;
  305. }
  306.  
  307. void rs600_bandwidth_update(struct radeon_device *rdev)
  308. {
  309.         /* FIXME: implement, should this be like rs690 ? */
  310. }
  311.  
  312.  
  313. /*
  314.  * Indirect registers accessor
  315.  */
  316. uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg)
  317. {
  318.         uint32_t r;
  319.  
  320.         WREG32(RS600_MC_INDEX,
  321.                ((reg & RS600_MC_ADDR_MASK) | RS600_MC_IND_CITF_ARB0));
  322.         r = RREG32(RS600_MC_DATA);
  323.         return r;
  324. }
  325.  
  326. void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
  327. {
  328.         WREG32(RS600_MC_INDEX,
  329.                 RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 |
  330.                 ((reg) & RS600_MC_ADDR_MASK));
  331.         WREG32(RS600_MC_DATA, v);
  332. }
  333.