1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2013 Advanced Micro Devices, Inc. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg#include <stdio.h> 29848b8605Smrg 30848b8605Smrg#include "pipe/p_video_codec.h" 31848b8605Smrg 32848b8605Smrg#include "util/u_video.h" 33848b8605Smrg#include "util/u_memory.h" 34848b8605Smrg 35848b8605Smrg#include "vl/vl_video_buffer.h" 36848b8605Smrg 37b8e80941Smrg#include "radeonsi/si_pipe.h" 38848b8605Smrg#include "radeon_video.h" 39848b8605Smrg#include "radeon_vce.h" 40848b8605Smrg 41b8e80941Smrg#define FW_40_2_2 ((40 << 24) | (2 << 16) | (2 << 8)) 42b8e80941Smrg#define FW_50_0_1 ((50 << 24) | (0 << 16) | (1 << 8)) 43b8e80941Smrg#define FW_50_1_2 ((50 << 24) | (1 << 16) | (2 << 8)) 44b8e80941Smrg#define FW_50_10_2 ((50 << 24) | (10 << 16) | (2 << 8)) 45b8e80941Smrg#define FW_50_17_3 ((50 << 24) | (17 << 16) | (3 << 8)) 46b8e80941Smrg#define FW_52_0_3 ((52 << 24) | (0 << 16) | (3 << 8)) 47b8e80941Smrg#define FW_52_4_3 ((52 << 24) | (4 << 16) | (3 << 8)) 48b8e80941Smrg#define FW_52_8_3 ((52 << 24) | (8 << 16) | (3 << 8)) 49b8e80941Smrg#define FW_53 (53 << 24) 50b8e80941Smrg 51848b8605Smrg/** 52848b8605Smrg * flush commands to the hardware 53848b8605Smrg */ 54848b8605Smrgstatic void flush(struct rvce_encoder *enc) 55848b8605Smrg{ 56b8e80941Smrg enc->ws->cs_flush(enc->cs, PIPE_FLUSH_ASYNC, NULL); 57b8e80941Smrg enc->task_info_idx = 0; 58b8e80941Smrg enc->bs_idx = 0; 59848b8605Smrg} 60848b8605Smrg 61848b8605Smrg#if 0 62848b8605Smrgstatic void dump_feedback(struct rvce_encoder *enc, struct rvid_buffer *fb) 63848b8605Smrg{ 64b8e80941Smrg uint32_t *ptr = enc->ws->buffer_map(fb->res->buf, enc->cs, PIPE_TRANSFER_READ_WRITE); 65848b8605Smrg unsigned i = 0; 66848b8605Smrg fprintf(stderr, "\n"); 67848b8605Smrg fprintf(stderr, "encStatus:\t\t\t%08x\n", ptr[i++]); 68848b8605Smrg fprintf(stderr, "encHasBitstream:\t\t%08x\n", ptr[i++]); 69848b8605Smrg fprintf(stderr, "encHasAudioBitstream:\t\t%08x\n", ptr[i++]); 70848b8605Smrg fprintf(stderr, "encBitstreamOffset:\t\t%08x\n", ptr[i++]); 71848b8605Smrg fprintf(stderr, "encBitstreamSize:\t\t%08x\n", ptr[i++]); 72848b8605Smrg fprintf(stderr, "encAudioBitstreamOffset:\t%08x\n", ptr[i++]); 73848b8605Smrg fprintf(stderr, "encAudioBitstreamSize:\t\t%08x\n", ptr[i++]); 74848b8605Smrg fprintf(stderr, "encExtrabytes:\t\t\t%08x\n", ptr[i++]); 75848b8605Smrg fprintf(stderr, "encAudioExtrabytes:\t\t%08x\n", ptr[i++]); 76848b8605Smrg fprintf(stderr, "videoTimeStamp:\t\t\t%08x\n", ptr[i++]); 77848b8605Smrg fprintf(stderr, "audioTimeStamp:\t\t\t%08x\n", ptr[i++]); 78848b8605Smrg fprintf(stderr, "videoOutputType:\t\t%08x\n", ptr[i++]); 79848b8605Smrg fprintf(stderr, "attributeFlags:\t\t\t%08x\n", ptr[i++]); 80848b8605Smrg fprintf(stderr, "seiPrivatePackageOffset:\t%08x\n", ptr[i++]); 81848b8605Smrg fprintf(stderr, "seiPrivatePackageSize:\t\t%08x\n", ptr[i++]); 82848b8605Smrg fprintf(stderr, "\n"); 83b8e80941Smrg enc->ws->buffer_unmap(fb->res->buf); 84848b8605Smrg} 85848b8605Smrg#endif 86848b8605Smrg 87848b8605Smrg/** 88848b8605Smrg * reset the CPB handling 89848b8605Smrg */ 90848b8605Smrgstatic void reset_cpb(struct rvce_encoder *enc) 91848b8605Smrg{ 92848b8605Smrg unsigned i; 93848b8605Smrg 94848b8605Smrg LIST_INITHEAD(&enc->cpb_slots); 95848b8605Smrg for (i = 0; i < enc->cpb_num; ++i) { 96848b8605Smrg struct rvce_cpb_slot *slot = &enc->cpb_array[i]; 97848b8605Smrg slot->index = i; 98848b8605Smrg slot->picture_type = PIPE_H264_ENC_PICTURE_TYPE_SKIP; 99848b8605Smrg slot->frame_num = 0; 100848b8605Smrg slot->pic_order_cnt = 0; 101848b8605Smrg LIST_ADDTAIL(&slot->list, &enc->cpb_slots); 102848b8605Smrg } 103848b8605Smrg} 104848b8605Smrg 105848b8605Smrg/** 106848b8605Smrg * sort l0 and l1 to the top of the list 107848b8605Smrg */ 108848b8605Smrgstatic void sort_cpb(struct rvce_encoder *enc) 109848b8605Smrg{ 110848b8605Smrg struct rvce_cpb_slot *i, *l0 = NULL, *l1 = NULL; 111848b8605Smrg 112848b8605Smrg LIST_FOR_EACH_ENTRY(i, &enc->cpb_slots, list) { 113848b8605Smrg if (i->frame_num == enc->pic.ref_idx_l0) 114848b8605Smrg l0 = i; 115848b8605Smrg 116848b8605Smrg if (i->frame_num == enc->pic.ref_idx_l1) 117848b8605Smrg l1 = i; 118848b8605Smrg 119848b8605Smrg if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P && l0) 120848b8605Smrg break; 121848b8605Smrg 122848b8605Smrg if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_B && 123848b8605Smrg l0 && l1) 124848b8605Smrg break; 125848b8605Smrg } 126848b8605Smrg 127848b8605Smrg if (l1) { 128848b8605Smrg LIST_DEL(&l1->list); 129848b8605Smrg LIST_ADD(&l1->list, &enc->cpb_slots); 130848b8605Smrg } 131848b8605Smrg 132848b8605Smrg if (l0) { 133848b8605Smrg LIST_DEL(&l0->list); 134848b8605Smrg LIST_ADD(&l0->list, &enc->cpb_slots); 135848b8605Smrg } 136848b8605Smrg} 137848b8605Smrg 138848b8605Smrg/** 139848b8605Smrg * get number of cpbs based on dpb 140848b8605Smrg */ 141848b8605Smrgstatic unsigned get_cpb_num(struct rvce_encoder *enc) 142848b8605Smrg{ 143848b8605Smrg unsigned w = align(enc->base.width, 16) / 16; 144848b8605Smrg unsigned h = align(enc->base.height, 16) / 16; 145848b8605Smrg unsigned dpb; 146848b8605Smrg 147848b8605Smrg switch (enc->base.level) { 148848b8605Smrg case 10: 149848b8605Smrg dpb = 396; 150848b8605Smrg break; 151848b8605Smrg case 11: 152848b8605Smrg dpb = 900; 153848b8605Smrg break; 154848b8605Smrg case 12: 155848b8605Smrg case 13: 156848b8605Smrg case 20: 157848b8605Smrg dpb = 2376; 158848b8605Smrg break; 159848b8605Smrg case 21: 160848b8605Smrg dpb = 4752; 161848b8605Smrg break; 162848b8605Smrg case 22: 163848b8605Smrg case 30: 164848b8605Smrg dpb = 8100; 165848b8605Smrg break; 166848b8605Smrg case 31: 167848b8605Smrg dpb = 18000; 168848b8605Smrg break; 169848b8605Smrg case 32: 170848b8605Smrg dpb = 20480; 171848b8605Smrg break; 172848b8605Smrg case 40: 173848b8605Smrg case 41: 174848b8605Smrg dpb = 32768; 175848b8605Smrg break; 176848b8605Smrg case 42: 177848b8605Smrg dpb = 34816; 178848b8605Smrg break; 179848b8605Smrg case 50: 180848b8605Smrg dpb = 110400; 181848b8605Smrg break; 182b8e80941Smrg default: 183848b8605Smrg case 51: 184b8e80941Smrg case 52: 185848b8605Smrg dpb = 184320; 186848b8605Smrg break; 187848b8605Smrg } 188848b8605Smrg 189848b8605Smrg return MIN2(dpb / (w * h), 16); 190848b8605Smrg} 191848b8605Smrg 192b8e80941Smrg/** 193b8e80941Smrg * Get the slot for the currently encoded frame 194b8e80941Smrg */ 195b8e80941Smrgstruct rvce_cpb_slot *si_current_slot(struct rvce_encoder *enc) 196b8e80941Smrg{ 197b8e80941Smrg return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.prev, list); 198b8e80941Smrg} 199b8e80941Smrg 200b8e80941Smrg/** 201b8e80941Smrg * Get the slot for L0 202b8e80941Smrg */ 203b8e80941Smrgstruct rvce_cpb_slot *si_l0_slot(struct rvce_encoder *enc) 204b8e80941Smrg{ 205b8e80941Smrg return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.next, list); 206b8e80941Smrg} 207b8e80941Smrg 208b8e80941Smrg/** 209b8e80941Smrg * Get the slot for L1 210b8e80941Smrg */ 211b8e80941Smrgstruct rvce_cpb_slot *si_l1_slot(struct rvce_encoder *enc) 212b8e80941Smrg{ 213b8e80941Smrg return LIST_ENTRY(struct rvce_cpb_slot, enc->cpb_slots.next->next, list); 214b8e80941Smrg} 215b8e80941Smrg 216b8e80941Smrg/** 217b8e80941Smrg * Calculate the offsets into the CPB 218b8e80941Smrg */ 219b8e80941Smrgvoid si_vce_frame_offset(struct rvce_encoder *enc, struct rvce_cpb_slot *slot, 220b8e80941Smrg signed *luma_offset, signed *chroma_offset) 221b8e80941Smrg{ 222b8e80941Smrg struct si_screen *sscreen = (struct si_screen *)enc->screen; 223b8e80941Smrg unsigned pitch, vpitch, fsize; 224b8e80941Smrg 225b8e80941Smrg if (sscreen->info.chip_class < GFX9) { 226b8e80941Smrg pitch = align(enc->luma->u.legacy.level[0].nblk_x * enc->luma->bpe, 128); 227b8e80941Smrg vpitch = align(enc->luma->u.legacy.level[0].nblk_y, 16); 228b8e80941Smrg } else { 229b8e80941Smrg pitch = align(enc->luma->u.gfx9.surf_pitch * enc->luma->bpe, 256); 230b8e80941Smrg vpitch = align(enc->luma->u.gfx9.surf_height, 16); 231b8e80941Smrg } 232b8e80941Smrg fsize = pitch * (vpitch + vpitch / 2); 233b8e80941Smrg 234b8e80941Smrg *luma_offset = slot->index * fsize; 235b8e80941Smrg *chroma_offset = *luma_offset + pitch * vpitch; 236b8e80941Smrg} 237b8e80941Smrg 238848b8605Smrg/** 239848b8605Smrg * destroy this video encoder 240848b8605Smrg */ 241848b8605Smrgstatic void rvce_destroy(struct pipe_video_codec *encoder) 242848b8605Smrg{ 243848b8605Smrg struct rvce_encoder *enc = (struct rvce_encoder*)encoder; 244848b8605Smrg if (enc->stream_handle) { 245848b8605Smrg struct rvid_buffer fb; 246b8e80941Smrg si_vid_create_buffer(enc->screen, &fb, 512, PIPE_USAGE_STAGING); 247848b8605Smrg enc->fb = &fb; 248848b8605Smrg enc->session(enc); 249848b8605Smrg enc->destroy(enc); 250848b8605Smrg flush(enc); 251b8e80941Smrg si_vid_destroy_buffer(&fb); 252848b8605Smrg } 253b8e80941Smrg si_vid_destroy_buffer(&enc->cpb); 254848b8605Smrg enc->ws->cs_destroy(enc->cs); 255848b8605Smrg FREE(enc->cpb_array); 256848b8605Smrg FREE(enc); 257848b8605Smrg} 258848b8605Smrg 259848b8605Smrgstatic void rvce_begin_frame(struct pipe_video_codec *encoder, 260848b8605Smrg struct pipe_video_buffer *source, 261848b8605Smrg struct pipe_picture_desc *picture) 262848b8605Smrg{ 263848b8605Smrg struct rvce_encoder *enc = (struct rvce_encoder*)encoder; 264848b8605Smrg struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source; 265848b8605Smrg struct pipe_h264_enc_picture_desc *pic = (struct pipe_h264_enc_picture_desc *)picture; 266848b8605Smrg 267848b8605Smrg bool need_rate_control = 268848b8605Smrg enc->pic.rate_ctrl.rate_ctrl_method != pic->rate_ctrl.rate_ctrl_method || 269848b8605Smrg enc->pic.quant_i_frames != pic->quant_i_frames || 270848b8605Smrg enc->pic.quant_p_frames != pic->quant_p_frames || 271848b8605Smrg enc->pic.quant_b_frames != pic->quant_b_frames; 272848b8605Smrg 273848b8605Smrg enc->pic = *pic; 274b8e80941Smrg si_get_pic_param(enc, pic); 275848b8605Smrg 276848b8605Smrg enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma); 277848b8605Smrg enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma); 278848b8605Smrg 279848b8605Smrg if (pic->picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR) 280848b8605Smrg reset_cpb(enc); 281848b8605Smrg else if (pic->picture_type == PIPE_H264_ENC_PICTURE_TYPE_P || 282848b8605Smrg pic->picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) 283848b8605Smrg sort_cpb(enc); 284848b8605Smrg 285848b8605Smrg if (!enc->stream_handle) { 286848b8605Smrg struct rvid_buffer fb; 287b8e80941Smrg enc->stream_handle = si_vid_alloc_stream_handle(); 288b8e80941Smrg si_vid_create_buffer(enc->screen, &fb, 512, PIPE_USAGE_STAGING); 289848b8605Smrg enc->fb = &fb; 290848b8605Smrg enc->session(enc); 291848b8605Smrg enc->create(enc); 292b8e80941Smrg enc->config(enc); 293848b8605Smrg enc->feedback(enc); 294848b8605Smrg flush(enc); 295848b8605Smrg //dump_feedback(enc, &fb); 296b8e80941Smrg si_vid_destroy_buffer(&fb); 297b8e80941Smrg need_rate_control = false; 298848b8605Smrg } 299848b8605Smrg 300b8e80941Smrg if (need_rate_control) { 301b8e80941Smrg enc->session(enc); 302b8e80941Smrg enc->config(enc); 303b8e80941Smrg flush(enc); 304b8e80941Smrg } 305848b8605Smrg} 306848b8605Smrg 307848b8605Smrgstatic void rvce_encode_bitstream(struct pipe_video_codec *encoder, 308848b8605Smrg struct pipe_video_buffer *source, 309848b8605Smrg struct pipe_resource *destination, 310848b8605Smrg void **fb) 311848b8605Smrg{ 312848b8605Smrg struct rvce_encoder *enc = (struct rvce_encoder*)encoder; 313848b8605Smrg enc->get_buffer(destination, &enc->bs_handle, NULL); 314848b8605Smrg enc->bs_size = destination->width0; 315848b8605Smrg 316848b8605Smrg *fb = enc->fb = CALLOC_STRUCT(rvid_buffer); 317b8e80941Smrg if (!si_vid_create_buffer(enc->screen, enc->fb, 512, PIPE_USAGE_STAGING)) { 318848b8605Smrg RVID_ERR("Can't create feedback buffer.\n"); 319848b8605Smrg return; 320848b8605Smrg } 321b8e80941Smrg if (!radeon_emitted(enc->cs, 0)) 322b8e80941Smrg enc->session(enc); 323848b8605Smrg enc->encode(enc); 324848b8605Smrg enc->feedback(enc); 325848b8605Smrg} 326848b8605Smrg 327848b8605Smrgstatic void rvce_end_frame(struct pipe_video_codec *encoder, 328848b8605Smrg struct pipe_video_buffer *source, 329848b8605Smrg struct pipe_picture_desc *picture) 330848b8605Smrg{ 331848b8605Smrg struct rvce_encoder *enc = (struct rvce_encoder*)encoder; 332848b8605Smrg struct rvce_cpb_slot *slot = LIST_ENTRY( 333848b8605Smrg struct rvce_cpb_slot, enc->cpb_slots.prev, list); 334848b8605Smrg 335b8e80941Smrg if (!enc->dual_inst || enc->bs_idx > 1) 336b8e80941Smrg flush(enc); 337848b8605Smrg 338848b8605Smrg /* update the CPB backtrack with the just encoded frame */ 339848b8605Smrg slot->picture_type = enc->pic.picture_type; 340848b8605Smrg slot->frame_num = enc->pic.frame_num; 341848b8605Smrg slot->pic_order_cnt = enc->pic.pic_order_cnt; 342848b8605Smrg if (!enc->pic.not_referenced) { 343848b8605Smrg LIST_DEL(&slot->list); 344848b8605Smrg LIST_ADD(&slot->list, &enc->cpb_slots); 345848b8605Smrg } 346848b8605Smrg} 347848b8605Smrg 348848b8605Smrgstatic void rvce_get_feedback(struct pipe_video_codec *encoder, 349848b8605Smrg void *feedback, unsigned *size) 350848b8605Smrg{ 351848b8605Smrg struct rvce_encoder *enc = (struct rvce_encoder*)encoder; 352848b8605Smrg struct rvid_buffer *fb = feedback; 353848b8605Smrg 354848b8605Smrg if (size) { 355b8e80941Smrg uint32_t *ptr = enc->ws->buffer_map( 356b8e80941Smrg fb->res->buf, enc->cs, 357b8e80941Smrg PIPE_TRANSFER_READ_WRITE | RADEON_TRANSFER_TEMPORARY); 358848b8605Smrg 359848b8605Smrg if (ptr[1]) { 360848b8605Smrg *size = ptr[4] - ptr[9]; 361848b8605Smrg } else { 362848b8605Smrg *size = 0; 363848b8605Smrg } 364848b8605Smrg 365b8e80941Smrg enc->ws->buffer_unmap(fb->res->buf); 366848b8605Smrg } 367848b8605Smrg //dump_feedback(enc, fb); 368b8e80941Smrg si_vid_destroy_buffer(fb); 369848b8605Smrg FREE(fb); 370848b8605Smrg} 371848b8605Smrg 372848b8605Smrg/** 373848b8605Smrg * flush any outstanding command buffers to the hardware 374848b8605Smrg */ 375848b8605Smrgstatic void rvce_flush(struct pipe_video_codec *encoder) 376848b8605Smrg{ 377b8e80941Smrg struct rvce_encoder *enc = (struct rvce_encoder*)encoder; 378b8e80941Smrg 379b8e80941Smrg flush(enc); 380848b8605Smrg} 381848b8605Smrg 382848b8605Smrgstatic void rvce_cs_flush(void *ctx, unsigned flags, 383848b8605Smrg struct pipe_fence_handle **fence) 384848b8605Smrg{ 385848b8605Smrg // just ignored 386848b8605Smrg} 387848b8605Smrg 388b8e80941Smrgstruct pipe_video_codec *si_vce_create_encoder(struct pipe_context *context, 389b8e80941Smrg const struct pipe_video_codec *templ, 390b8e80941Smrg struct radeon_winsys* ws, 391b8e80941Smrg rvce_get_buffer get_buffer) 392848b8605Smrg{ 393b8e80941Smrg struct si_screen *sscreen = (struct si_screen *)context->screen; 394b8e80941Smrg struct si_context *sctx = (struct si_context*)context; 395848b8605Smrg struct rvce_encoder *enc; 396848b8605Smrg struct pipe_video_buffer *tmp_buf, templat = {}; 397b8e80941Smrg struct radeon_surf *tmp_surf; 398848b8605Smrg unsigned cpb_size; 399848b8605Smrg 400b8e80941Smrg if (!sscreen->info.vce_fw_version) { 401848b8605Smrg RVID_ERR("Kernel doesn't supports VCE!\n"); 402848b8605Smrg return NULL; 403848b8605Smrg 404b8e80941Smrg } else if (!si_vce_is_fw_version_supported(sscreen)) { 405848b8605Smrg RVID_ERR("Unsupported VCE fw version loaded!\n"); 406848b8605Smrg return NULL; 407848b8605Smrg } 408848b8605Smrg 409848b8605Smrg enc = CALLOC_STRUCT(rvce_encoder); 410848b8605Smrg if (!enc) 411848b8605Smrg return NULL; 412848b8605Smrg 413b8e80941Smrg if (sscreen->info.drm_major == 3) 414b8e80941Smrg enc->use_vm = true; 415b8e80941Smrg if ((sscreen->info.drm_major == 2 && sscreen->info.drm_minor >= 42) || 416b8e80941Smrg sscreen->info.drm_major == 3) 417b8e80941Smrg enc->use_vui = true; 418b8e80941Smrg if (sscreen->info.family >= CHIP_TONGA && 419b8e80941Smrg sscreen->info.family != CHIP_STONEY && 420b8e80941Smrg sscreen->info.family != CHIP_POLARIS11 && 421b8e80941Smrg sscreen->info.family != CHIP_POLARIS12 && 422b8e80941Smrg sscreen->info.family != CHIP_VEGAM) 423b8e80941Smrg enc->dual_pipe = true; 424b8e80941Smrg /* TODO enable B frame with dual instance */ 425b8e80941Smrg if ((sscreen->info.family >= CHIP_TONGA) && 426b8e80941Smrg (templ->max_references == 1) && 427b8e80941Smrg (sscreen->info.vce_harvest_config == 0)) 428b8e80941Smrg enc->dual_inst = true; 429b8e80941Smrg 430848b8605Smrg enc->base = *templ; 431848b8605Smrg enc->base.context = context; 432848b8605Smrg 433848b8605Smrg enc->base.destroy = rvce_destroy; 434848b8605Smrg enc->base.begin_frame = rvce_begin_frame; 435848b8605Smrg enc->base.encode_bitstream = rvce_encode_bitstream; 436848b8605Smrg enc->base.end_frame = rvce_end_frame; 437848b8605Smrg enc->base.flush = rvce_flush; 438848b8605Smrg enc->base.get_feedback = rvce_get_feedback; 439848b8605Smrg enc->get_buffer = get_buffer; 440848b8605Smrg 441b8e80941Smrg enc->screen = context->screen; 442848b8605Smrg enc->ws = ws; 443b8e80941Smrg enc->cs = ws->cs_create(sctx->ctx, RING_VCE, rvce_cs_flush, enc, false); 444848b8605Smrg if (!enc->cs) { 445848b8605Smrg RVID_ERR("Can't get command submission context.\n"); 446848b8605Smrg goto error; 447848b8605Smrg } 448848b8605Smrg 449848b8605Smrg templat.buffer_format = PIPE_FORMAT_NV12; 450848b8605Smrg templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 451848b8605Smrg templat.width = enc->base.width; 452848b8605Smrg templat.height = enc->base.height; 453848b8605Smrg templat.interlaced = false; 454848b8605Smrg if (!(tmp_buf = context->create_video_buffer(context, &templat))) { 455848b8605Smrg RVID_ERR("Can't create video buffer.\n"); 456848b8605Smrg goto error; 457848b8605Smrg } 458848b8605Smrg 459848b8605Smrg enc->cpb_num = get_cpb_num(enc); 460848b8605Smrg if (!enc->cpb_num) 461848b8605Smrg goto error; 462848b8605Smrg 463848b8605Smrg get_buffer(((struct vl_video_buffer *)tmp_buf)->resources[0], NULL, &tmp_surf); 464b8e80941Smrg 465b8e80941Smrg cpb_size = (sscreen->info.chip_class < GFX9) ? 466b8e80941Smrg align(tmp_surf->u.legacy.level[0].nblk_x * tmp_surf->bpe, 128) * 467b8e80941Smrg align(tmp_surf->u.legacy.level[0].nblk_y, 32) : 468b8e80941Smrg 469b8e80941Smrg align(tmp_surf->u.gfx9.surf_pitch * tmp_surf->bpe, 256) * 470b8e80941Smrg align(tmp_surf->u.gfx9.surf_height, 32); 471b8e80941Smrg 472848b8605Smrg cpb_size = cpb_size * 3 / 2; 473848b8605Smrg cpb_size = cpb_size * enc->cpb_num; 474b8e80941Smrg if (enc->dual_pipe) 475b8e80941Smrg cpb_size += RVCE_MAX_AUX_BUFFER_NUM * 476b8e80941Smrg RVCE_MAX_BITSTREAM_OUTPUT_ROW_SIZE * 2; 477848b8605Smrg tmp_buf->destroy(tmp_buf); 478b8e80941Smrg if (!si_vid_create_buffer(enc->screen, &enc->cpb, cpb_size, PIPE_USAGE_DEFAULT)) { 479848b8605Smrg RVID_ERR("Can't create CPB buffer.\n"); 480848b8605Smrg goto error; 481848b8605Smrg } 482848b8605Smrg 483848b8605Smrg enc->cpb_array = CALLOC(enc->cpb_num, sizeof(struct rvce_cpb_slot)); 484848b8605Smrg if (!enc->cpb_array) 485848b8605Smrg goto error; 486848b8605Smrg 487848b8605Smrg reset_cpb(enc); 488848b8605Smrg 489b8e80941Smrg switch (sscreen->info.vce_fw_version) { 490b8e80941Smrg case FW_40_2_2: 491b8e80941Smrg si_vce_40_2_2_init(enc); 492b8e80941Smrg si_get_pic_param = si_vce_40_2_2_get_param; 493b8e80941Smrg break; 494b8e80941Smrg 495b8e80941Smrg case FW_50_0_1: 496b8e80941Smrg case FW_50_1_2: 497b8e80941Smrg case FW_50_10_2: 498b8e80941Smrg case FW_50_17_3: 499b8e80941Smrg si_vce_50_init(enc); 500b8e80941Smrg si_get_pic_param = si_vce_50_get_param; 501b8e80941Smrg break; 502b8e80941Smrg 503b8e80941Smrg case FW_52_0_3: 504b8e80941Smrg case FW_52_4_3: 505b8e80941Smrg case FW_52_8_3: 506b8e80941Smrg si_vce_52_init(enc); 507b8e80941Smrg si_get_pic_param = si_vce_52_get_param; 508b8e80941Smrg break; 509b8e80941Smrg 510b8e80941Smrg default: 511b8e80941Smrg if ((sscreen->info.vce_fw_version & (0xff << 24)) >= FW_53) { 512b8e80941Smrg si_vce_52_init(enc); 513b8e80941Smrg si_get_pic_param = si_vce_52_get_param; 514b8e80941Smrg } else 515b8e80941Smrg goto error; 516b8e80941Smrg } 517848b8605Smrg 518848b8605Smrg return &enc->base; 519848b8605Smrg 520848b8605Smrgerror: 521848b8605Smrg if (enc->cs) 522848b8605Smrg enc->ws->cs_destroy(enc->cs); 523848b8605Smrg 524b8e80941Smrg si_vid_destroy_buffer(&enc->cpb); 525848b8605Smrg 526848b8605Smrg FREE(enc->cpb_array); 527848b8605Smrg FREE(enc); 528848b8605Smrg return NULL; 529848b8605Smrg} 530848b8605Smrg 531848b8605Smrg/** 532848b8605Smrg * check if kernel has the right fw version loaded 533848b8605Smrg */ 534b8e80941Smrgbool si_vce_is_fw_version_supported(struct si_screen *sscreen) 535848b8605Smrg{ 536b8e80941Smrg switch (sscreen->info.vce_fw_version) { 537b8e80941Smrg case FW_40_2_2: 538b8e80941Smrg case FW_50_0_1: 539b8e80941Smrg case FW_50_1_2: 540b8e80941Smrg case FW_50_10_2: 541b8e80941Smrg case FW_50_17_3: 542b8e80941Smrg case FW_52_0_3: 543b8e80941Smrg case FW_52_4_3: 544b8e80941Smrg case FW_52_8_3: 545b8e80941Smrg return true; 546b8e80941Smrg default: 547b8e80941Smrg if ((sscreen->info.vce_fw_version & (0xff << 24)) >= FW_53) 548b8e80941Smrg return true; 549b8e80941Smrg else 550b8e80941Smrg return false; 551b8e80941Smrg } 552b8e80941Smrg} 553b8e80941Smrg 554b8e80941Smrg/** 555b8e80941Smrg * Add the buffer as relocation to the current command submission 556b8e80941Smrg */ 557b8e80941Smrgvoid si_vce_add_buffer(struct rvce_encoder *enc, struct pb_buffer *buf, 558b8e80941Smrg enum radeon_bo_usage usage, enum radeon_bo_domain domain, 559b8e80941Smrg signed offset) 560b8e80941Smrg{ 561b8e80941Smrg int reloc_idx; 562b8e80941Smrg 563b8e80941Smrg reloc_idx = enc->ws->cs_add_buffer(enc->cs, buf, usage | RADEON_USAGE_SYNCHRONIZED, 564b8e80941Smrg domain, 0); 565b8e80941Smrg if (enc->use_vm) { 566b8e80941Smrg uint64_t addr; 567b8e80941Smrg addr = enc->ws->buffer_get_virtual_address(buf); 568b8e80941Smrg addr = addr + offset; 569b8e80941Smrg RVCE_CS(addr >> 32); 570b8e80941Smrg RVCE_CS(addr); 571b8e80941Smrg } else { 572b8e80941Smrg offset += enc->ws->buffer_get_reloc_offset(buf); 573b8e80941Smrg RVCE_CS(reloc_idx * 4); 574b8e80941Smrg RVCE_CS(offset); 575b8e80941Smrg } 576848b8605Smrg} 577