Home | History | Annotate | Line # | Download | only in common
      1 /*
      2  * Copyright (C) 2012-2018 Rob Clark <robclark (at) freedesktop.org>
      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 (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  *
     23  * Authors:
     24  *    Rob Clark <robclark (at) freedesktop.org>
     25  */
     26 
     27 #ifndef FREEDRENO_PM4_H_
     28 #define FREEDRENO_PM4_H_
     29 
     30 #include <stdint.h>
     31 
     32 #ifdef __cplusplus
     33 extern "C" {
     34 #endif
     35 
     36 #define CP_TYPE0_PKT 0x00000000
     37 #define CP_TYPE2_PKT 0x80000000
     38 #define CP_TYPE3_PKT 0xc0000000
     39 #define CP_TYPE4_PKT 0x40000000
     40 #define CP_TYPE7_PKT 0x70000000
     41 
     42 /*
     43  * Helpers for pm4 pkt header building/parsing:
     44  */
     45 
     46 static inline unsigned
     47 pm4_odd_parity_bit(unsigned val)
     48 {
     49    /* See: http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
     50     * note that we want odd parity so 0x6996 is inverted.
     51     */
     52    val ^= val >> 16;
     53    val ^= val >> 8;
     54    val ^= val >> 4;
     55    val &= 0xf;
     56    return (~0x6996 >> val) & 1;
     57 }
     58 
     59 static inline uint32_t
     60 pm4_pkt0_hdr(uint16_t regindx, uint16_t cnt)
     61 {
     62    return CP_TYPE0_PKT | ((cnt - 1) << 16) | (regindx & 0x7fff);
     63 }
     64 
     65 static inline uint32_t
     66 pm4_pkt3_hdr(uint8_t opcode, uint16_t cnt)
     67 {
     68    return CP_TYPE3_PKT | ((cnt - 1) << 16) | ((opcode & 0xff) << 8);
     69 }
     70 
     71 static inline uint32_t
     72 pm4_pkt4_hdr(uint16_t regindx, uint16_t cnt)
     73 {
     74    return CP_TYPE4_PKT | cnt | (pm4_odd_parity_bit(cnt) << 7) |
     75          ((regindx & 0x3ffff) << 8) |
     76          ((pm4_odd_parity_bit(regindx) << 27));
     77 }
     78 
     79 static inline uint32_t
     80 pm4_pkt7_hdr(uint8_t opcode, uint16_t cnt)
     81 {
     82    return CP_TYPE7_PKT | cnt | (pm4_odd_parity_bit(cnt) << 15) |
     83          ((opcode & 0x7f) << 16) |
     84          ((pm4_odd_parity_bit(opcode) << 23));
     85 }
     86 
     87 /*
     88  * Helpers for packet parsing:
     89  */
     90 
     91 #define pkt_is_type0(pkt)     (((pkt)&0XC0000000) == CP_TYPE0_PKT)
     92 #define type0_pkt_size(pkt)   ((((pkt) >> 16) & 0x3FFF) + 1)
     93 #define type0_pkt_offset(pkt) ((pkt)&0x7FFF)
     94 
     95 #define pkt_is_type2(pkt) ((pkt) == CP_TYPE2_PKT)
     96 
     97 #define pkt_is_type3(pkt)                                                      \
     98    ((((pkt)&0xC0000000) == CP_TYPE3_PKT) && (((pkt)&0x80FE) == 0))
     99 
    100 #define cp_type3_opcode(pkt) (((pkt) >> 8) & 0xFF)
    101 #define type3_pkt_size(pkt)  ((((pkt) >> 16) & 0x3FFF) + 1)
    102 
    103 static inline uint
    104 pm4_calc_odd_parity_bit(uint val)
    105 {
    106    return (0x9669 >> (0xf & ((val) ^ ((val) >> 4) ^ ((val) >> 8) ^
    107                              ((val) >> 12) ^ ((val) >> 16) ^ ((val) >> 20) ^
    108                              ((val) >> 24) ^ ((val) >> 28)))) &
    109           1;
    110 }
    111 
    112 #define pkt_is_type4(pkt)                                                      \
    113    ((((pkt)&0xF0000000) == CP_TYPE4_PKT) &&                                    \
    114     ((((pkt) >> 27) & 0x1) ==                                                  \
    115      pm4_calc_odd_parity_bit(type4_pkt_offset(pkt))) &&                        \
    116     ((((pkt) >> 7) & 0x1) == pm4_calc_odd_parity_bit(type4_pkt_size(pkt))))
    117 
    118 #define type4_pkt_offset(pkt) (((pkt) >> 8) & 0x7FFFF)
    119 #define type4_pkt_size(pkt)   ((pkt)&0x7F)
    120 
    121 #define pkt_is_type7(pkt)                                                      \
    122    ((((pkt)&0xF0000000) == CP_TYPE7_PKT) && (((pkt)&0x0F000000) == 0) &&       \
    123     ((((pkt) >> 23) & 0x1) ==                                                  \
    124      pm4_calc_odd_parity_bit(cp_type7_opcode(pkt))) &&                         \
    125     ((((pkt) >> 15) & 0x1) == pm4_calc_odd_parity_bit(type7_pkt_size(pkt))))
    126 
    127 #define cp_type7_opcode(pkt) (((pkt) >> 16) & 0x7F)
    128 #define type7_pkt_size(pkt)  ((pkt)&0x3FFF)
    129 
    130 #ifdef __cplusplus
    131 } /* end of extern "C" */
    132 #endif
    133 
    134 #endif /* FREEDRENO_PM4_H_ */
    135