1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Hantro VPU HEVC codec driver 4 * 5 * Copyright (C) 2020 Safran Passenger Innovations LLC 6 */ 7 8 #include <linux/types.h> 9 #include <media/v4l2-mem2mem.h> 10 11 #include "hantro.h" 12 #include "hantro_hw.h" 13 14 #define VERT_FILTER_RAM_SIZE 8 /* bytes per pixel row */ 15 /* 16 * BSD control data of current picture at tile border 17 * 128 bits per 4x4 tile = 128/(8*4) bytes per row 18 */ 19 #define BSD_CTRL_RAM_SIZE 4 /* bytes per pixel row */ 20 /* tile border coefficients of filter */ 21 #define VERT_SAO_RAM_SIZE 48 /* bytes per pixel */ 22 23 #define SCALING_LIST_SIZE (16 * 64) 24 25 #define MAX_TILE_COLS 20 26 #define MAX_TILE_ROWS 22 27 28 void hantro_hevc_ref_init(struct hantro_ctx *ctx) 29 { 30 struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; 31 32 hevc_dec->ref_bufs_used = 0; 33 } 34 35 dma_addr_t hantro_hevc_get_ref_buf(struct hantro_ctx *ctx, 36 s32 poc) 37 { 38 struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; 39 int i; 40 41 /* Find the reference buffer in already known ones */ 42 for (i = 0; i < NUM_REF_PICTURES; i++) { 43 if (hevc_dec->ref_bufs_poc[i] == poc) { 44 hevc_dec->ref_bufs_used |= 1 << i; 45 return hevc_dec->ref_bufs[i].dma; 46 } 47 } 48 49 return 0; 50 } 51 52 int hantro_hevc_add_ref_buf(struct hantro_ctx *ctx, int poc, dma_addr_t addr) 53 { 54 struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; 55 int i; 56 57 /* Add a new reference buffer */ 58 for (i = 0; i < NUM_REF_PICTURES; i++) { 59 if (!(hevc_dec->ref_bufs_used & 1 << i)) { 60 hevc_dec->ref_bufs_used |= 1 << i; 61 hevc_dec->ref_bufs_poc[i] = poc; 62 hevc_dec->ref_bufs[i].dma = addr; 63 return 0; 64 } 65 } 66 67 return -EINVAL; 68 } 69 70 static int tile_buffer_reallocate(struct hantro_ctx *ctx) 71 { 72 struct hantro_dev *vpu = ctx->dev; 73 struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; 74 const struct hantro_hevc_dec_ctrls *ctrls = &ctx->hevc_dec.ctrls; 75 const struct v4l2_ctrl_hevc_pps *pps = ctrls->pps; 76 const struct v4l2_ctrl_hevc_sps *sps = ctrls->sps; 77 unsigned int num_tile_cols = pps->num_tile_columns_minus1 + 1; 78 unsigned int height64 = (sps->pic_height_in_luma_samples + 63) & ~63; 79 unsigned int size; 80 81 if (num_tile_cols <= 1 || 82 num_tile_cols <= hevc_dec->num_tile_cols_allocated) 83 return 0; 84 85 /* Need to reallocate due to tiles passed via PPS */ 86 if (hevc_dec->tile_filter.cpu) { 87 dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, 88 hevc_dec->tile_filter.cpu, 89 hevc_dec->tile_filter.dma); 90 hevc_dec->tile_filter.cpu = NULL; 91 } 92 93 if (hevc_dec->tile_sao.cpu) { 94 dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size, 95 hevc_dec->tile_sao.cpu, 96 hevc_dec->tile_sao.dma); 97 hevc_dec->tile_sao.cpu = NULL; 98 } 99 100 if (hevc_dec->tile_bsd.cpu) { 101 dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size, 102 hevc_dec->tile_bsd.cpu, 103 hevc_dec->tile_bsd.dma); 104 hevc_dec->tile_bsd.cpu = NULL; 105 } 106 107 size = (VERT_FILTER_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8; 108 hevc_dec->tile_filter.cpu = dma_alloc_coherent(vpu->dev, size, 109 &hevc_dec->tile_filter.dma, 110 GFP_KERNEL); 111 if (!hevc_dec->tile_filter.cpu) 112 return -ENOMEM; 113 hevc_dec->tile_filter.size = size; 114 115 size = (VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8; 116 hevc_dec->tile_sao.cpu = dma_alloc_coherent(vpu->dev, size, 117 &hevc_dec->tile_sao.dma, 118 GFP_KERNEL); 119 if (!hevc_dec->tile_sao.cpu) 120 goto err_free_tile_buffers; 121 hevc_dec->tile_sao.size = size; 122 123 size = BSD_CTRL_RAM_SIZE * height64 * (num_tile_cols - 1); 124 hevc_dec->tile_bsd.cpu = dma_alloc_coherent(vpu->dev, size, 125 &hevc_dec->tile_bsd.dma, 126 GFP_KERNEL); 127 if (!hevc_dec->tile_bsd.cpu) 128 goto err_free_sao_buffers; 129 hevc_dec->tile_bsd.size = size; 130 131 hevc_dec->num_tile_cols_allocated = num_tile_cols; 132 133 return 0; 134 135 err_free_sao_buffers: 136 if (hevc_dec->tile_sao.cpu) 137 dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size, 138 hevc_dec->tile_sao.cpu, 139 hevc_dec->tile_sao.dma); 140 hevc_dec->tile_sao.cpu = NULL; 141 142 err_free_tile_buffers: 143 if (hevc_dec->tile_filter.cpu) 144 dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, 145 hevc_dec->tile_filter.cpu, 146 hevc_dec->tile_filter.dma); 147 hevc_dec->tile_filter.cpu = NULL; 148 149 return -ENOMEM; 150 } 151 152 static int hantro_hevc_validate_sps(struct hantro_ctx *ctx, const struct v4l2_ctrl_hevc_sps *sps) 153 { 154 /* 155 * for tile pixel format check if the width and height match 156 * hardware constraints 157 */ 158 if (ctx->vpu_dst_fmt->fourcc == V4L2_PIX_FMT_NV12_4L4) { 159 if (ctx->dst_fmt.width != 160 ALIGN(sps->pic_width_in_luma_samples, ctx->vpu_dst_fmt->frmsize.step_width)) 161 return -EINVAL; 162 163 if (ctx->dst_fmt.height != 164 ALIGN(sps->pic_height_in_luma_samples, ctx->vpu_dst_fmt->frmsize.step_height)) 165 return -EINVAL; 166 } 167 168 return 0; 169 } 170 171 int hantro_hevc_dec_prepare_run(struct hantro_ctx *ctx) 172 { 173 struct hantro_hevc_dec_hw_ctx *hevc_ctx = &ctx->hevc_dec; 174 struct hantro_hevc_dec_ctrls *ctrls = &hevc_ctx->ctrls; 175 int ret; 176 177 hantro_start_prepare_run(ctx); 178 179 ctrls->decode_params = 180 hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_DECODE_PARAMS); 181 if (WARN_ON(!ctrls->decode_params)) 182 return -EINVAL; 183 184 ctrls->scaling = 185 hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_SCALING_MATRIX); 186 if (WARN_ON(!ctrls->scaling)) 187 return -EINVAL; 188 189 ctrls->sps = 190 hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_SPS); 191 if (WARN_ON(!ctrls->sps)) 192 return -EINVAL; 193 194 ret = hantro_hevc_validate_sps(ctx, ctrls->sps); 195 if (ret) 196 return ret; 197 198 ctrls->pps = 199 hantro_get_ctrl(ctx, V4L2_CID_STATELESS_HEVC_PPS); 200 if (WARN_ON(!ctrls->pps)) 201 return -EINVAL; 202 203 ret = tile_buffer_reallocate(ctx); 204 if (ret) 205 return ret; 206 207 return 0; 208 } 209 210 void hantro_hevc_dec_exit(struct hantro_ctx *ctx) 211 { 212 struct hantro_dev *vpu = ctx->dev; 213 struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; 214 215 if (hevc_dec->tile_sizes.cpu) 216 dma_free_coherent(vpu->dev, hevc_dec->tile_sizes.size, 217 hevc_dec->tile_sizes.cpu, 218 hevc_dec->tile_sizes.dma); 219 hevc_dec->tile_sizes.cpu = NULL; 220 221 if (hevc_dec->scaling_lists.cpu) 222 dma_free_coherent(vpu->dev, hevc_dec->scaling_lists.size, 223 hevc_dec->scaling_lists.cpu, 224 hevc_dec->scaling_lists.dma); 225 hevc_dec->scaling_lists.cpu = NULL; 226 227 if (hevc_dec->tile_filter.cpu) 228 dma_free_coherent(vpu->dev, hevc_dec->tile_filter.size, 229 hevc_dec->tile_filter.cpu, 230 hevc_dec->tile_filter.dma); 231 hevc_dec->tile_filter.cpu = NULL; 232 233 if (hevc_dec->tile_sao.cpu) 234 dma_free_coherent(vpu->dev, hevc_dec->tile_sao.size, 235 hevc_dec->tile_sao.cpu, 236 hevc_dec->tile_sao.dma); 237 hevc_dec->tile_sao.cpu = NULL; 238 239 if (hevc_dec->tile_bsd.cpu) 240 dma_free_coherent(vpu->dev, hevc_dec->tile_bsd.size, 241 hevc_dec->tile_bsd.cpu, 242 hevc_dec->tile_bsd.dma); 243 hevc_dec->tile_bsd.cpu = NULL; 244 } 245 246 int hantro_hevc_dec_init(struct hantro_ctx *ctx) 247 { 248 struct hantro_dev *vpu = ctx->dev; 249 struct hantro_hevc_dec_hw_ctx *hevc_dec = &ctx->hevc_dec; 250 unsigned int size; 251 252 memset(hevc_dec, 0, sizeof(*hevc_dec)); 253 254 /* 255 * Maximum number of tiles times width and height (2 bytes each), 256 * rounding up to next 16 bytes boundary + one extra 16 byte 257 * chunk (HW guys wanted to have this). 258 */ 259 size = round_up(MAX_TILE_COLS * MAX_TILE_ROWS * 4 * sizeof(u16) + 16, 16); 260 hevc_dec->tile_sizes.cpu = dma_alloc_coherent(vpu->dev, size, 261 &hevc_dec->tile_sizes.dma, 262 GFP_KERNEL); 263 if (!hevc_dec->tile_sizes.cpu) 264 return -ENOMEM; 265 266 hevc_dec->tile_sizes.size = size; 267 268 hevc_dec->scaling_lists.cpu = dma_alloc_coherent(vpu->dev, SCALING_LIST_SIZE, 269 &hevc_dec->scaling_lists.dma, 270 GFP_KERNEL); 271 if (!hevc_dec->scaling_lists.cpu) 272 return -ENOMEM; 273 274 hevc_dec->scaling_lists.size = SCALING_LIST_SIZE; 275 276 hantro_hevc_ref_init(ctx); 277 278 return 0; 279 } 280