1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2013 Ilia Mirkin 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include <sys/mman.h> 24bf215546Sopenharmony_ci#include <sys/stat.h> 25bf215546Sopenharmony_ci#include <sys/types.h> 26bf215546Sopenharmony_ci#include <fcntl.h> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_sampler.h" 30bf215546Sopenharmony_ci#include "vl/vl_zscan.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "nv50/nv84_video.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_cistatic int 35bf215546Sopenharmony_cinv84_copy_firmware(const char *path, void *dest, ssize_t len) 36bf215546Sopenharmony_ci{ 37bf215546Sopenharmony_ci int fd = open(path, O_RDONLY | O_CLOEXEC); 38bf215546Sopenharmony_ci ssize_t r; 39bf215546Sopenharmony_ci if (fd < 0) { 40bf215546Sopenharmony_ci fprintf(stderr, "opening firmware file %s failed: %m\n", path); 41bf215546Sopenharmony_ci return 1; 42bf215546Sopenharmony_ci } 43bf215546Sopenharmony_ci r = read(fd, dest, len); 44bf215546Sopenharmony_ci close(fd); 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci if (r != len) { 47bf215546Sopenharmony_ci fprintf(stderr, "reading firmware file %s failed: %m\n", path); 48bf215546Sopenharmony_ci return 1; 49bf215546Sopenharmony_ci } 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci return 0; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic int 55bf215546Sopenharmony_cifilesize(const char *path) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci int ret; 58bf215546Sopenharmony_ci struct stat statbuf; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci ret = stat(path, &statbuf); 61bf215546Sopenharmony_ci if (ret) 62bf215546Sopenharmony_ci return ret; 63bf215546Sopenharmony_ci return statbuf.st_size; 64bf215546Sopenharmony_ci} 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_cistatic struct nouveau_bo * 67bf215546Sopenharmony_cinv84_load_firmwares(struct nouveau_device *dev, struct nv84_decoder *dec, 68bf215546Sopenharmony_ci const char *fw1, const char *fw2) 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci int ret, size1, size2 = 0; 71bf215546Sopenharmony_ci struct nouveau_bo *fw; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci size1 = filesize(fw1); 74bf215546Sopenharmony_ci if (fw2) 75bf215546Sopenharmony_ci size2 = filesize(fw2); 76bf215546Sopenharmony_ci if (size1 < 0 || size2 < 0) 77bf215546Sopenharmony_ci return NULL; 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci dec->vp_fw2_offset = align(size1, 0x100); 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, dec->vp_fw2_offset + size2, NULL, &fw); 82bf215546Sopenharmony_ci if (ret) 83bf215546Sopenharmony_ci return NULL; 84bf215546Sopenharmony_ci ret = nouveau_bo_map(fw, NOUVEAU_BO_WR, dec->client); 85bf215546Sopenharmony_ci if (ret) 86bf215546Sopenharmony_ci goto error; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci ret = nv84_copy_firmware(fw1, fw->map, size1); 89bf215546Sopenharmony_ci if (fw2 && !ret) 90bf215546Sopenharmony_ci ret = nv84_copy_firmware(fw2, fw->map + dec->vp_fw2_offset, size2); 91bf215546Sopenharmony_ci munmap(fw->map, fw->size); 92bf215546Sopenharmony_ci fw->map = NULL; 93bf215546Sopenharmony_ci if (!ret) 94bf215546Sopenharmony_ci return fw; 95bf215546Sopenharmony_cierror: 96bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &fw); 97bf215546Sopenharmony_ci return NULL; 98bf215546Sopenharmony_ci} 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_cistatic struct nouveau_bo * 101bf215546Sopenharmony_cinv84_load_bsp_firmware(struct nouveau_device *dev, struct nv84_decoder *dec) 102bf215546Sopenharmony_ci{ 103bf215546Sopenharmony_ci return nv84_load_firmwares( 104bf215546Sopenharmony_ci dev, dec, "/lib/firmware/nouveau/nv84_bsp-h264", NULL); 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_cistatic struct nouveau_bo * 108bf215546Sopenharmony_cinv84_load_vp_firmware(struct nouveau_device *dev, struct nv84_decoder *dec) 109bf215546Sopenharmony_ci{ 110bf215546Sopenharmony_ci return nv84_load_firmwares( 111bf215546Sopenharmony_ci dev, dec, 112bf215546Sopenharmony_ci "/lib/firmware/nouveau/nv84_vp-h264-1", 113bf215546Sopenharmony_ci "/lib/firmware/nouveau/nv84_vp-h264-2"); 114bf215546Sopenharmony_ci} 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_cistatic struct nouveau_bo * 117bf215546Sopenharmony_cinv84_load_vp_firmware_mpeg(struct nouveau_device *dev, struct nv84_decoder *dec) 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci return nv84_load_firmwares( 120bf215546Sopenharmony_ci dev, dec, "/lib/firmware/nouveau/nv84_vp-mpeg12", NULL); 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic void 124bf215546Sopenharmony_cinv84_decoder_decode_bitstream_h264(struct pipe_video_codec *decoder, 125bf215546Sopenharmony_ci struct pipe_video_buffer *video_target, 126bf215546Sopenharmony_ci struct pipe_picture_desc *picture, 127bf215546Sopenharmony_ci unsigned num_buffers, 128bf215546Sopenharmony_ci const void *const *data, 129bf215546Sopenharmony_ci const unsigned *num_bytes) 130bf215546Sopenharmony_ci{ 131bf215546Sopenharmony_ci struct nv84_decoder *dec = (struct nv84_decoder *)decoder; 132bf215546Sopenharmony_ci struct nv84_video_buffer *target = (struct nv84_video_buffer *)video_target; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci struct pipe_h264_picture_desc *desc = (struct pipe_h264_picture_desc *)picture; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci assert(target->base.buffer_format == PIPE_FORMAT_NV12); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci nv84_decoder_bsp(dec, desc, num_buffers, data, num_bytes, target); 139bf215546Sopenharmony_ci nv84_decoder_vp_h264(dec, desc, target); 140bf215546Sopenharmony_ci} 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_cistatic void 143bf215546Sopenharmony_cinv84_decoder_flush(struct pipe_video_codec *decoder) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci} 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_cistatic void 148bf215546Sopenharmony_cinv84_decoder_begin_frame_h264(struct pipe_video_codec *decoder, 149bf215546Sopenharmony_ci struct pipe_video_buffer *target, 150bf215546Sopenharmony_ci struct pipe_picture_desc *picture) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci} 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_cistatic void 155bf215546Sopenharmony_cinv84_decoder_end_frame_h264(struct pipe_video_codec *decoder, 156bf215546Sopenharmony_ci struct pipe_video_buffer *target, 157bf215546Sopenharmony_ci struct pipe_picture_desc *picture) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci} 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_cistatic void 162bf215546Sopenharmony_cinv84_decoder_decode_bitstream_mpeg12(struct pipe_video_codec *decoder, 163bf215546Sopenharmony_ci struct pipe_video_buffer *video_target, 164bf215546Sopenharmony_ci struct pipe_picture_desc *picture, 165bf215546Sopenharmony_ci unsigned num_buffers, 166bf215546Sopenharmony_ci const void *const *data, 167bf215546Sopenharmony_ci const unsigned *num_bytes) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci struct nv84_decoder *dec = (struct nv84_decoder *)decoder; 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci assert(video_target->buffer_format == PIPE_FORMAT_NV12); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci vl_mpg12_bs_decode(dec->mpeg12_bs, 174bf215546Sopenharmony_ci video_target, 175bf215546Sopenharmony_ci (struct pipe_mpeg12_picture_desc *)picture, 176bf215546Sopenharmony_ci num_buffers, 177bf215546Sopenharmony_ci data, 178bf215546Sopenharmony_ci num_bytes); 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cistatic void 182bf215546Sopenharmony_cinv84_decoder_begin_frame_mpeg12(struct pipe_video_codec *decoder, 183bf215546Sopenharmony_ci struct pipe_video_buffer *target, 184bf215546Sopenharmony_ci struct pipe_picture_desc *picture) 185bf215546Sopenharmony_ci{ 186bf215546Sopenharmony_ci struct nv84_decoder *dec = (struct nv84_decoder *)decoder; 187bf215546Sopenharmony_ci struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture; 188bf215546Sopenharmony_ci int i; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci nouveau_bo_wait(dec->mpeg12_bo, NOUVEAU_BO_RDWR, dec->client); 191bf215546Sopenharmony_ci dec->mpeg12_mb_info = dec->mpeg12_bo->map + 0x100; 192bf215546Sopenharmony_ci dec->mpeg12_data = dec->mpeg12_bo->map + 0x100 + 193bf215546Sopenharmony_ci align(0x20 * mb(dec->base.width) * mb(dec->base.height), 0x100); 194bf215546Sopenharmony_ci if (desc->intra_matrix) { 195bf215546Sopenharmony_ci dec->zscan = desc->alternate_scan ? vl_zscan_alternate : vl_zscan_normal; 196bf215546Sopenharmony_ci for (i = 0; i < 64; i++) { 197bf215546Sopenharmony_ci dec->mpeg12_intra_matrix[i] = desc->intra_matrix[dec->zscan[i]]; 198bf215546Sopenharmony_ci dec->mpeg12_non_intra_matrix[i] = desc->non_intra_matrix[dec->zscan[i]]; 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci dec->mpeg12_intra_matrix[0] = 1 << (7 - desc->intra_dc_precision); 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_cistatic void 205bf215546Sopenharmony_cinv84_decoder_end_frame_mpeg12(struct pipe_video_codec *decoder, 206bf215546Sopenharmony_ci struct pipe_video_buffer *target, 207bf215546Sopenharmony_ci struct pipe_picture_desc *picture) 208bf215546Sopenharmony_ci{ 209bf215546Sopenharmony_ci nv84_decoder_vp_mpeg12( 210bf215546Sopenharmony_ci (struct nv84_decoder *)decoder, 211bf215546Sopenharmony_ci (struct pipe_mpeg12_picture_desc *)picture, 212bf215546Sopenharmony_ci (struct nv84_video_buffer *)target); 213bf215546Sopenharmony_ci} 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_cistatic void 216bf215546Sopenharmony_cinv84_decoder_decode_macroblock(struct pipe_video_codec *decoder, 217bf215546Sopenharmony_ci struct pipe_video_buffer *target, 218bf215546Sopenharmony_ci struct pipe_picture_desc *picture, 219bf215546Sopenharmony_ci const struct pipe_macroblock *macroblocks, 220bf215546Sopenharmony_ci unsigned num_macroblocks) 221bf215546Sopenharmony_ci{ 222bf215546Sopenharmony_ci const struct pipe_mpeg12_macroblock *mb = (const struct pipe_mpeg12_macroblock *)macroblocks; 223bf215546Sopenharmony_ci for (int i = 0; i < num_macroblocks; i++, mb++) { 224bf215546Sopenharmony_ci nv84_decoder_vp_mpeg12_mb( 225bf215546Sopenharmony_ci (struct nv84_decoder *)decoder, 226bf215546Sopenharmony_ci (struct pipe_mpeg12_picture_desc *)picture, 227bf215546Sopenharmony_ci mb); 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci} 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_cistatic void 232bf215546Sopenharmony_cinv84_decoder_destroy(struct pipe_video_codec *decoder) 233bf215546Sopenharmony_ci{ 234bf215546Sopenharmony_ci struct nv84_decoder *dec = (struct nv84_decoder *)decoder; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->bsp_fw); 237bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->bsp_data); 238bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->vp_fw); 239bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->vp_data); 240bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->mbring); 241bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->vpring); 242bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->bitstream); 243bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->vp_params); 244bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->fence); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci nouveau_object_del(&dec->bsp); 247bf215546Sopenharmony_ci nouveau_object_del(&dec->vp); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci nouveau_bufctx_del(&dec->bsp_bufctx); 250bf215546Sopenharmony_ci nouveau_pushbuf_del(&dec->bsp_pushbuf); 251bf215546Sopenharmony_ci nouveau_object_del(&dec->bsp_channel); 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci nouveau_bufctx_del(&dec->vp_bufctx); 254bf215546Sopenharmony_ci nouveau_pushbuf_del(&dec->vp_pushbuf); 255bf215546Sopenharmony_ci nouveau_object_del(&dec->vp_channel); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci nouveau_client_del(&dec->client); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci FREE(dec->mpeg12_bs); 260bf215546Sopenharmony_ci FREE(dec); 261bf215546Sopenharmony_ci} 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_cistruct pipe_video_codec * 264bf215546Sopenharmony_cinv84_create_decoder(struct pipe_context *context, 265bf215546Sopenharmony_ci const struct pipe_video_codec *templ) 266bf215546Sopenharmony_ci{ 267bf215546Sopenharmony_ci struct nv50_context *nv50 = (struct nv50_context *)context; 268bf215546Sopenharmony_ci struct nouveau_screen *screen = &nv50->screen->base; 269bf215546Sopenharmony_ci struct nv84_decoder *dec; 270bf215546Sopenharmony_ci struct nouveau_pushbuf *bsp_push, *vp_push; 271bf215546Sopenharmony_ci struct nv50_surface surf; 272bf215546Sopenharmony_ci struct nv50_miptree mip; 273bf215546Sopenharmony_ci union pipe_color_union color; 274bf215546Sopenharmony_ci struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 }; 275bf215546Sopenharmony_ci int ret, i; 276bf215546Sopenharmony_ci int is_h264 = u_reduce_video_profile(templ->profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC; 277bf215546Sopenharmony_ci int is_mpeg12 = u_reduce_video_profile(templ->profile) == PIPE_VIDEO_FORMAT_MPEG12; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci if (getenv("XVMC_VL")) 280bf215546Sopenharmony_ci return vl_create_decoder(context, templ); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci if ((is_h264 && templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) || 283bf215546Sopenharmony_ci (is_mpeg12 && templ->entrypoint > PIPE_VIDEO_ENTRYPOINT_IDCT)) { 284bf215546Sopenharmony_ci debug_printf("%x\n", templ->entrypoint); 285bf215546Sopenharmony_ci return NULL; 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci if (!is_h264 && !is_mpeg12) { 289bf215546Sopenharmony_ci debug_printf("invalid profile: %x\n", templ->profile); 290bf215546Sopenharmony_ci return NULL; 291bf215546Sopenharmony_ci } 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci dec = CALLOC_STRUCT(nv84_decoder); 294bf215546Sopenharmony_ci if (!dec) 295bf215546Sopenharmony_ci return NULL; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci dec->base = *templ; 298bf215546Sopenharmony_ci dec->base.context = context; 299bf215546Sopenharmony_ci dec->base.destroy = nv84_decoder_destroy; 300bf215546Sopenharmony_ci dec->base.flush = nv84_decoder_flush; 301bf215546Sopenharmony_ci if (is_h264) { 302bf215546Sopenharmony_ci dec->base.decode_bitstream = nv84_decoder_decode_bitstream_h264; 303bf215546Sopenharmony_ci dec->base.begin_frame = nv84_decoder_begin_frame_h264; 304bf215546Sopenharmony_ci dec->base.end_frame = nv84_decoder_end_frame_h264; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci dec->frame_mbs = mb(dec->base.width) * mb_half(dec->base.height) * 2; 307bf215546Sopenharmony_ci dec->frame_size = dec->frame_mbs << 8; 308bf215546Sopenharmony_ci dec->vpring_deblock = align(0x30 * dec->frame_mbs, 0x100); 309bf215546Sopenharmony_ci dec->vpring_residual = 0x2000 + MAX2(0x32000, 0x600 * dec->frame_mbs); 310bf215546Sopenharmony_ci dec->vpring_ctrl = MAX2(0x10000, align(0x1080 + 0x144 * dec->frame_mbs, 0x100)); 311bf215546Sopenharmony_ci } else if (is_mpeg12) { 312bf215546Sopenharmony_ci dec->base.decode_macroblock = nv84_decoder_decode_macroblock; 313bf215546Sopenharmony_ci dec->base.begin_frame = nv84_decoder_begin_frame_mpeg12; 314bf215546Sopenharmony_ci dec->base.end_frame = nv84_decoder_end_frame_mpeg12; 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci if (templ->entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) { 317bf215546Sopenharmony_ci dec->mpeg12_bs = CALLOC_STRUCT(vl_mpg12_bs); 318bf215546Sopenharmony_ci if (!dec->mpeg12_bs) 319bf215546Sopenharmony_ci goto fail; 320bf215546Sopenharmony_ci vl_mpg12_bs_init(dec->mpeg12_bs, &dec->base); 321bf215546Sopenharmony_ci dec->base.decode_bitstream = nv84_decoder_decode_bitstream_mpeg12; 322bf215546Sopenharmony_ci } 323bf215546Sopenharmony_ci } else { 324bf215546Sopenharmony_ci goto fail; 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci ret = nouveau_client_new(screen->device, &dec->client); 328bf215546Sopenharmony_ci if (ret) 329bf215546Sopenharmony_ci goto fail; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci if (is_h264) { 332bf215546Sopenharmony_ci ret = nouveau_object_new(&screen->device->object, 0, 333bf215546Sopenharmony_ci NOUVEAU_FIFO_CHANNEL_CLASS, 334bf215546Sopenharmony_ci &nv04_data, sizeof(nv04_data), &dec->bsp_channel); 335bf215546Sopenharmony_ci if (ret) 336bf215546Sopenharmony_ci goto fail; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci ret = nouveau_pushbuf_new(dec->client, dec->bsp_channel, 4, 339bf215546Sopenharmony_ci 32 * 1024, true, &dec->bsp_pushbuf); 340bf215546Sopenharmony_ci if (ret) 341bf215546Sopenharmony_ci goto fail; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci ret = nouveau_bufctx_new(dec->client, 1, &dec->bsp_bufctx); 344bf215546Sopenharmony_ci if (ret) 345bf215546Sopenharmony_ci goto fail; 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci ret = nouveau_object_new(&screen->device->object, 0, 349bf215546Sopenharmony_ci NOUVEAU_FIFO_CHANNEL_CLASS, 350bf215546Sopenharmony_ci &nv04_data, sizeof(nv04_data), &dec->vp_channel); 351bf215546Sopenharmony_ci if (ret) 352bf215546Sopenharmony_ci goto fail; 353bf215546Sopenharmony_ci ret = nouveau_pushbuf_new(dec->client, dec->vp_channel, 4, 354bf215546Sopenharmony_ci 32 * 1024, true, &dec->vp_pushbuf); 355bf215546Sopenharmony_ci if (ret) 356bf215546Sopenharmony_ci goto fail; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci ret = nouveau_bufctx_new(dec->client, 1, &dec->vp_bufctx); 359bf215546Sopenharmony_ci if (ret) 360bf215546Sopenharmony_ci goto fail; 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci bsp_push = dec->bsp_pushbuf; 363bf215546Sopenharmony_ci vp_push = dec->vp_pushbuf; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci if (is_h264) { 366bf215546Sopenharmony_ci dec->bsp_fw = nv84_load_bsp_firmware(screen->device, dec); 367bf215546Sopenharmony_ci dec->vp_fw = nv84_load_vp_firmware(screen->device, dec); 368bf215546Sopenharmony_ci if (!dec->bsp_fw || !dec->vp_fw) 369bf215546Sopenharmony_ci goto fail; 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci if (is_mpeg12) { 372bf215546Sopenharmony_ci dec->vp_fw = nv84_load_vp_firmware_mpeg(screen->device, dec); 373bf215546Sopenharmony_ci if (!dec->vp_fw) 374bf215546Sopenharmony_ci goto fail; 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci if (is_h264) { 378bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 379bf215546Sopenharmony_ci 0, 0x40000, NULL, &dec->bsp_data); 380bf215546Sopenharmony_ci if (ret) 381bf215546Sopenharmony_ci goto fail; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 384bf215546Sopenharmony_ci 0, 0x40000, NULL, &dec->vp_data); 385bf215546Sopenharmony_ci if (ret) 386bf215546Sopenharmony_ci goto fail; 387bf215546Sopenharmony_ci if (is_h264) { 388bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 389bf215546Sopenharmony_ci 0, 390bf215546Sopenharmony_ci 2 * (dec->vpring_deblock + 391bf215546Sopenharmony_ci dec->vpring_residual + 392bf215546Sopenharmony_ci dec->vpring_ctrl + 393bf215546Sopenharmony_ci 0x1000), 394bf215546Sopenharmony_ci NULL, &dec->vpring); 395bf215546Sopenharmony_ci if (ret) 396bf215546Sopenharmony_ci goto fail; 397bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 398bf215546Sopenharmony_ci 0, 399bf215546Sopenharmony_ci (templ->max_references + 1) * dec->frame_mbs * 0x40 + 400bf215546Sopenharmony_ci dec->frame_size + 0x2000, 401bf215546Sopenharmony_ci NULL, &dec->mbring); 402bf215546Sopenharmony_ci if (ret) 403bf215546Sopenharmony_ci goto fail; 404bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART, 405bf215546Sopenharmony_ci 0, 2 * (0x700 + MAX2(0x40000, 0x800 + 0x180 * dec->frame_mbs)), 406bf215546Sopenharmony_ci NULL, &dec->bitstream); 407bf215546Sopenharmony_ci if (ret) 408bf215546Sopenharmony_ci goto fail; 409bf215546Sopenharmony_ci ret = nouveau_bo_map(dec->bitstream, NOUVEAU_BO_WR, dec->client); 410bf215546Sopenharmony_ci if (ret) 411bf215546Sopenharmony_ci goto fail; 412bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART, 413bf215546Sopenharmony_ci 0, 0x2000, NULL, &dec->vp_params); 414bf215546Sopenharmony_ci if (ret) 415bf215546Sopenharmony_ci goto fail; 416bf215546Sopenharmony_ci ret = nouveau_bo_map(dec->vp_params, NOUVEAU_BO_WR, dec->client); 417bf215546Sopenharmony_ci if (ret) 418bf215546Sopenharmony_ci goto fail; 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci if (is_mpeg12) { 421bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART, 422bf215546Sopenharmony_ci 0, 423bf215546Sopenharmony_ci align(0x20 * mb(templ->width) * mb(templ->height), 0x100) + 424bf215546Sopenharmony_ci (6 * 64 * 8) * mb(templ->width) * mb(templ->height) + 0x100, 425bf215546Sopenharmony_ci NULL, &dec->mpeg12_bo); 426bf215546Sopenharmony_ci if (ret) 427bf215546Sopenharmony_ci goto fail; 428bf215546Sopenharmony_ci ret = nouveau_bo_map(dec->mpeg12_bo, NOUVEAU_BO_WR, dec->client); 429bf215546Sopenharmony_ci if (ret) 430bf215546Sopenharmony_ci goto fail; 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 434bf215546Sopenharmony_ci 0, 0x1000, NULL, &dec->fence); 435bf215546Sopenharmony_ci if (ret) 436bf215546Sopenharmony_ci goto fail; 437bf215546Sopenharmony_ci ret = nouveau_bo_map(dec->fence, NOUVEAU_BO_WR, dec->client); 438bf215546Sopenharmony_ci if (ret) 439bf215546Sopenharmony_ci goto fail; 440bf215546Sopenharmony_ci *(uint32_t *)dec->fence->map = 0; 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci if (is_h264) { 443bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(bsp_push, dec->bsp_bufctx); 444bf215546Sopenharmony_ci nouveau_bufctx_refn(dec->bsp_bufctx, 0, 445bf215546Sopenharmony_ci dec->bsp_fw, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 446bf215546Sopenharmony_ci nouveau_bufctx_refn(dec->bsp_bufctx, 0, 447bf215546Sopenharmony_ci dec->bsp_data, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 448bf215546Sopenharmony_ci } 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(vp_push, dec->vp_bufctx); 451bf215546Sopenharmony_ci nouveau_bufctx_refn(dec->vp_bufctx, 0, dec->vp_fw, 452bf215546Sopenharmony_ci NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 453bf215546Sopenharmony_ci nouveau_bufctx_refn(dec->vp_bufctx, 0, dec->vp_data, 454bf215546Sopenharmony_ci NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci if (is_h264 && !ret) 457bf215546Sopenharmony_ci ret = nouveau_object_new(dec->bsp_channel, 0xbeef74b0, 0x74b0, 458bf215546Sopenharmony_ci NULL, 0, &dec->bsp); 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci if (!ret) 461bf215546Sopenharmony_ci ret = nouveau_object_new(dec->vp_channel, 0xbeef7476, 0x7476, 462bf215546Sopenharmony_ci NULL, 0, &dec->vp); 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci if (ret) 465bf215546Sopenharmony_ci goto fail; 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci if (is_h264) { 469bf215546Sopenharmony_ci /* Zero out some parts of mbring/vpring. there's gotta be some cleaner way 470bf215546Sopenharmony_ci * of doing this... perhaps makes sense to just copy the relevant logic 471bf215546Sopenharmony_ci * here. */ 472bf215546Sopenharmony_ci color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0; 473bf215546Sopenharmony_ci surf.offset = dec->frame_size; 474bf215546Sopenharmony_ci surf.width = 64; 475bf215546Sopenharmony_ci surf.height = (templ->max_references + 1) * dec->frame_mbs / 4; 476bf215546Sopenharmony_ci surf.depth = 1; 477bf215546Sopenharmony_ci surf.base.format = PIPE_FORMAT_B8G8R8A8_UNORM; 478bf215546Sopenharmony_ci surf.base.u.tex.level = 0; 479bf215546Sopenharmony_ci surf.base.texture = &mip.base.base; 480bf215546Sopenharmony_ci mip.level[0].tile_mode = 0; 481bf215546Sopenharmony_ci mip.level[0].pitch = surf.width * 4; 482bf215546Sopenharmony_ci mip.base.domain = NOUVEAU_BO_VRAM; 483bf215546Sopenharmony_ci mip.base.bo = dec->mbring; 484bf215546Sopenharmony_ci mip.base.address = dec->mbring->offset; 485bf215546Sopenharmony_ci context->clear_render_target(context, &surf.base, &color, 0, 0, 64, 4760, false); 486bf215546Sopenharmony_ci surf.offset = dec->vpring->size / 2 - 0x1000; 487bf215546Sopenharmony_ci surf.width = 1024; 488bf215546Sopenharmony_ci surf.height = 1; 489bf215546Sopenharmony_ci mip.level[0].pitch = surf.width * 4; 490bf215546Sopenharmony_ci mip.base.bo = dec->vpring; 491bf215546Sopenharmony_ci mip.base.address = dec->vpring->offset; 492bf215546Sopenharmony_ci context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1, false); 493bf215546Sopenharmony_ci surf.offset = dec->vpring->size - 0x1000; 494bf215546Sopenharmony_ci context->clear_render_target(context, &surf.base, &color, 0, 0, 1024, 1, false); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci PUSH_SPACE(nv50->base.pushbuf, 5); 497bf215546Sopenharmony_ci PUSH_REFN(nv50->base.pushbuf, dec->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 498bf215546Sopenharmony_ci /* The clear_render_target is done via 3D engine, so use it to write to a 499bf215546Sopenharmony_ci * sempahore to indicate that it's done. 500bf215546Sopenharmony_ci */ 501bf215546Sopenharmony_ci BEGIN_NV04(nv50->base.pushbuf, NV50_3D(QUERY_ADDRESS_HIGH), 4); 502bf215546Sopenharmony_ci PUSH_DATAh(nv50->base.pushbuf, dec->fence->offset); 503bf215546Sopenharmony_ci PUSH_DATA (nv50->base.pushbuf, dec->fence->offset); 504bf215546Sopenharmony_ci PUSH_DATA (nv50->base.pushbuf, 1); 505bf215546Sopenharmony_ci PUSH_DATA (nv50->base.pushbuf, 0xf010); 506bf215546Sopenharmony_ci PUSH_KICK (nv50->base.pushbuf); 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci PUSH_SPACE(bsp_push, 2 + 12 + 2 + 4 + 3); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci BEGIN_NV04(bsp_push, SUBC_BSP(NV01_SUBCHAN_OBJECT), 1); 511bf215546Sopenharmony_ci PUSH_DATA (bsp_push, dec->bsp->handle); 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci BEGIN_NV04(bsp_push, SUBC_BSP(0x180), 11); 514bf215546Sopenharmony_ci for (i = 0; i < 11; i++) 515bf215546Sopenharmony_ci PUSH_DATA(bsp_push, nv04_data.vram); 516bf215546Sopenharmony_ci BEGIN_NV04(bsp_push, SUBC_BSP(0x1b8), 1); 517bf215546Sopenharmony_ci PUSH_DATA (bsp_push, nv04_data.vram); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci BEGIN_NV04(bsp_push, SUBC_BSP(0x600), 3); 520bf215546Sopenharmony_ci PUSH_DATAh(bsp_push, dec->bsp_fw->offset); 521bf215546Sopenharmony_ci PUSH_DATA (bsp_push, dec->bsp_fw->offset); 522bf215546Sopenharmony_ci PUSH_DATA (bsp_push, dec->bsp_fw->size); 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci BEGIN_NV04(bsp_push, SUBC_BSP(0x628), 2); 525bf215546Sopenharmony_ci PUSH_DATA (bsp_push, dec->bsp_data->offset >> 8); 526bf215546Sopenharmony_ci PUSH_DATA (bsp_push, dec->bsp_data->size); 527bf215546Sopenharmony_ci PUSH_KICK (bsp_push); 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci PUSH_SPACE(vp_push, 2 + 12 + 2 + 4 + 3); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci BEGIN_NV04(vp_push, SUBC_VP(NV01_SUBCHAN_OBJECT), 1); 533bf215546Sopenharmony_ci PUSH_DATA (vp_push, dec->vp->handle); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci BEGIN_NV04(vp_push, SUBC_VP(0x180), 11); 536bf215546Sopenharmony_ci for (i = 0; i < 11; i++) 537bf215546Sopenharmony_ci PUSH_DATA(vp_push, nv04_data.vram); 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci BEGIN_NV04(vp_push, SUBC_VP(0x1b8), 1); 540bf215546Sopenharmony_ci PUSH_DATA (vp_push, nv04_data.vram); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci BEGIN_NV04(vp_push, SUBC_VP(0x600), 3); 543bf215546Sopenharmony_ci PUSH_DATAh(vp_push, dec->vp_fw->offset); 544bf215546Sopenharmony_ci PUSH_DATA (vp_push, dec->vp_fw->offset); 545bf215546Sopenharmony_ci PUSH_DATA (vp_push, dec->vp_fw->size); 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci BEGIN_NV04(vp_push, SUBC_VP(0x628), 2); 548bf215546Sopenharmony_ci PUSH_DATA (vp_push, dec->vp_data->offset >> 8); 549bf215546Sopenharmony_ci PUSH_DATA (vp_push, dec->vp_data->size); 550bf215546Sopenharmony_ci PUSH_KICK (vp_push); 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci return &dec->base; 553bf215546Sopenharmony_cifail: 554bf215546Sopenharmony_ci nv84_decoder_destroy(&dec->base); 555bf215546Sopenharmony_ci return NULL; 556bf215546Sopenharmony_ci} 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_cistatic struct pipe_sampler_view ** 559bf215546Sopenharmony_cinv84_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer) 560bf215546Sopenharmony_ci{ 561bf215546Sopenharmony_ci struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer; 562bf215546Sopenharmony_ci return buf->sampler_view_planes; 563bf215546Sopenharmony_ci} 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_cistatic struct pipe_sampler_view ** 566bf215546Sopenharmony_cinv84_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer) 567bf215546Sopenharmony_ci{ 568bf215546Sopenharmony_ci struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer; 569bf215546Sopenharmony_ci return buf->sampler_view_components; 570bf215546Sopenharmony_ci} 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_cistatic struct pipe_surface ** 573bf215546Sopenharmony_cinv84_video_buffer_surfaces(struct pipe_video_buffer *buffer) 574bf215546Sopenharmony_ci{ 575bf215546Sopenharmony_ci struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer; 576bf215546Sopenharmony_ci return buf->surfaces; 577bf215546Sopenharmony_ci} 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_cistatic void 580bf215546Sopenharmony_cinv84_video_buffer_destroy(struct pipe_video_buffer *buffer) 581bf215546Sopenharmony_ci{ 582bf215546Sopenharmony_ci struct nv84_video_buffer *buf = (struct nv84_video_buffer *)buffer; 583bf215546Sopenharmony_ci unsigned i; 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci assert(buf); 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 588bf215546Sopenharmony_ci pipe_resource_reference(&buf->resources[i], NULL); 589bf215546Sopenharmony_ci pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL); 590bf215546Sopenharmony_ci pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); 591bf215546Sopenharmony_ci pipe_surface_reference(&buf->surfaces[i * 2], NULL); 592bf215546Sopenharmony_ci pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL); 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &buf->interlaced); 596bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &buf->full); 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci FREE(buffer); 599bf215546Sopenharmony_ci} 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_cistruct pipe_video_buffer * 602bf215546Sopenharmony_cinv84_video_buffer_create(struct pipe_context *pipe, 603bf215546Sopenharmony_ci const struct pipe_video_buffer *template) 604bf215546Sopenharmony_ci{ 605bf215546Sopenharmony_ci struct nv84_video_buffer *buffer; 606bf215546Sopenharmony_ci struct pipe_resource templ; 607bf215546Sopenharmony_ci unsigned i, j, component; 608bf215546Sopenharmony_ci struct pipe_sampler_view sv_templ; 609bf215546Sopenharmony_ci struct pipe_surface surf_templ; 610bf215546Sopenharmony_ci struct nv50_miptree *mt0, *mt1; 611bf215546Sopenharmony_ci struct nouveau_screen *screen = &((struct nv50_context *)pipe)->screen->base; 612bf215546Sopenharmony_ci union nouveau_bo_config cfg; 613bf215546Sopenharmony_ci unsigned bo_size; 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci if (getenv("XVMC_VL") || template->buffer_format != PIPE_FORMAT_NV12) 616bf215546Sopenharmony_ci return vl_video_buffer_create(pipe, template); 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci if (!template->interlaced) { 619bf215546Sopenharmony_ci debug_printf("Require interlaced video buffers\n"); 620bf215546Sopenharmony_ci return NULL; 621bf215546Sopenharmony_ci } 622bf215546Sopenharmony_ci if (pipe_format_to_chroma_format(template->buffer_format) != PIPE_VIDEO_CHROMA_FORMAT_420) { 623bf215546Sopenharmony_ci debug_printf("Must use 4:2:0 format\n"); 624bf215546Sopenharmony_ci return NULL; 625bf215546Sopenharmony_ci } 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci /* 628bf215546Sopenharmony_ci * Note that there are always going to be exactly two planes, one for Y, 629bf215546Sopenharmony_ci * and one for UV. These are also the resources. VP expects these to be 630bf215546Sopenharmony_ci * adjacent, so they need to belong to the same BO. 631bf215546Sopenharmony_ci */ 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci buffer = CALLOC_STRUCT(nv84_video_buffer); 634bf215546Sopenharmony_ci if (!buffer) return NULL; 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci buffer->mvidx = -1; 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci buffer->base.buffer_format = template->buffer_format; 639bf215546Sopenharmony_ci buffer->base.context = pipe; 640bf215546Sopenharmony_ci buffer->base.destroy = nv84_video_buffer_destroy; 641bf215546Sopenharmony_ci buffer->base.width = template->width; 642bf215546Sopenharmony_ci buffer->base.height = template->height; 643bf215546Sopenharmony_ci buffer->base.get_sampler_view_planes = nv84_video_buffer_sampler_view_planes; 644bf215546Sopenharmony_ci buffer->base.get_sampler_view_components = nv84_video_buffer_sampler_view_components; 645bf215546Sopenharmony_ci buffer->base.get_surfaces = nv84_video_buffer_surfaces; 646bf215546Sopenharmony_ci buffer->base.interlaced = true; 647bf215546Sopenharmony_ci 648bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 649bf215546Sopenharmony_ci templ.target = PIPE_TEXTURE_2D_ARRAY; 650bf215546Sopenharmony_ci templ.depth0 = 1; 651bf215546Sopenharmony_ci templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 652bf215546Sopenharmony_ci templ.format = PIPE_FORMAT_R8_UNORM; 653bf215546Sopenharmony_ci templ.width0 = align(template->width, 2); 654bf215546Sopenharmony_ci templ.height0 = align(template->height, 4) / 2; 655bf215546Sopenharmony_ci templ.flags = NV50_RESOURCE_FLAG_VIDEO | NV50_RESOURCE_FLAG_NOALLOC; 656bf215546Sopenharmony_ci templ.array_size = 2; 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_ci cfg.nv50.tile_mode = 0x20; 659bf215546Sopenharmony_ci cfg.nv50.memtype = 0x70; 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ); 662bf215546Sopenharmony_ci if (!buffer->resources[0]) 663bf215546Sopenharmony_ci goto error; 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci templ.format = PIPE_FORMAT_R8G8_UNORM; 666bf215546Sopenharmony_ci templ.width0 /= 2; 667bf215546Sopenharmony_ci templ.height0 /= 2; 668bf215546Sopenharmony_ci buffer->resources[1] = pipe->screen->resource_create(pipe->screen, &templ); 669bf215546Sopenharmony_ci if (!buffer->resources[1]) 670bf215546Sopenharmony_ci goto error; 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci mt0 = nv50_miptree(buffer->resources[0]); 673bf215546Sopenharmony_ci mt1 = nv50_miptree(buffer->resources[1]); 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci bo_size = mt0->total_size + mt1->total_size; 676bf215546Sopenharmony_ci if (nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 0, 677bf215546Sopenharmony_ci bo_size, &cfg, &buffer->interlaced)) 678bf215546Sopenharmony_ci goto error; 679bf215546Sopenharmony_ci /* XXX Change reference frame management so that this is only allocated in 680bf215546Sopenharmony_ci * the decoder when necessary. */ 681bf215546Sopenharmony_ci if (nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM | NOUVEAU_BO_NOSNOOP, 0, 682bf215546Sopenharmony_ci bo_size, &cfg, &buffer->full)) 683bf215546Sopenharmony_ci goto error; 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci nouveau_bo_ref(buffer->interlaced, &mt0->base.bo); 686bf215546Sopenharmony_ci mt0->base.domain = NOUVEAU_BO_VRAM; 687bf215546Sopenharmony_ci mt0->base.address = buffer->interlaced->offset; 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci nouveau_bo_ref(buffer->interlaced, &mt1->base.bo); 690bf215546Sopenharmony_ci mt1->base.domain = NOUVEAU_BO_VRAM; 691bf215546Sopenharmony_ci mt1->base.offset = mt0->total_size; 692bf215546Sopenharmony_ci mt1->base.address = buffer->interlaced->offset + mt0->total_size; 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci memset(&sv_templ, 0, sizeof(sv_templ)); 695bf215546Sopenharmony_ci for (component = 0, i = 0; i < 2; ++i ) { 696bf215546Sopenharmony_ci struct pipe_resource *res = buffer->resources[i]; 697bf215546Sopenharmony_ci unsigned nr_components = util_format_get_nr_components(res->format); 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci u_sampler_view_default_template(&sv_templ, res, res->format); 700bf215546Sopenharmony_ci buffer->sampler_view_planes[i] = 701bf215546Sopenharmony_ci pipe->create_sampler_view(pipe, res, &sv_templ); 702bf215546Sopenharmony_ci if (!buffer->sampler_view_planes[i]) 703bf215546Sopenharmony_ci goto error; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci for (j = 0; j < nr_components; ++j, ++component) { 706bf215546Sopenharmony_ci sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = 707bf215546Sopenharmony_ci PIPE_SWIZZLE_X + j; 708bf215546Sopenharmony_ci sv_templ.swizzle_a = PIPE_SWIZZLE_1; 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci buffer->sampler_view_components[component] = 711bf215546Sopenharmony_ci pipe->create_sampler_view(pipe, res, &sv_templ); 712bf215546Sopenharmony_ci if (!buffer->sampler_view_components[component]) 713bf215546Sopenharmony_ci goto error; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci memset(&surf_templ, 0, sizeof(surf_templ)); 718bf215546Sopenharmony_ci for (j = 0; j < 2; ++j) { 719bf215546Sopenharmony_ci surf_templ.format = buffer->resources[j]->format; 720bf215546Sopenharmony_ci surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0; 721bf215546Sopenharmony_ci buffer->surfaces[j * 2] = 722bf215546Sopenharmony_ci pipe->create_surface(pipe, buffer->resources[j], &surf_templ); 723bf215546Sopenharmony_ci if (!buffer->surfaces[j * 2]) 724bf215546Sopenharmony_ci goto error; 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1; 727bf215546Sopenharmony_ci buffer->surfaces[j * 2 + 1] = 728bf215546Sopenharmony_ci pipe->create_surface(pipe, buffer->resources[j], &surf_templ); 729bf215546Sopenharmony_ci if (!buffer->surfaces[j * 2 + 1]) 730bf215546Sopenharmony_ci goto error; 731bf215546Sopenharmony_ci } 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci return &buffer->base; 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_cierror: 736bf215546Sopenharmony_ci nv84_video_buffer_destroy(&buffer->base); 737bf215546Sopenharmony_ci return NULL; 738bf215546Sopenharmony_ci} 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci#define FIRMWARE_BSP_KERN 0x01 741bf215546Sopenharmony_ci#define FIRMWARE_VP_KERN 0x02 742bf215546Sopenharmony_ci#define FIRMWARE_BSP_H264 0x04 743bf215546Sopenharmony_ci#define FIRMWARE_VP_MPEG2 0x08 744bf215546Sopenharmony_ci#define FIRMWARE_VP_H264_1 0x10 745bf215546Sopenharmony_ci#define FIRMWARE_VP_H264_2 0x20 746bf215546Sopenharmony_ci#define FIRMWARE_PRESENT(val, fw) (val & FIRMWARE_ ## fw) 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_cistatic int 749bf215546Sopenharmony_cifirmware_present(struct pipe_screen *pscreen, enum pipe_video_format codec) 750bf215546Sopenharmony_ci{ 751bf215546Sopenharmony_ci struct nouveau_screen *screen = nouveau_screen(pscreen); 752bf215546Sopenharmony_ci struct nouveau_object *obj = NULL; 753bf215546Sopenharmony_ci struct stat s; 754bf215546Sopenharmony_ci int checked = screen->firmware_info.profiles_checked; 755bf215546Sopenharmony_ci int present, ret; 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci if (!FIRMWARE_PRESENT(checked, VP_KERN)) { 758bf215546Sopenharmony_ci ret = nouveau_object_new(screen->channel, 0, 0x7476, NULL, 0, &obj); 759bf215546Sopenharmony_ci if (!ret) 760bf215546Sopenharmony_ci screen->firmware_info.profiles_present |= FIRMWARE_VP_KERN; 761bf215546Sopenharmony_ci nouveau_object_del(&obj); 762bf215546Sopenharmony_ci screen->firmware_info.profiles_checked |= FIRMWARE_VP_KERN; 763bf215546Sopenharmony_ci } 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci if (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 766bf215546Sopenharmony_ci if (!FIRMWARE_PRESENT(checked, BSP_KERN)) { 767bf215546Sopenharmony_ci ret = nouveau_object_new(screen->channel, 0, 0x74b0, NULL, 0, &obj); 768bf215546Sopenharmony_ci if (!ret) 769bf215546Sopenharmony_ci screen->firmware_info.profiles_present |= FIRMWARE_BSP_KERN; 770bf215546Sopenharmony_ci nouveau_object_del(&obj); 771bf215546Sopenharmony_ci screen->firmware_info.profiles_checked |= FIRMWARE_BSP_KERN; 772bf215546Sopenharmony_ci } 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci if (!FIRMWARE_PRESENT(checked, VP_H264_1)) { 775bf215546Sopenharmony_ci ret = stat("/lib/firmware/nouveau/nv84_vp-h264-1", &s); 776bf215546Sopenharmony_ci if (!ret && s.st_size > 1000) 777bf215546Sopenharmony_ci screen->firmware_info.profiles_present |= FIRMWARE_VP_H264_1; 778bf215546Sopenharmony_ci screen->firmware_info.profiles_checked |= FIRMWARE_VP_H264_1; 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci /* should probably check the others, but assume that 1 means all */ 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci present = screen->firmware_info.profiles_present; 784bf215546Sopenharmony_ci return FIRMWARE_PRESENT(present, VP_KERN) && 785bf215546Sopenharmony_ci FIRMWARE_PRESENT(present, BSP_KERN) && 786bf215546Sopenharmony_ci FIRMWARE_PRESENT(present, VP_H264_1); 787bf215546Sopenharmony_ci } else { 788bf215546Sopenharmony_ci if (!FIRMWARE_PRESENT(checked, VP_MPEG2)) { 789bf215546Sopenharmony_ci ret = stat("/lib/firmware/nouveau/nv84_vp-mpeg12", &s); 790bf215546Sopenharmony_ci if (!ret && s.st_size > 1000) 791bf215546Sopenharmony_ci screen->firmware_info.profiles_present |= FIRMWARE_VP_MPEG2; 792bf215546Sopenharmony_ci screen->firmware_info.profiles_checked |= FIRMWARE_VP_MPEG2; 793bf215546Sopenharmony_ci } 794bf215546Sopenharmony_ci present = screen->firmware_info.profiles_present; 795bf215546Sopenharmony_ci return FIRMWARE_PRESENT(present, VP_KERN) && 796bf215546Sopenharmony_ci FIRMWARE_PRESENT(present, VP_MPEG2); 797bf215546Sopenharmony_ci } 798bf215546Sopenharmony_ci} 799bf215546Sopenharmony_ci 800bf215546Sopenharmony_ciint 801bf215546Sopenharmony_cinv84_screen_get_video_param(struct pipe_screen *pscreen, 802bf215546Sopenharmony_ci enum pipe_video_profile profile, 803bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 804bf215546Sopenharmony_ci enum pipe_video_cap param) 805bf215546Sopenharmony_ci{ 806bf215546Sopenharmony_ci enum pipe_video_format codec; 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci switch (param) { 809bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTED: 810bf215546Sopenharmony_ci codec = u_reduce_video_profile(profile); 811bf215546Sopenharmony_ci return (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC || 812bf215546Sopenharmony_ci codec == PIPE_VIDEO_FORMAT_MPEG12) && 813bf215546Sopenharmony_ci firmware_present(pscreen, codec); 814bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_NPOT_TEXTURES: 815bf215546Sopenharmony_ci return 1; 816bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_WIDTH: 817bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_HEIGHT: 818bf215546Sopenharmony_ci return 2048; 819bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERED_FORMAT: 820bf215546Sopenharmony_ci return PIPE_FORMAT_NV12; 821bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 822bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 823bf215546Sopenharmony_ci return true; 824bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 825bf215546Sopenharmony_ci return false; 826bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_LEVEL: 827bf215546Sopenharmony_ci switch (profile) { 828bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG1: 829bf215546Sopenharmony_ci return 0; 830bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 831bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 832bf215546Sopenharmony_ci return 3; 833bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 834bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 835bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 836bf215546Sopenharmony_ci return 41; 837bf215546Sopenharmony_ci default: 838bf215546Sopenharmony_ci debug_printf("unknown video profile: %d\n", profile); 839bf215546Sopenharmony_ci return 0; 840bf215546Sopenharmony_ci } 841bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_MACROBLOCKS: 842bf215546Sopenharmony_ci return 8192; /* vc-1 actually has 8190, but this is not supported */ 843bf215546Sopenharmony_ci default: 844bf215546Sopenharmony_ci debug_printf("unknown video param: %d\n", param); 845bf215546Sopenharmony_ci return 0; 846bf215546Sopenharmony_ci } 847bf215546Sopenharmony_ci} 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_cibool 850bf215546Sopenharmony_cinv84_screen_video_supported(struct pipe_screen *screen, 851bf215546Sopenharmony_ci enum pipe_format format, 852bf215546Sopenharmony_ci enum pipe_video_profile profile, 853bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint) 854bf215546Sopenharmony_ci{ 855bf215546Sopenharmony_ci if (profile != PIPE_VIDEO_PROFILE_UNKNOWN) 856bf215546Sopenharmony_ci return format == PIPE_FORMAT_NV12; 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint); 859bf215546Sopenharmony_ci} 860