1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2011-2013 Maarten Lankhorst 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 <stdio.h> 26bf215546Sopenharmony_ci#include <fcntl.h> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include <nvif/class.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "nouveau_screen.h" 31bf215546Sopenharmony_ci#include "nouveau_context.h" 32bf215546Sopenharmony_ci#include "nouveau_vp3_video.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "util/u_video.h" 35bf215546Sopenharmony_ci#include "util/format/u_format.h" 36bf215546Sopenharmony_ci#include "util/u_sampler.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic struct pipe_sampler_view ** 39bf215546Sopenharmony_cinouveau_vp3_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer) 40bf215546Sopenharmony_ci{ 41bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer; 42bf215546Sopenharmony_ci return buf->sampler_view_planes; 43bf215546Sopenharmony_ci} 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistatic struct pipe_sampler_view ** 46bf215546Sopenharmony_cinouveau_vp3_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer) 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer; 49bf215546Sopenharmony_ci return buf->sampler_view_components; 50bf215546Sopenharmony_ci} 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistatic struct pipe_surface ** 53bf215546Sopenharmony_cinouveau_vp3_video_buffer_surfaces(struct pipe_video_buffer *buffer) 54bf215546Sopenharmony_ci{ 55bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer; 56bf215546Sopenharmony_ci return buf->surfaces; 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_cistatic void 60bf215546Sopenharmony_cinouveau_vp3_video_buffer_destroy(struct pipe_video_buffer *buffer) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *buf = (struct nouveau_vp3_video_buffer *)buffer; 63bf215546Sopenharmony_ci unsigned i; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci assert(buf); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci for (i = 0; i < VL_NUM_COMPONENTS; ++i) { 68bf215546Sopenharmony_ci pipe_resource_reference(&buf->resources[i], NULL); 69bf215546Sopenharmony_ci pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL); 70bf215546Sopenharmony_ci pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL); 71bf215546Sopenharmony_ci pipe_surface_reference(&buf->surfaces[i * 2], NULL); 72bf215546Sopenharmony_ci pipe_surface_reference(&buf->surfaces[i * 2 + 1], NULL); 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci FREE(buffer); 75bf215546Sopenharmony_ci} 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_cistruct pipe_video_buffer * 78bf215546Sopenharmony_cinouveau_vp3_video_buffer_create(struct pipe_context *pipe, 79bf215546Sopenharmony_ci const struct pipe_video_buffer *templat, 80bf215546Sopenharmony_ci int flags) 81bf215546Sopenharmony_ci{ 82bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *buffer; 83bf215546Sopenharmony_ci struct pipe_resource templ; 84bf215546Sopenharmony_ci unsigned i, j, component; 85bf215546Sopenharmony_ci struct pipe_sampler_view sv_templ; 86bf215546Sopenharmony_ci struct pipe_surface surf_templ; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci if (getenv("XVMC_VL") || templat->buffer_format != PIPE_FORMAT_NV12) 89bf215546Sopenharmony_ci return vl_video_buffer_create(pipe, templat); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci assert(templat->interlaced); 92bf215546Sopenharmony_ci assert(pipe_format_to_chroma_format(templat->buffer_format) == PIPE_VIDEO_CHROMA_FORMAT_420); 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci buffer = CALLOC_STRUCT(nouveau_vp3_video_buffer); 95bf215546Sopenharmony_ci if (!buffer) 96bf215546Sopenharmony_ci return NULL; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci buffer->base.buffer_format = templat->buffer_format; 99bf215546Sopenharmony_ci buffer->base.context = pipe; 100bf215546Sopenharmony_ci buffer->base.destroy = nouveau_vp3_video_buffer_destroy; 101bf215546Sopenharmony_ci buffer->base.width = templat->width; 102bf215546Sopenharmony_ci buffer->base.height = templat->height; 103bf215546Sopenharmony_ci buffer->base.get_sampler_view_planes = nouveau_vp3_video_buffer_sampler_view_planes; 104bf215546Sopenharmony_ci buffer->base.get_sampler_view_components = nouveau_vp3_video_buffer_sampler_view_components; 105bf215546Sopenharmony_ci buffer->base.get_surfaces = nouveau_vp3_video_buffer_surfaces; 106bf215546Sopenharmony_ci buffer->base.interlaced = true; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 109bf215546Sopenharmony_ci templ.target = PIPE_TEXTURE_2D_ARRAY; 110bf215546Sopenharmony_ci templ.depth0 = 1; 111bf215546Sopenharmony_ci templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 112bf215546Sopenharmony_ci templ.format = PIPE_FORMAT_R8_UNORM; 113bf215546Sopenharmony_ci templ.width0 = buffer->base.width; 114bf215546Sopenharmony_ci templ.height0 = (buffer->base.height + 1)/2; 115bf215546Sopenharmony_ci templ.flags = flags; 116bf215546Sopenharmony_ci templ.array_size = 2; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci buffer->resources[0] = pipe->screen->resource_create(pipe->screen, &templ); 119bf215546Sopenharmony_ci if (!buffer->resources[0]) 120bf215546Sopenharmony_ci goto error; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci templ.format = PIPE_FORMAT_R8G8_UNORM; 123bf215546Sopenharmony_ci buffer->num_planes = 2; 124bf215546Sopenharmony_ci templ.width0 = (templ.width0 + 1) / 2; 125bf215546Sopenharmony_ci templ.height0 = (templ.height0 + 1) / 2; 126bf215546Sopenharmony_ci for (i = 1; i < buffer->num_planes; ++i) { 127bf215546Sopenharmony_ci buffer->resources[i] = pipe->screen->resource_create(pipe->screen, &templ); 128bf215546Sopenharmony_ci if (!buffer->resources[i]) 129bf215546Sopenharmony_ci goto error; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci memset(&sv_templ, 0, sizeof(sv_templ)); 133bf215546Sopenharmony_ci for (component = 0, i = 0; i < buffer->num_planes; ++i ) { 134bf215546Sopenharmony_ci struct pipe_resource *res = buffer->resources[i]; 135bf215546Sopenharmony_ci unsigned nr_components = util_format_get_nr_components(res->format); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci u_sampler_view_default_template(&sv_templ, res, res->format); 138bf215546Sopenharmony_ci buffer->sampler_view_planes[i] = pipe->create_sampler_view(pipe, res, &sv_templ); 139bf215546Sopenharmony_ci if (!buffer->sampler_view_planes[i]) 140bf215546Sopenharmony_ci goto error; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci for (j = 0; j < nr_components; ++j, ++component) { 143bf215546Sopenharmony_ci sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_X + j; 144bf215546Sopenharmony_ci sv_templ.swizzle_a = PIPE_SWIZZLE_1; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci buffer->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ); 147bf215546Sopenharmony_ci if (!buffer->sampler_view_components[component]) 148bf215546Sopenharmony_ci goto error; 149bf215546Sopenharmony_ci } 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci memset(&surf_templ, 0, sizeof(surf_templ)); 153bf215546Sopenharmony_ci for (j = 0; j < buffer->num_planes; ++j) { 154bf215546Sopenharmony_ci surf_templ.format = buffer->resources[j]->format; 155bf215546Sopenharmony_ci surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 0; 156bf215546Sopenharmony_ci buffer->surfaces[j * 2] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ); 157bf215546Sopenharmony_ci if (!buffer->surfaces[j * 2]) 158bf215546Sopenharmony_ci goto error; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = 1; 161bf215546Sopenharmony_ci buffer->surfaces[j * 2 + 1] = pipe->create_surface(pipe, buffer->resources[j], &surf_templ); 162bf215546Sopenharmony_ci if (!buffer->surfaces[j * 2 + 1]) 163bf215546Sopenharmony_ci goto error; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci return &buffer->base; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_cierror: 169bf215546Sopenharmony_ci nouveau_vp3_video_buffer_destroy(&buffer->base); 170bf215546Sopenharmony_ci return NULL; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_cistatic void 174bf215546Sopenharmony_cinouveau_vp3_decoder_flush(struct pipe_video_codec *decoder) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_cistatic void 179bf215546Sopenharmony_cinouveau_vp3_decoder_begin_frame(struct pipe_video_codec *decoder, 180bf215546Sopenharmony_ci struct pipe_video_buffer *target, 181bf215546Sopenharmony_ci struct pipe_picture_desc *picture) 182bf215546Sopenharmony_ci{ 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_cistatic void 186bf215546Sopenharmony_cinouveau_vp3_decoder_end_frame(struct pipe_video_codec *decoder, 187bf215546Sopenharmony_ci struct pipe_video_buffer *target, 188bf215546Sopenharmony_ci struct pipe_picture_desc *picture) 189bf215546Sopenharmony_ci{ 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_cistatic void 193bf215546Sopenharmony_cinouveau_vp3_decoder_destroy(struct pipe_video_codec *decoder) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci struct nouveau_vp3_decoder *dec = (struct nouveau_vp3_decoder *)decoder; 196bf215546Sopenharmony_ci int i; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->ref_bo); 199bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->bitplane_bo); 200bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->inter_bo[0]); 201bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->inter_bo[1]); 202bf215546Sopenharmony_ci#if NOUVEAU_VP3_DEBUG_FENCE 203bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->fence_bo); 204bf215546Sopenharmony_ci#endif 205bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->fw_bo); 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH; ++i) 208bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &dec->bsp_bo[i]); 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci nouveau_object_del(&dec->bsp); 211bf215546Sopenharmony_ci nouveau_object_del(&dec->vp); 212bf215546Sopenharmony_ci nouveau_object_del(&dec->ppp); 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (dec->channel[0] != dec->channel[1]) { 215bf215546Sopenharmony_ci for (i = 0; i < 3; ++i) { 216bf215546Sopenharmony_ci nouveau_pushbuf_del(&dec->pushbuf[i]); 217bf215546Sopenharmony_ci nouveau_object_del(&dec->channel[i]); 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci } else { 220bf215546Sopenharmony_ci nouveau_pushbuf_del(dec->pushbuf); 221bf215546Sopenharmony_ci nouveau_object_del(dec->channel); 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci FREE(dec); 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_civoid 228bf215546Sopenharmony_cinouveau_vp3_decoder_init_common(struct pipe_video_codec *dec) 229bf215546Sopenharmony_ci{ 230bf215546Sopenharmony_ci dec->destroy = nouveau_vp3_decoder_destroy; 231bf215546Sopenharmony_ci dec->flush = nouveau_vp3_decoder_flush; 232bf215546Sopenharmony_ci dec->begin_frame = nouveau_vp3_decoder_begin_frame; 233bf215546Sopenharmony_ci dec->end_frame = nouveau_vp3_decoder_end_frame; 234bf215546Sopenharmony_ci} 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_cistatic void vp3_getpath(enum pipe_video_profile profile, char *path) 237bf215546Sopenharmony_ci{ 238bf215546Sopenharmony_ci switch (u_reduce_video_profile(profile)) { 239bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG12: { 240bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-vp3-mpeg12-0"); 241bf215546Sopenharmony_ci break; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_VC1: { 244bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-vp3-vc1-0"); 245bf215546Sopenharmony_ci break; 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4_AVC: { 248bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-vp3-h264-0"); 249bf215546Sopenharmony_ci break; 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci default: assert(0); 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci} 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_cistatic void vp4_getpath(enum pipe_video_profile profile, char *path) 256bf215546Sopenharmony_ci{ 257bf215546Sopenharmony_ci switch (u_reduce_video_profile(profile)) { 258bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG12: { 259bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-mpeg12-0"); 260bf215546Sopenharmony_ci break; 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4: { 263bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-mpeg4-0"); 264bf215546Sopenharmony_ci break; 265bf215546Sopenharmony_ci } 266bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_VC1: { 267bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-vc1-0"); 268bf215546Sopenharmony_ci break; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4_AVC: { 271bf215546Sopenharmony_ci sprintf(path, "/lib/firmware/nouveau/vuc-h264-0"); 272bf215546Sopenharmony_ci break; 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci default: assert(0); 275bf215546Sopenharmony_ci } 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ciint 279bf215546Sopenharmony_cinouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, 280bf215546Sopenharmony_ci enum pipe_video_profile profile, 281bf215546Sopenharmony_ci unsigned chipset) 282bf215546Sopenharmony_ci{ 283bf215546Sopenharmony_ci int fd; 284bf215546Sopenharmony_ci char path[PATH_MAX]; 285bf215546Sopenharmony_ci ssize_t r; 286bf215546Sopenharmony_ci uint32_t *end, endval; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci if (chipset >= 0xa3 && chipset != 0xaa && chipset != 0xac) 289bf215546Sopenharmony_ci vp4_getpath(profile, path); 290bf215546Sopenharmony_ci else 291bf215546Sopenharmony_ci vp3_getpath(profile, path); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci if (nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client)) 294bf215546Sopenharmony_ci return 1; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci fd = open(path, O_RDONLY | O_CLOEXEC); 297bf215546Sopenharmony_ci if (fd < 0) { 298bf215546Sopenharmony_ci fprintf(stderr, "opening firmware file %s failed: %m\n", path); 299bf215546Sopenharmony_ci return 1; 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci r = read(fd, dec->fw_bo->map, 0x4000); 302bf215546Sopenharmony_ci close(fd); 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci if (r < 0) { 305bf215546Sopenharmony_ci fprintf(stderr, "reading firmware file %s failed: %m\n", path); 306bf215546Sopenharmony_ci return 1; 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci if (r == 0x4000) { 310bf215546Sopenharmony_ci fprintf(stderr, "firmware file %s too large!\n", path); 311bf215546Sopenharmony_ci return 1; 312bf215546Sopenharmony_ci } 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci if (r & 0xff) { 315bf215546Sopenharmony_ci fprintf(stderr, "firmware file %s wrong size!\n", path); 316bf215546Sopenharmony_ci return 1; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci end = dec->fw_bo->map + r - 4; 320bf215546Sopenharmony_ci endval = *end; 321bf215546Sopenharmony_ci while (endval == *end) 322bf215546Sopenharmony_ci end--; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci switch (u_reduce_video_profile(profile)) { 327bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG12: { 328bf215546Sopenharmony_ci assert((r & 0xff) == 0xe0); 329bf215546Sopenharmony_ci dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0); 330bf215546Sopenharmony_ci break; 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4: { 333bf215546Sopenharmony_ci assert((r & 0xff) == 0xe0); 334bf215546Sopenharmony_ci dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0); 335bf215546Sopenharmony_ci break; 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_VC1: { 338bf215546Sopenharmony_ci assert((r & 0xff) == 0xac); 339bf215546Sopenharmony_ci dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac); 340bf215546Sopenharmony_ci break; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4_AVC: { 343bf215546Sopenharmony_ci assert((r & 0xff) == 0x70); 344bf215546Sopenharmony_ci dec->fw_sizes = (0x370<<16) | (r - 0x370); 345bf215546Sopenharmony_ci break; 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci default: 348bf215546Sopenharmony_ci return 1; 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci munmap(dec->fw_bo->map, dec->fw_bo->size); 351bf215546Sopenharmony_ci dec->fw_bo->map = NULL; 352bf215546Sopenharmony_ci return 0; 353bf215546Sopenharmony_ci} 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_cistatic const struct nouveau_mclass 356bf215546Sopenharmony_cinouveau_decoder_msvld[] = { 357bf215546Sopenharmony_ci { G98_MSVLD, -1 }, 358bf215546Sopenharmony_ci { IGT21A_MSVLD, -1 }, 359bf215546Sopenharmony_ci { GT212_MSVLD, -1 }, 360bf215546Sopenharmony_ci { GF100_MSVLD, -1 }, 361bf215546Sopenharmony_ci { GK104_MSVLD, -1 }, 362bf215546Sopenharmony_ci {} 363bf215546Sopenharmony_ci}; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_cistatic int 366bf215546Sopenharmony_cifirmware_present(struct pipe_screen *pscreen, enum pipe_video_profile profile) 367bf215546Sopenharmony_ci{ 368bf215546Sopenharmony_ci struct nouveau_screen *screen = nouveau_screen(pscreen); 369bf215546Sopenharmony_ci int chipset = screen->device->chipset; 370bf215546Sopenharmony_ci int vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac; 371bf215546Sopenharmony_ci int vp5 = chipset >= 0xd0; 372bf215546Sopenharmony_ci int ret; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci /* For all chipsets, try to create a BSP objects. Assume that if firmware 375bf215546Sopenharmony_ci * is present for it, firmware is also present for VP/PPP */ 376bf215546Sopenharmony_ci if (!(screen->firmware_info.profiles_checked & 1)) { 377bf215546Sopenharmony_ci struct nouveau_object *channel = NULL, *bsp = NULL; 378bf215546Sopenharmony_ci struct nv04_fifo nv04_data = {.vram = 0xbeef0201, .gart = 0xbeef0202}; 379bf215546Sopenharmony_ci struct nvc0_fifo nvc0_args = {}; 380bf215546Sopenharmony_ci struct nve0_fifo nve0_args = {.engine = NVE0_FIFO_ENGINE_BSP}; 381bf215546Sopenharmony_ci void *data = NULL; 382bf215546Sopenharmony_ci int size; 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ci if (chipset < 0xc0) { 385bf215546Sopenharmony_ci data = &nv04_data; 386bf215546Sopenharmony_ci size = sizeof(nv04_data); 387bf215546Sopenharmony_ci } else if (chipset < 0xe0) { 388bf215546Sopenharmony_ci data = &nvc0_args; 389bf215546Sopenharmony_ci size = sizeof(nvc0_args); 390bf215546Sopenharmony_ci } else { 391bf215546Sopenharmony_ci data = &nve0_args; 392bf215546Sopenharmony_ci size = sizeof(nve0_args); 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci /* kepler must have its own channel, so just do this for everyone */ 396bf215546Sopenharmony_ci nouveau_object_new(&screen->device->object, 0, 397bf215546Sopenharmony_ci NOUVEAU_FIFO_CHANNEL_CLASS, 398bf215546Sopenharmony_ci data, size, &channel); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci if (channel) { 401bf215546Sopenharmony_ci ret = nouveau_object_mclass(channel, nouveau_decoder_msvld); 402bf215546Sopenharmony_ci if (ret >= 0) 403bf215546Sopenharmony_ci nouveau_object_new(channel, 0, nouveau_decoder_msvld[ret].oclass, 404bf215546Sopenharmony_ci NULL, 0, &bsp); 405bf215546Sopenharmony_ci if (bsp) 406bf215546Sopenharmony_ci screen->firmware_info.profiles_present |= 1; 407bf215546Sopenharmony_ci nouveau_object_del(&bsp); 408bf215546Sopenharmony_ci nouveau_object_del(&channel); 409bf215546Sopenharmony_ci } 410bf215546Sopenharmony_ci screen->firmware_info.profiles_checked |= 1; 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci if (!(screen->firmware_info.profiles_present & 1)) 414bf215546Sopenharmony_ci return 0; 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci /* For vp3/vp4 chipsets, make sure that the relevant firmware is present */ 417bf215546Sopenharmony_ci if (!vp5 && !(screen->firmware_info.profiles_checked & (1 << profile))) { 418bf215546Sopenharmony_ci char path[PATH_MAX]; 419bf215546Sopenharmony_ci struct stat s; 420bf215546Sopenharmony_ci if (vp3) 421bf215546Sopenharmony_ci vp3_getpath(profile, path); 422bf215546Sopenharmony_ci else 423bf215546Sopenharmony_ci vp4_getpath(profile, path); 424bf215546Sopenharmony_ci ret = stat(path, &s); 425bf215546Sopenharmony_ci if (!ret && s.st_size > 1000) 426bf215546Sopenharmony_ci screen->firmware_info.profiles_present |= (1 << profile); 427bf215546Sopenharmony_ci screen->firmware_info.profiles_checked |= (1 << profile); 428bf215546Sopenharmony_ci } 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci return vp5 || (screen->firmware_info.profiles_present & (1 << profile)); 431bf215546Sopenharmony_ci} 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ciint 434bf215546Sopenharmony_cinouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen, 435bf215546Sopenharmony_ci enum pipe_video_profile profile, 436bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 437bf215546Sopenharmony_ci enum pipe_video_cap param) 438bf215546Sopenharmony_ci{ 439bf215546Sopenharmony_ci const int chipset = nouveau_screen(pscreen)->device->chipset; 440bf215546Sopenharmony_ci /* Feature Set B = vp3, C = vp4, D = vp5 */ 441bf215546Sopenharmony_ci const bool vp3 = chipset < 0xa3 || chipset == 0xaa || chipset == 0xac; 442bf215546Sopenharmony_ci const bool vp5 = chipset >= 0xd0; 443bf215546Sopenharmony_ci enum pipe_video_format codec = u_reduce_video_profile(profile); 444bf215546Sopenharmony_ci switch (param) { 445bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTED: 446bf215546Sopenharmony_ci /* VP3 does not support MPEG4, VP4+ do. */ 447bf215546Sopenharmony_ci return entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM && 448bf215546Sopenharmony_ci profile >= PIPE_VIDEO_PROFILE_MPEG1 && 449bf215546Sopenharmony_ci profile < PIPE_VIDEO_PROFILE_HEVC_MAIN && 450bf215546Sopenharmony_ci (!vp3 || codec != PIPE_VIDEO_FORMAT_MPEG4) && 451bf215546Sopenharmony_ci firmware_present(pscreen, profile); 452bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_NPOT_TEXTURES: 453bf215546Sopenharmony_ci return 1; 454bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_WIDTH: 455bf215546Sopenharmony_ci switch (codec) { 456bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG12: 457bf215546Sopenharmony_ci return vp5 ? 4032 : 2048; 458bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4: 459bf215546Sopenharmony_ci return 2048; 460bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_VC1: 461bf215546Sopenharmony_ci return 2048; 462bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4_AVC: 463bf215546Sopenharmony_ci if (vp3) 464bf215546Sopenharmony_ci return 2032; 465bf215546Sopenharmony_ci if (vp5) 466bf215546Sopenharmony_ci return 4032; 467bf215546Sopenharmony_ci return 2048; /* vp4 */ 468bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_UNKNOWN: 469bf215546Sopenharmony_ci return vp5 ? 4032 : 2048; 470bf215546Sopenharmony_ci default: 471bf215546Sopenharmony_ci debug_printf("unknown video codec: %d\n", codec); 472bf215546Sopenharmony_ci return 0; 473bf215546Sopenharmony_ci } 474bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_HEIGHT: 475bf215546Sopenharmony_ci switch (codec) { 476bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG12: 477bf215546Sopenharmony_ci return vp5 ? 4048 : 2048; 478bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4: 479bf215546Sopenharmony_ci return 2048; 480bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_VC1: 481bf215546Sopenharmony_ci return 2048; 482bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4_AVC: 483bf215546Sopenharmony_ci if (vp3) 484bf215546Sopenharmony_ci return 2048; 485bf215546Sopenharmony_ci if (vp5) 486bf215546Sopenharmony_ci return 4080; 487bf215546Sopenharmony_ci return 2048; /* vp4 */ 488bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_UNKNOWN: 489bf215546Sopenharmony_ci return vp5 ? 4080 : 2048; 490bf215546Sopenharmony_ci default: 491bf215546Sopenharmony_ci debug_printf("unknown video codec: %d\n", codec); 492bf215546Sopenharmony_ci return 0; 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERED_FORMAT: 495bf215546Sopenharmony_ci return PIPE_FORMAT_NV12; 496bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: 497bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_PREFERS_INTERLACED: 498bf215546Sopenharmony_ci return true; 499bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: 500bf215546Sopenharmony_ci return false; 501bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_LEVEL: 502bf215546Sopenharmony_ci switch (profile) { 503bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG1: 504bf215546Sopenharmony_ci return 0; 505bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: 506bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG2_MAIN: 507bf215546Sopenharmony_ci return 3; 508bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE: 509bf215546Sopenharmony_ci return 3; 510bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE: 511bf215546Sopenharmony_ci return 5; 512bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_VC1_SIMPLE: 513bf215546Sopenharmony_ci return 1; 514bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_VC1_MAIN: 515bf215546Sopenharmony_ci return 2; 516bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_VC1_ADVANCED: 517bf215546Sopenharmony_ci return 4; 518bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: 519bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_CONSTRAINED_BASELINE: 520bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: 521bf215546Sopenharmony_ci case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: 522bf215546Sopenharmony_ci return 41; 523bf215546Sopenharmony_ci default: 524bf215546Sopenharmony_ci debug_printf("unknown video profile: %d\n", profile); 525bf215546Sopenharmony_ci return 0; 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci case PIPE_VIDEO_CAP_MAX_MACROBLOCKS: 528bf215546Sopenharmony_ci switch (codec) { 529bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG12: 530bf215546Sopenharmony_ci return vp5 ? 65536 : 8192; 531bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4: 532bf215546Sopenharmony_ci return 8192; 533bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_VC1: 534bf215546Sopenharmony_ci return 8190; 535bf215546Sopenharmony_ci case PIPE_VIDEO_FORMAT_MPEG4_AVC: 536bf215546Sopenharmony_ci if (vp3) 537bf215546Sopenharmony_ci return 8190; 538bf215546Sopenharmony_ci if (vp5) 539bf215546Sopenharmony_ci return 65536; 540bf215546Sopenharmony_ci return 8192; /* vp4 */ 541bf215546Sopenharmony_ci default: 542bf215546Sopenharmony_ci debug_printf("unknown video codec: %d\n", codec); 543bf215546Sopenharmony_ci return 0; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci default: 546bf215546Sopenharmony_ci debug_printf("unknown video param: %d\n", param); 547bf215546Sopenharmony_ci return 0; 548bf215546Sopenharmony_ci } 549bf215546Sopenharmony_ci} 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_cibool 552bf215546Sopenharmony_cinouveau_vp3_screen_video_supported(struct pipe_screen *screen, 553bf215546Sopenharmony_ci enum pipe_format format, 554bf215546Sopenharmony_ci enum pipe_video_profile profile, 555bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint) 556bf215546Sopenharmony_ci{ 557bf215546Sopenharmony_ci if (profile != PIPE_VIDEO_PROFILE_UNKNOWN) 558bf215546Sopenharmony_ci return format == PIPE_FORMAT_NV12; 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci return vl_video_buffer_is_format_supported(screen, format, profile, entrypoint); 561bf215546Sopenharmony_ci} 562