LCOV - code coverage report
Current view: top level - dev/pci/drm/radeon - vce_v1_0.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 179 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2013 Advanced Micro Devices, Inc.
       3             :  * All Rights Reserved.
       4             :  *
       5             :  * Permission is hereby granted, free of charge, to any person obtaining a
       6             :  * copy of this software and associated documentation files (the
       7             :  * "Software"), to deal in the Software without restriction, including
       8             :  * without limitation the rights to use, copy, modify, merge, publish,
       9             :  * distribute, sub license, and/or sell copies of the Software, and to
      10             :  * permit persons to whom the Software is furnished to do so, subject to
      11             :  * the following conditions:
      12             :  *
      13             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      14             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      15             :  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
      16             :  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
      17             :  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
      18             :  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
      19             :  * USE OR OTHER DEALINGS IN THE SOFTWARE.
      20             :  *
      21             :  * The above copyright notice and this permission notice (including the
      22             :  * next paragraph) shall be included in all copies or substantial portions
      23             :  * of the Software.
      24             :  *
      25             :  * Authors: Christian König <christian.koenig@amd.com>
      26             :  */
      27             : 
      28             : #include <dev/pci/drm/drmP.h>
      29             : #include "radeon.h"
      30             : #include "radeon_asic.h"
      31             : #include "sid.h"
      32             : 
      33             : #define VCE_V1_0_FW_SIZE        (256 * 1024)
      34             : #define VCE_V1_0_STACK_SIZE     (64 * 1024)
      35             : #define VCE_V1_0_DATA_SIZE      (7808 * (RADEON_MAX_VCE_HANDLES + 1))
      36             : 
      37             : struct vce_v1_0_fw_signature
      38             : {
      39             :         int32_t off;
      40             :         uint32_t len;
      41             :         int32_t num;
      42             :         struct {
      43             :                 uint32_t chip_id;
      44             :                 uint32_t keyselect;
      45             :                 uint32_t nonce[4];
      46             :                 uint32_t sigval[4];
      47             :         } val[8];
      48             : };
      49             : 
      50             : /**
      51             :  * vce_v1_0_get_rptr - get read pointer
      52             :  *
      53             :  * @rdev: radeon_device pointer
      54             :  * @ring: radeon_ring pointer
      55             :  *
      56             :  * Returns the current hardware read pointer
      57             :  */
      58           0 : uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev,
      59             :                            struct radeon_ring *ring)
      60             : {
      61           0 :         if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
      62           0 :                 return RREG32(VCE_RB_RPTR);
      63             :         else
      64           0 :                 return RREG32(VCE_RB_RPTR2);
      65           0 : }
      66             : 
      67             : /**
      68             :  * vce_v1_0_get_wptr - get write pointer
      69             :  *
      70             :  * @rdev: radeon_device pointer
      71             :  * @ring: radeon_ring pointer
      72             :  *
      73             :  * Returns the current hardware write pointer
      74             :  */
      75           0 : uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev,
      76             :                            struct radeon_ring *ring)
      77             : {
      78           0 :         if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
      79           0 :                 return RREG32(VCE_RB_WPTR);
      80             :         else
      81           0 :                 return RREG32(VCE_RB_WPTR2);
      82           0 : }
      83             : 
      84             : /**
      85             :  * vce_v1_0_set_wptr - set write pointer
      86             :  *
      87             :  * @rdev: radeon_device pointer
      88             :  * @ring: radeon_ring pointer
      89             :  *
      90             :  * Commits the write pointer to the hardware
      91             :  */
      92           0 : void vce_v1_0_set_wptr(struct radeon_device *rdev,
      93             :                        struct radeon_ring *ring)
      94             : {
      95           0 :         if (ring->idx == TN_RING_TYPE_VCE1_INDEX)
      96           0 :                 WREG32(VCE_RB_WPTR, ring->wptr);
      97             :         else
      98           0 :                 WREG32(VCE_RB_WPTR2, ring->wptr);
      99           0 : }
     100             : 
     101           0 : void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable)
     102             : {
     103             :         u32 tmp;
     104             : 
     105           0 :         if (enable && (rdev->cg_flags & RADEON_CG_SUPPORT_VCE_MGCG)) {
     106           0 :                 tmp = RREG32(VCE_CLOCK_GATING_A);
     107           0 :                 tmp |= CGC_DYN_CLOCK_MODE;
     108           0 :                 WREG32(VCE_CLOCK_GATING_A, tmp);
     109             : 
     110           0 :                 tmp = RREG32(VCE_UENC_CLOCK_GATING);
     111           0 :                 tmp &= ~0x1ff000;
     112           0 :                 tmp |= 0xff800000;
     113           0 :                 WREG32(VCE_UENC_CLOCK_GATING, tmp);
     114             : 
     115           0 :                 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
     116           0 :                 tmp &= ~0x3ff;
     117           0 :                 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
     118           0 :         } else {
     119           0 :                 tmp = RREG32(VCE_CLOCK_GATING_A);
     120           0 :                 tmp &= ~CGC_DYN_CLOCK_MODE;
     121           0 :                 WREG32(VCE_CLOCK_GATING_A, tmp);
     122             : 
     123           0 :                 tmp = RREG32(VCE_UENC_CLOCK_GATING);
     124           0 :                 tmp |= 0x1ff000;
     125           0 :                 tmp &= ~0xff800000;
     126           0 :                 WREG32(VCE_UENC_CLOCK_GATING, tmp);
     127             : 
     128           0 :                 tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
     129           0 :                 tmp |= 0x3ff;
     130           0 :                 WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
     131             :         }
     132           0 : }
     133             : 
     134           0 : static void vce_v1_0_init_cg(struct radeon_device *rdev)
     135             : {
     136             :         u32 tmp;
     137             : 
     138           0 :         tmp = RREG32(VCE_CLOCK_GATING_A);
     139           0 :         tmp |= CGC_DYN_CLOCK_MODE;
     140           0 :         WREG32(VCE_CLOCK_GATING_A, tmp);
     141             : 
     142           0 :         tmp = RREG32(VCE_CLOCK_GATING_B);
     143           0 :         tmp |= 0x1e;
     144           0 :         tmp &= ~0xe100e1;
     145           0 :         WREG32(VCE_CLOCK_GATING_B, tmp);
     146             : 
     147           0 :         tmp = RREG32(VCE_UENC_CLOCK_GATING);
     148           0 :         tmp &= ~0xff9ff000;
     149           0 :         WREG32(VCE_UENC_CLOCK_GATING, tmp);
     150             : 
     151           0 :         tmp = RREG32(VCE_UENC_REG_CLOCK_GATING);
     152           0 :         tmp &= ~0x3ff;
     153           0 :         WREG32(VCE_UENC_REG_CLOCK_GATING, tmp);
     154           0 : }
     155             : 
     156           0 : int vce_v1_0_load_fw(struct radeon_device *rdev, uint32_t *data)
     157             : {
     158           0 :         struct vce_v1_0_fw_signature *sign = (void*)rdev->vce_fw->data;
     159             :         uint32_t chip_id;
     160             :         int i;
     161             : 
     162           0 :         switch (rdev->family) {
     163             :         case CHIP_TAHITI:
     164             :                 chip_id = 0x01000014;
     165           0 :                 break;
     166             :         case CHIP_VERDE:
     167             :                 chip_id = 0x01000015;
     168           0 :                 break;
     169             :         case CHIP_PITCAIRN:
     170             :         case CHIP_OLAND:
     171             :                 chip_id = 0x01000016;
     172           0 :                 break;
     173             :         case CHIP_ARUBA:
     174             :                 chip_id = 0x01000017;
     175           0 :                 break;
     176             :         default:
     177           0 :                 return -EINVAL;
     178             :         }
     179             : 
     180           0 :         for (i = 0; i < le32_to_cpu(sign->num); ++i) {
     181           0 :                 if (le32_to_cpu(sign->val[i].chip_id) == chip_id)
     182             :                         break;
     183             :         }
     184             : 
     185           0 :         if (i == le32_to_cpu(sign->num))
     186           0 :                 return -EINVAL;
     187             : 
     188           0 :         data += (256 - 64) / 4;
     189           0 :         data[0] = sign->val[i].nonce[0];
     190           0 :         data[1] = sign->val[i].nonce[1];
     191           0 :         data[2] = sign->val[i].nonce[2];
     192           0 :         data[3] = sign->val[i].nonce[3];
     193           0 :         data[4] = cpu_to_le32(le32_to_cpu(sign->len) + 64);
     194             : 
     195           0 :         memset(&data[5], 0, 44);
     196           0 :         memcpy(&data[16], &sign[1], rdev->vce_fw->size - sizeof(*sign));
     197             : 
     198           0 :         data += le32_to_cpu(data[4]) / 4;
     199           0 :         data[0] = sign->val[i].sigval[0];
     200           0 :         data[1] = sign->val[i].sigval[1];
     201           0 :         data[2] = sign->val[i].sigval[2];
     202           0 :         data[3] = sign->val[i].sigval[3];
     203             : 
     204           0 :         rdev->vce.keyselect = le32_to_cpu(sign->val[i].keyselect);
     205             : 
     206           0 :         return 0;
     207           0 : }
     208             : 
     209           0 : unsigned vce_v1_0_bo_size(struct radeon_device *rdev)
     210             : {
     211           0 :         WARN_ON(VCE_V1_0_FW_SIZE < rdev->vce_fw->size);
     212           0 :         return VCE_V1_0_FW_SIZE + VCE_V1_0_STACK_SIZE + VCE_V1_0_DATA_SIZE;
     213             : }
     214             : 
     215           0 : int vce_v1_0_resume(struct radeon_device *rdev)
     216             : {
     217           0 :         uint64_t addr = rdev->vce.gpu_addr;
     218             :         uint32_t size;
     219             :         int i;
     220             : 
     221           0 :         WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16));
     222           0 :         WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
     223           0 :         WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
     224           0 :         WREG32(VCE_CLOCK_GATING_B, 0);
     225             : 
     226           0 :         WREG32_P(VCE_LMI_FW_PERIODIC_CTRL, 0x4, ~0x4);
     227             : 
     228           0 :         WREG32(VCE_LMI_CTRL, 0x00398000);
     229           0 :         WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1);
     230           0 :         WREG32(VCE_LMI_SWAP_CNTL, 0);
     231           0 :         WREG32(VCE_LMI_SWAP_CNTL1, 0);
     232           0 :         WREG32(VCE_LMI_VM_CTRL, 0);
     233             : 
     234           0 :         WREG32(VCE_VCPU_SCRATCH7, RADEON_MAX_VCE_HANDLES);
     235             : 
     236           0 :         addr += 256;
     237             :         size = VCE_V1_0_FW_SIZE;
     238           0 :         WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
     239           0 :         WREG32(VCE_VCPU_CACHE_SIZE0, size);
     240             : 
     241           0 :         addr += size;
     242             :         size = VCE_V1_0_STACK_SIZE;
     243           0 :         WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
     244           0 :         WREG32(VCE_VCPU_CACHE_SIZE1, size);
     245             : 
     246           0 :         addr += size;
     247             :         size = VCE_V1_0_DATA_SIZE;
     248           0 :         WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
     249           0 :         WREG32(VCE_VCPU_CACHE_SIZE2, size);
     250             : 
     251           0 :         WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100);
     252             : 
     253           0 :         WREG32(VCE_LMI_FW_START_KEYSEL, rdev->vce.keyselect);
     254             : 
     255           0 :         for (i = 0; i < 10; ++i) {
     256           0 :                 mdelay(10);
     257           0 :                 if (RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_DONE)
     258             :                         break;
     259             :         }
     260             : 
     261           0 :         if (i == 10)
     262           0 :                 return -ETIMEDOUT;
     263             : 
     264           0 :         if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_PASS))
     265           0 :                 return -EINVAL;
     266             : 
     267           0 :         for (i = 0; i < 10; ++i) {
     268           0 :                 mdelay(10);
     269           0 :                 if (!(RREG32(VCE_FW_REG_STATUS) & VCE_FW_REG_STATUS_BUSY))
     270             :                         break;
     271             :         }
     272             : 
     273           0 :         if (i == 10)
     274           0 :                 return -ETIMEDOUT;
     275             : 
     276           0 :         vce_v1_0_init_cg(rdev);
     277             : 
     278           0 :         return 0;
     279           0 : }
     280             : 
     281             : /**
     282             :  * vce_v1_0_start - start VCE block
     283             :  *
     284             :  * @rdev: radeon_device pointer
     285             :  *
     286             :  * Setup and start the VCE block
     287             :  */
     288           0 : int vce_v1_0_start(struct radeon_device *rdev)
     289             : {
     290             :         struct radeon_ring *ring;
     291             :         int i, j, r;
     292             : 
     293             :         /* set BUSY flag */
     294           0 :         WREG32_P(VCE_STATUS, 1, ~1);
     295             : 
     296           0 :         ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
     297           0 :         WREG32(VCE_RB_RPTR, ring->wptr);
     298           0 :         WREG32(VCE_RB_WPTR, ring->wptr);
     299           0 :         WREG32(VCE_RB_BASE_LO, ring->gpu_addr);
     300           0 :         WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
     301           0 :         WREG32(VCE_RB_SIZE, ring->ring_size / 4);
     302             : 
     303           0 :         ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
     304           0 :         WREG32(VCE_RB_RPTR2, ring->wptr);
     305           0 :         WREG32(VCE_RB_WPTR2, ring->wptr);
     306           0 :         WREG32(VCE_RB_BASE_LO2, ring->gpu_addr);
     307           0 :         WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
     308           0 :         WREG32(VCE_RB_SIZE2, ring->ring_size / 4);
     309             : 
     310           0 :         WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN);
     311             : 
     312           0 :         WREG32_P(VCE_SOFT_RESET,
     313             :                  VCE_ECPU_SOFT_RESET |
     314             :                  VCE_FME_SOFT_RESET, ~(
     315             :                  VCE_ECPU_SOFT_RESET |
     316             :                  VCE_FME_SOFT_RESET));
     317             : 
     318           0 :         mdelay(100);
     319             : 
     320           0 :         WREG32_P(VCE_SOFT_RESET, 0, ~(
     321             :                  VCE_ECPU_SOFT_RESET |
     322             :                  VCE_FME_SOFT_RESET));
     323             : 
     324           0 :         for (i = 0; i < 10; ++i) {
     325             :                 uint32_t status;
     326           0 :                 for (j = 0; j < 100; ++j) {
     327           0 :                         status = RREG32(VCE_STATUS);
     328           0 :                         if (status & 2)
     329             :                                 break;
     330           0 :                         mdelay(10);
     331             :                 }
     332             :                 r = 0;
     333           0 :                 if (status & 2)
     334           0 :                         break;
     335             : 
     336           0 :                 DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
     337           0 :                 WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET);
     338           0 :                 mdelay(10);
     339           0 :                 WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET);
     340           0 :                 mdelay(10);
     341             :                 r = -1;
     342           0 :         }
     343             : 
     344             :         /* clear BUSY flag */
     345           0 :         WREG32_P(VCE_STATUS, 0, ~1);
     346             : 
     347           0 :         if (r) {
     348           0 :                 DRM_ERROR("VCE not responding, giving up!!!\n");
     349           0 :                 return r;
     350             :         }
     351             : 
     352           0 :         return 0;
     353           0 : }
     354             : 
     355           0 : int vce_v1_0_init(struct radeon_device *rdev)
     356             : {
     357             :         struct radeon_ring *ring;
     358             :         int r;
     359             : 
     360           0 :         r = vce_v1_0_start(rdev);
     361           0 :         if (r)
     362           0 :                 return r;
     363             : 
     364           0 :         ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
     365           0 :         ring->ready = true;
     366           0 :         r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring);
     367           0 :         if (r) {
     368           0 :                 ring->ready = false;
     369           0 :                 return r;
     370             :         }
     371             : 
     372           0 :         ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
     373           0 :         ring->ready = true;
     374           0 :         r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring);
     375           0 :         if (r) {
     376           0 :                 ring->ready = false;
     377           0 :                 return r;
     378             :         }
     379             : 
     380             :         DRM_INFO("VCE initialized successfully.\n");
     381             : 
     382           0 :         return 0;
     383           0 : }

Generated by: LCOV version 1.13