linux/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
<<
>>
Prefs
   1/*
   2 * Copyright 2016 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23
  24#ifndef __AMDGPU_VCN_H__
  25#define __AMDGPU_VCN_H__
  26
  27#define AMDGPU_VCN_STACK_SIZE           (128*1024)
  28#define AMDGPU_VCN_CONTEXT_SIZE         (512*1024)
  29
  30#define AMDGPU_VCN_FIRMWARE_OFFSET      256
  31#define AMDGPU_VCN_MAX_ENC_RINGS        3
  32
  33#define AMDGPU_MAX_VCN_INSTANCES        2
  34#define AMDGPU_MAX_VCN_ENC_RINGS  AMDGPU_VCN_MAX_ENC_RINGS * AMDGPU_MAX_VCN_INSTANCES
  35
  36#define AMDGPU_VCN_HARVEST_VCN0 (1 << 0)
  37#define AMDGPU_VCN_HARVEST_VCN1 (1 << 1)
  38
  39#define VCN_DEC_KMD_CMD                 0x80000000
  40#define VCN_DEC_CMD_FENCE               0x00000000
  41#define VCN_DEC_CMD_TRAP                0x00000001
  42#define VCN_DEC_CMD_WRITE_REG           0x00000004
  43#define VCN_DEC_CMD_REG_READ_COND_WAIT  0x00000006
  44#define VCN_DEC_CMD_PACKET_START        0x0000000a
  45#define VCN_DEC_CMD_PACKET_END          0x0000000b
  46
  47#define VCN_DEC_SW_CMD_NO_OP            0x00000000
  48#define VCN_DEC_SW_CMD_END              0x00000001
  49#define VCN_DEC_SW_CMD_IB               0x00000002
  50#define VCN_DEC_SW_CMD_FENCE            0x00000003
  51#define VCN_DEC_SW_CMD_TRAP             0x00000004
  52#define VCN_DEC_SW_CMD_IB_AUTO          0x00000005
  53#define VCN_DEC_SW_CMD_SEMAPHORE        0x00000006
  54#define VCN_DEC_SW_CMD_PREEMPT_FENCE    0x00000009
  55#define VCN_DEC_SW_CMD_REG_WRITE        0x0000000b
  56#define VCN_DEC_SW_CMD_REG_WAIT         0x0000000c
  57
  58#define VCN_ENC_CMD_NO_OP               0x00000000
  59#define VCN_ENC_CMD_END                 0x00000001
  60#define VCN_ENC_CMD_IB                  0x00000002
  61#define VCN_ENC_CMD_FENCE               0x00000003
  62#define VCN_ENC_CMD_TRAP                0x00000004
  63#define VCN_ENC_CMD_REG_WRITE           0x0000000b
  64#define VCN_ENC_CMD_REG_WAIT            0x0000000c
  65
  66#define VCN_VID_SOC_ADDRESS_2_0         0x1fa00
  67#define VCN1_VID_SOC_ADDRESS_3_0        0x48200
  68#define VCN_AON_SOC_ADDRESS_2_0         0x1f800
  69#define VCN1_AON_SOC_ADDRESS_3_0        0x48000
  70#define VCN_VID_IP_ADDRESS_2_0          0x0
  71#define VCN_AON_IP_ADDRESS_2_0          0x30000
  72
  73#define mmUVD_RBC_XX_IB_REG_CHECK                                       0x026b
  74#define mmUVD_RBC_XX_IB_REG_CHECK_BASE_IDX                              1
  75#define mmUVD_REG_XX_MASK                                               0x026c
  76#define mmUVD_REG_XX_MASK_BASE_IDX                                      1
  77
  78/* 1 second timeout */
  79#define VCN_IDLE_TIMEOUT        msecs_to_jiffies(1000)
  80
  81#define RREG32_SOC15_DPG_MODE_1_0(ip, inst_idx, reg, mask, sram_sel)                    \
  82        ({      WREG32_SOC15(ip, inst_idx, mmUVD_DPG_LMA_MASK, mask);                   \
  83                WREG32_SOC15(ip, inst_idx, mmUVD_DPG_LMA_CTL,                           \
  84                        UVD_DPG_LMA_CTL__MASK_EN_MASK |                                 \
  85                        ((adev->reg_offset[ip##_HWIP][inst_idx][reg##_BASE_IDX] + reg)  \
  86                        << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT) |                   \
  87                        (sram_sel << UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT));                \
  88                RREG32_SOC15(ip, inst_idx, mmUVD_DPG_LMA_DATA);                         \
  89        })
  90
  91#define WREG32_SOC15_DPG_MODE_1_0(ip, inst_idx, reg, value, mask, sram_sel)             \
  92        do {                                                                            \
  93                WREG32_SOC15(ip, inst_idx, mmUVD_DPG_LMA_DATA, value);                  \
  94                WREG32_SOC15(ip, inst_idx, mmUVD_DPG_LMA_MASK, mask);                   \
  95                WREG32_SOC15(ip, inst_idx, mmUVD_DPG_LMA_CTL,                           \
  96                        UVD_DPG_LMA_CTL__READ_WRITE_MASK |                              \
  97                        ((adev->reg_offset[ip##_HWIP][inst_idx][reg##_BASE_IDX] + reg)  \
  98                        << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT) |                   \
  99                        (sram_sel << UVD_DPG_LMA_CTL__SRAM_SEL__SHIFT));                \
 100        } while (0)
 101
 102#define SOC15_DPG_MODE_OFFSET(ip, inst_idx, reg)                                                \
 103        ({                                                                                      \
 104                uint32_t internal_reg_offset, addr;                                             \
 105                bool video_range, video1_range, aon_range, aon1_range;                          \
 106                                                                                                \
 107                addr = (adev->reg_offset[ip##_HWIP][inst_idx][reg##_BASE_IDX] + reg);           \
 108                addr <<= 2;                                                                     \
 109                video_range = ((((0xFFFFF & addr) >= (VCN_VID_SOC_ADDRESS_2_0)) &&              \
 110                                ((0xFFFFF & addr) < ((VCN_VID_SOC_ADDRESS_2_0 + 0x2600)))));    \
 111                video1_range = ((((0xFFFFF & addr) >= (VCN1_VID_SOC_ADDRESS_3_0)) &&            \
 112                                ((0xFFFFF & addr) < ((VCN1_VID_SOC_ADDRESS_3_0 + 0x2600)))));   \
 113                aon_range   = ((((0xFFFFF & addr) >= (VCN_AON_SOC_ADDRESS_2_0)) &&              \
 114                                ((0xFFFFF & addr) < ((VCN_AON_SOC_ADDRESS_2_0 + 0x600)))));     \
 115                aon1_range   = ((((0xFFFFF & addr) >= (VCN1_AON_SOC_ADDRESS_3_0)) &&            \
 116                                ((0xFFFFF & addr) < ((VCN1_AON_SOC_ADDRESS_3_0 + 0x600)))));    \
 117                if (video_range)                                                                \
 118                        internal_reg_offset = ((0xFFFFF & addr) - (VCN_VID_SOC_ADDRESS_2_0) +   \
 119                                (VCN_VID_IP_ADDRESS_2_0));                                      \
 120                else if (aon_range)                                                             \
 121                        internal_reg_offset = ((0xFFFFF & addr) - (VCN_AON_SOC_ADDRESS_2_0) +   \
 122                                (VCN_AON_IP_ADDRESS_2_0));                                      \
 123                else if (video1_range)                                                          \
 124                        internal_reg_offset = ((0xFFFFF & addr) - (VCN1_VID_SOC_ADDRESS_3_0) +  \
 125                                (VCN_VID_IP_ADDRESS_2_0));                                      \
 126                else if (aon1_range)                                                            \
 127                        internal_reg_offset = ((0xFFFFF & addr) - (VCN1_AON_SOC_ADDRESS_3_0) +  \
 128                                (VCN_AON_IP_ADDRESS_2_0));                                      \
 129                else                                                                            \
 130                        internal_reg_offset = (0xFFFFF & addr);                                 \
 131                                                                                                \
 132                internal_reg_offset >>= 2;                                                      \
 133        })
 134
 135#define RREG32_SOC15_DPG_MODE(inst_idx, offset, mask_en)                                        \
 136        ({                                                                                      \
 137                WREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_CTL,                                  \
 138                        (0x0 << UVD_DPG_LMA_CTL__READ_WRITE__SHIFT |                            \
 139                        mask_en << UVD_DPG_LMA_CTL__MASK_EN__SHIFT |                            \
 140                        offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT));                    \
 141                RREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_DATA);                                \
 142        })
 143
 144#define WREG32_SOC15_DPG_MODE(inst_idx, offset, value, mask_en, indirect)                       \
 145        do {                                                                                    \
 146                if (!indirect) {                                                                \
 147                        WREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_DATA, value);                 \
 148                        WREG32_SOC15(VCN, inst_idx, mmUVD_DPG_LMA_CTL,                          \
 149                                (0x1 << UVD_DPG_LMA_CTL__READ_WRITE__SHIFT |                    \
 150                                 mask_en << UVD_DPG_LMA_CTL__MASK_EN__SHIFT |                   \
 151                                 offset << UVD_DPG_LMA_CTL__READ_WRITE_ADDR__SHIFT));           \
 152                } else {                                                                        \
 153                        *adev->vcn.inst[inst_idx].dpg_sram_curr_addr++ = offset;                \
 154                        *adev->vcn.inst[inst_idx].dpg_sram_curr_addr++ = value;                 \
 155                }                                                                               \
 156        } while (0)
 157
 158#define AMDGPU_VCN_MULTI_QUEUE_FLAG     (1 << 8)
 159#define AMDGPU_VCN_SW_RING_FLAG         (1 << 9)
 160
 161#define AMDGPU_VCN_IB_FLAG_DECODE_BUFFER        0x00000001
 162#define AMDGPU_VCN_CMD_FLAG_MSG_BUFFER          0x00000001
 163
 164enum fw_queue_mode {
 165        FW_QUEUE_RING_RESET = 1,
 166        FW_QUEUE_DPG_HOLD_OFF = 2,
 167};
 168
 169enum engine_status_constants {
 170        UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON = 0x2AAAA0,
 171        UVD_PGFSM_STATUS__UVDM_UVDU_PWR_ON_2_0 = 0xAAAA0,
 172        UVD_PGFSM_STATUS__UVDM_UVDU_UVDLM_PWR_ON_3_0 = 0x2A2A8AA0,
 173        UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON = 0x00000002,
 174        UVD_STATUS__UVD_BUSY = 0x00000004,
 175        GB_ADDR_CONFIG_DEFAULT = 0x26010011,
 176        UVD_STATUS__IDLE = 0x2,
 177        UVD_STATUS__BUSY = 0x5,
 178        UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF = 0x1,
 179        UVD_STATUS__RBC_BUSY = 0x1,
 180        UVD_PGFSM_STATUS_UVDJ_PWR_ON = 0,
 181};
 182
 183enum internal_dpg_state {
 184        VCN_DPG_STATE__UNPAUSE = 0,
 185        VCN_DPG_STATE__PAUSE,
 186};
 187
 188struct dpg_pause_state {
 189        enum internal_dpg_state fw_based;
 190        enum internal_dpg_state jpeg;
 191};
 192
 193struct amdgpu_vcn_reg{
 194        unsigned        data0;
 195        unsigned        data1;
 196        unsigned        cmd;
 197        unsigned        nop;
 198        unsigned        context_id;
 199        unsigned        ib_vmid;
 200        unsigned        ib_bar_low;
 201        unsigned        ib_bar_high;
 202        unsigned        ib_size;
 203        unsigned        gp_scratch8;
 204        unsigned        scratch9;
 205};
 206
 207struct amdgpu_vcn_inst {
 208        struct amdgpu_bo        *vcpu_bo;
 209        void                    *cpu_addr;
 210        uint64_t                gpu_addr;
 211        void                    *saved_bo;
 212        struct amdgpu_ring      ring_dec;
 213        struct amdgpu_ring      ring_enc[AMDGPU_VCN_MAX_ENC_RINGS];
 214        struct amdgpu_irq_src   irq;
 215        struct amdgpu_vcn_reg   external;
 216        struct amdgpu_bo        *dpg_sram_bo;
 217        struct dpg_pause_state  pause_state;
 218        void                    *dpg_sram_cpu_addr;
 219        uint64_t                dpg_sram_gpu_addr;
 220        uint32_t                *dpg_sram_curr_addr;
 221        atomic_t                dpg_enc_submission_cnt;
 222        void                    *fw_shared_cpu_addr;
 223        uint64_t                fw_shared_gpu_addr;
 224};
 225
 226struct amdgpu_vcn {
 227        unsigned                fw_version;
 228        struct delayed_work     idle_work;
 229        const struct firmware   *fw;    /* VCN firmware */
 230        unsigned                num_enc_rings;
 231        enum amd_powergating_state cur_state;
 232        bool                    indirect_sram;
 233
 234        uint8_t num_vcn_inst;
 235        struct amdgpu_vcn_inst   inst[AMDGPU_MAX_VCN_INSTANCES];
 236        struct amdgpu_vcn_reg    internal;
 237        struct mutex             vcn_pg_lock;
 238        struct mutex            vcn1_jpeg1_workaround;
 239        atomic_t                 total_submission_cnt;
 240
 241        unsigned        harvest_config;
 242        int (*pause_dpg_mode)(struct amdgpu_device *adev,
 243                int inst_idx, struct dpg_pause_state *new_state);
 244};
 245
 246struct amdgpu_fw_shared_multi_queue {
 247        uint8_t decode_queue_mode;
 248        uint8_t encode_generalpurpose_queue_mode;
 249        uint8_t encode_lowlatency_queue_mode;
 250        uint8_t encode_realtime_queue_mode;
 251        uint8_t padding[4];
 252};
 253
 254struct amdgpu_fw_shared_sw_ring {
 255        uint8_t is_enabled;
 256        uint8_t padding[3];
 257};
 258
 259struct amdgpu_fw_shared {
 260        uint32_t present_flag_0;
 261        uint8_t pad[53];
 262        struct amdgpu_fw_shared_multi_queue multi_queue;
 263        struct amdgpu_fw_shared_sw_ring sw_ring;
 264} __attribute__((__packed__));
 265
 266struct amdgpu_vcn_decode_buffer {
 267        uint32_t valid_buf_flag;
 268        uint32_t msg_buffer_address_hi;
 269        uint32_t msg_buffer_address_lo;
 270        uint32_t pad[30];
 271};
 272
 273int amdgpu_vcn_sw_init(struct amdgpu_device *adev);
 274int amdgpu_vcn_sw_fini(struct amdgpu_device *adev);
 275int amdgpu_vcn_suspend(struct amdgpu_device *adev);
 276int amdgpu_vcn_resume(struct amdgpu_device *adev);
 277void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring);
 278void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring);
 279
 280int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring);
 281int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
 282int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring);
 283int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout);
 284
 285int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring);
 286int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout);
 287
 288#endif
 289