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 <nouveau.h> 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "pipe/p_defines.h" 26bf215546Sopenharmony_ci#include "vl/vl_video_buffer.h" 27bf215546Sopenharmony_ci#include "util/u_video.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_cistruct nouveau_vp3_video_buffer { 30bf215546Sopenharmony_ci struct pipe_video_buffer base; 31bf215546Sopenharmony_ci unsigned num_planes, valid_ref; 32bf215546Sopenharmony_ci struct pipe_resource *resources[VL_NUM_COMPONENTS]; 33bf215546Sopenharmony_ci struct pipe_sampler_view *sampler_view_planes[VL_NUM_COMPONENTS]; 34bf215546Sopenharmony_ci struct pipe_sampler_view *sampler_view_components[VL_NUM_COMPONENTS]; 35bf215546Sopenharmony_ci struct pipe_surface *surfaces[VL_NUM_COMPONENTS * 2]; 36bf215546Sopenharmony_ci}; 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#define SLICE_SIZE 0x200 39bf215546Sopenharmony_ci#define VP_OFFSET 0x200 40bf215546Sopenharmony_ci#define COMM_OFFSET 0x500 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#define NOUVEAU_VP3_BSP_RESERVED_SIZE 0x700 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#define NOUVEAU_VP3_DEBUG_FENCE 0 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#if NOUVEAU_VP3_DEBUG_FENCE 47bf215546Sopenharmony_ci# define NOUVEAU_VP3_VIDEO_QDEPTH 1 48bf215546Sopenharmony_ci#else 49bf215546Sopenharmony_ci# define NOUVEAU_VP3_VIDEO_QDEPTH 2 50bf215546Sopenharmony_ci#endif 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci#define SUBC_BSP(m) dec->bsp_idx, (m) 53bf215546Sopenharmony_ci#define SUBC_VP(m) dec->vp_idx, (m) 54bf215546Sopenharmony_ci#define SUBC_PPP(m) dec->ppp_idx, (m) 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ciunion pipe_desc { 57bf215546Sopenharmony_ci struct pipe_picture_desc *base; 58bf215546Sopenharmony_ci struct pipe_mpeg12_picture_desc *mpeg12; 59bf215546Sopenharmony_ci struct pipe_mpeg4_picture_desc *mpeg4; 60bf215546Sopenharmony_ci struct pipe_vc1_picture_desc *vc1; 61bf215546Sopenharmony_ci struct pipe_h264_picture_desc *h264; 62bf215546Sopenharmony_ci}; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_cistruct nouveau_vp3_decoder { 65bf215546Sopenharmony_ci struct pipe_video_codec base; 66bf215546Sopenharmony_ci struct nouveau_client *client; 67bf215546Sopenharmony_ci struct nouveau_object *channel[3], *bsp, *vp, *ppp; 68bf215546Sopenharmony_ci struct nouveau_pushbuf *pushbuf[3]; 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci#if NOUVEAU_VP3_DEBUG_FENCE 71bf215546Sopenharmony_ci /* dump fence and comm, as needed.. */ 72bf215546Sopenharmony_ci unsigned *fence_map; 73bf215546Sopenharmony_ci struct comm *comm; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci struct nouveau_bo *fence_bo; 76bf215546Sopenharmony_ci#endif 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci struct nouveau_bo *fw_bo, *bitplane_bo; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci // array size max_references + 2, contains unpostprocessed images 81bf215546Sopenharmony_ci // added at the end of ref_bo is a tmp array 82bf215546Sopenharmony_ci // tmp is an array for h264, with each member being used for a ref frame or current 83bf215546Sopenharmony_ci // target.. size = (((mb(w)*((mb(h)+1)&~1))+3)>>2)<<8 * (max_references+1) 84bf215546Sopenharmony_ci // for other codecs, it simply seems that size = w*h is enough 85bf215546Sopenharmony_ci // unsure what it's supposed to contain.. 86bf215546Sopenharmony_ci struct nouveau_bo *ref_bo; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci struct nouveau_bo *inter_bo[2]; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci struct nouveau_bo *bsp_bo[NOUVEAU_VP3_VIDEO_QDEPTH]; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci // bo's used by each cycle: 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci // bsp_bo: contains raw bitstream data and parameters for BSP and VP. 95bf215546Sopenharmony_ci // inter_bo: contains data shared between BSP and VP 96bf215546Sopenharmony_ci // ref_bo: reference image data, used by PPP and VP 97bf215546Sopenharmony_ci // bitplane_bo: contain bitplane data (similar to ref_bo), used by BSP only 98bf215546Sopenharmony_ci // fw_bo: used by VP only. 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci // Needed amount of copies in optimal case: 101bf215546Sopenharmony_ci // 2 copies of inter_bo, VP would process the last inter_bo, while BSP is 102bf215546Sopenharmony_ci // writing out a new set. 103bf215546Sopenharmony_ci // NOUVEAU_VP3_VIDEO_QDEPTH copies of bsp_bo. We don't want to block the 104bf215546Sopenharmony_ci // pipeline ever, and give shaders a chance to run as well. 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci struct { 107bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *vidbuf; 108bf215546Sopenharmony_ci unsigned last_used; 109bf215546Sopenharmony_ci unsigned field_pic_flag : 1; 110bf215546Sopenharmony_ci unsigned decoded_top : 1; 111bf215546Sopenharmony_ci unsigned decoded_bottom : 1; 112bf215546Sopenharmony_ci unsigned decoded_first : 1; 113bf215546Sopenharmony_ci } refs[17]; 114bf215546Sopenharmony_ci unsigned fence_seq, fw_sizes, last_frame_num, tmp_stride, ref_stride; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci unsigned bsp_idx, vp_idx, ppp_idx; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci /* End of the bsp bo where new data should be appended between one begin/end 119bf215546Sopenharmony_ci * frame. 120bf215546Sopenharmony_ci */ 121bf215546Sopenharmony_ci char *bsp_ptr; 122bf215546Sopenharmony_ci}; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_cistruct comm { 125bf215546Sopenharmony_ci uint32_t bsp_cur_index; // 000 126bf215546Sopenharmony_ci uint32_t byte_ofs; // 004 127bf215546Sopenharmony_ci uint32_t status[0x10]; // 008 128bf215546Sopenharmony_ci uint32_t pos[0x10]; // 048 129bf215546Sopenharmony_ci uint8_t pad[0x100 - 0x88]; // 0a0 bool comm_encrypted 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci uint32_t pvp_cur_index; // 100 132bf215546Sopenharmony_ci uint32_t acked_byte_ofs; // 104 133bf215546Sopenharmony_ci uint32_t status_vp[0x10]; // 108 134bf215546Sopenharmony_ci uint16_t mb_y[0x10]; //148 135bf215546Sopenharmony_ci uint32_t pvp_stage; // 168 0xeeXX 136bf215546Sopenharmony_ci uint16_t parse_endpos_index; // 16c 137bf215546Sopenharmony_ci uint16_t irq_index; // 16e 138bf215546Sopenharmony_ci uint8_t irq_470[0x10]; // 170 139bf215546Sopenharmony_ci uint32_t irq_pos[0x10]; // 180 140bf215546Sopenharmony_ci uint32_t parse_endpos[0x10]; // 1c0 141bf215546Sopenharmony_ci}; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_cistatic inline uint32_t nouveau_vp3_video_align(uint32_t h) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci return ((h+0x3f)&~0x3f); 146bf215546Sopenharmony_ci}; 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_cistatic inline uint32_t mb(uint32_t coord) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci return (coord + 0xf)>>4; 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_cistatic inline uint32_t mb_half(uint32_t coord) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci return (coord + 0x1f)>>5; 156bf215546Sopenharmony_ci} 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_cistatic inline uint64_t 159bf215546Sopenharmony_cinouveau_vp3_video_addr(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target) 160bf215546Sopenharmony_ci{ 161bf215546Sopenharmony_ci uint64_t ret; 162bf215546Sopenharmony_ci if (target) 163bf215546Sopenharmony_ci ret = dec->ref_stride * target->valid_ref; 164bf215546Sopenharmony_ci else 165bf215546Sopenharmony_ci ret = dec->ref_stride * (dec->base.max_references+1); 166bf215546Sopenharmony_ci return dec->ref_bo->offset + ret; 167bf215546Sopenharmony_ci} 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_cistatic inline void 170bf215546Sopenharmony_cinouveau_vp3_ycbcr_offsets(struct nouveau_vp3_decoder *dec, uint32_t *y2, 171bf215546Sopenharmony_ci uint32_t *cbcr, uint32_t *cbcr2) 172bf215546Sopenharmony_ci{ 173bf215546Sopenharmony_ci uint32_t w = mb(dec->base.width), size; 174bf215546Sopenharmony_ci *y2 = mb_half(dec->base.height)*w; 175bf215546Sopenharmony_ci *cbcr = *y2 * 2; 176bf215546Sopenharmony_ci *cbcr2 = *cbcr + w * (nouveau_vp3_video_align(dec->base.height)>>6); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci /* The check here should never fail because it means a bug 179bf215546Sopenharmony_ci * in the code rather than a bug in hardware.. 180bf215546Sopenharmony_ci */ 181bf215546Sopenharmony_ci size = (2 * (*cbcr2 - *cbcr) + *cbcr) << 8; 182bf215546Sopenharmony_ci if (size > dec->ref_stride) { 183bf215546Sopenharmony_ci debug_printf("Overshot ref_stride (%u) with size %u and ofs (%u,%u,%u)\n", 184bf215546Sopenharmony_ci dec->ref_stride, size, *y2<<8, *cbcr<<8, *cbcr2<<8); 185bf215546Sopenharmony_ci *y2 = *cbcr = *cbcr2 = 0; 186bf215546Sopenharmony_ci assert(size <= dec->ref_stride); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic inline void 191bf215546Sopenharmony_cinouveau_vp3_inter_sizes(struct nouveau_vp3_decoder *dec, uint32_t slice_count, 192bf215546Sopenharmony_ci uint32_t *slice_size, uint32_t *bucket_size, 193bf215546Sopenharmony_ci uint32_t *ring_size) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci *slice_size = (SLICE_SIZE * slice_count)>>8; 196bf215546Sopenharmony_ci if (u_reduce_video_profile(dec->base.profile) == PIPE_VIDEO_FORMAT_MPEG12) 197bf215546Sopenharmony_ci *bucket_size = 0; 198bf215546Sopenharmony_ci else 199bf215546Sopenharmony_ci *bucket_size = mb(dec->base.width) * 3; 200bf215546Sopenharmony_ci *ring_size = (dec->inter_bo[0]->size >> 8) - *bucket_size - *slice_size; 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_cistruct pipe_video_buffer * 204bf215546Sopenharmony_cinouveau_vp3_video_buffer_create(struct pipe_context *pipe, 205bf215546Sopenharmony_ci const struct pipe_video_buffer *templat, 206bf215546Sopenharmony_ci int flags); 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_civoid 209bf215546Sopenharmony_cinouveau_vp3_decoder_init_common(struct pipe_video_codec *decoder); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ciint 212bf215546Sopenharmony_cinouveau_vp3_load_firmware(struct nouveau_vp3_decoder *dec, 213bf215546Sopenharmony_ci enum pipe_video_profile profile, 214bf215546Sopenharmony_ci unsigned chipset); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_civoid 217bf215546Sopenharmony_cinouveau_vp3_bsp_begin(struct nouveau_vp3_decoder *dec); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_civoid 220bf215546Sopenharmony_cinouveau_vp3_bsp_next(struct nouveau_vp3_decoder *dec, unsigned num_buffers, 221bf215546Sopenharmony_ci const void *const *data, const unsigned *num_bytes); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ciuint32_t 224bf215546Sopenharmony_cinouveau_vp3_bsp_end(struct nouveau_vp3_decoder *dec, union pipe_desc desc); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_civoid 227bf215546Sopenharmony_cinouveau_vp3_vp_caps(struct nouveau_vp3_decoder *dec, union pipe_desc desc, 228bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *target, unsigned comm_seq, 229bf215546Sopenharmony_ci unsigned *caps, unsigned *is_ref, 230bf215546Sopenharmony_ci struct nouveau_vp3_video_buffer *refs[16]); 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ciint 233bf215546Sopenharmony_cinouveau_vp3_screen_get_video_param(struct pipe_screen *pscreen, 234bf215546Sopenharmony_ci enum pipe_video_profile profile, 235bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint, 236bf215546Sopenharmony_ci enum pipe_video_cap param); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cibool 239bf215546Sopenharmony_cinouveau_vp3_screen_video_supported(struct pipe_screen *screen, 240bf215546Sopenharmony_ci enum pipe_format format, 241bf215546Sopenharmony_ci enum pipe_video_profile profile, 242bf215546Sopenharmony_ci enum pipe_video_entrypoint entrypoint); 243