1 /* 2 * Copyright 2011-2013 Maarten Lankhorst 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #include "nvc0/nvc0_video.h" 24 #include <sys/mman.h> 25 26 #if NOUVEAU_VP3_DEBUG_FENCE 27 static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32 comm_seq, 28 struct nouveau_bo *inter_bo, unsigned slice_size) 29 { 30 unsigned i, idx = comm->pvp_cur_index & 0xf; 31 debug_printf("Status: %08x, stage: %08x\n", comm->status_vp[idx], comm->pvp_stage); 32 #if 0 33 debug_printf("Acked byte ofs: %x, bsp byte ofs: %x\n", comm->acked_byte_ofs, comm->byte_ofs); 34 debug_printf("Irq/parse indexes: %i %i\n", comm->irq_index, comm->parse_endpos_index); 35 36 for (i = 0; i != comm->irq_index; ++i) 37 debug_printf("irq[%i] = { @ %08x -> %04x }\n", i, comm->irq_pos[i], comm->irq_470[i]); 38 for (i = 0; i != comm->parse_endpos_index; ++i) 39 debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]); 40 #endif 41 debug_printf("mb_y = %u\n", comm->mb_y[idx]); 42 if (comm->status_vp[idx] <= 1) 43 return; 44 45 if ((comm->pvp_stage & 0xff) != 0xff) { 46 unsigned *map; 47 int ret = nouveau_bo_map(inter_bo, NOUVEAU_BO_RD|NOUVEAU_BO_NOBLOCK, dec->client); 48 assert(ret >= 0); 49 map = inter_bo->map; 50 for (i = 0; i < comm->byte_ofs + slice_size; i += 0x10) { 51 debug_printf("%05x: %08x %08x %08x %08x\n", i, map[i/4], map[i/4+1], map[i/4+2], map[i/4+3]); 52 } 53 munmap(inter_bo->map, inter_bo->size); 54 inter_bo->map = NULL; 55 } 56 assert((comm->pvp_stage & 0xff) == 0xff); 57 } 58 #endif 59 60 static void 61 nvc0_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target) 62 { 63 dec->refs[target->valid_ref].last_used = 0; 64 // debug_printf("Unreffed %p\n", target); 65 } 66 67 void 68 nvc0_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc, 69 struct nouveau_vp3_video_buffer *target, unsigned comm_seq, 70 unsigned caps, unsigned is_ref, 71 struct nouveau_vp3_video_buffer *refs[16]) 72 { 73 struct nouveau_pushbuf *push = dec->pushbuf[1]; 74 uint32_t bsp_addr, comm_addr, inter_addr, ucode_addr, pic_addr[17], last_addr, null_addr; 75 uint32_t slice_size, bucket_size, ring_size, i; 76 enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile); 77 struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; 78 struct nouveau_bo *inter_bo = dec->inter_bo[comm_seq & 1]; 79 u32 codec_extra = 0; 80 struct nouveau_pushbuf_refn bo_refs[] = { 81 { inter_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, 82 { dec->ref_bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, 83 { bsp_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, 84 #if NOUVEAU_VP3_DEBUG_FENCE 85 { dec->fence_bo, NOUVEAU_BO_WR | NOUVEAU_BO_GART }, 86 #endif 87 { dec->fw_bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM }, 88 }; 89 int num_refs = ARRAY_SIZE(bo_refs) - !dec->fw_bo; 90 91 if (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 92 nouveau_vp3_inter_sizes(dec, desc.h264->slice_count, &slice_size, &bucket_size, &ring_size); 93 codec_extra += 2; 94 } else 95 nouveau_vp3_inter_sizes(dec, 1, &slice_size, &bucket_size, &ring_size); 96 97 if (dec->base.max_references > 2) 98 codec_extra += 1 + (dec->base.max_references - 2); 99 100 pic_addr[16] = nouveau_vp3_video_addr(dec, target) >> 8; 101 last_addr = null_addr = nouveau_vp3_video_addr(dec, NULL) >> 8; 102 103 for (i = 0; i < dec->base.max_references; ++i) { 104 if (!refs[i]) 105 pic_addr[i] = last_addr; 106 else if (dec->refs[refs[i]->valid_ref].vidbuf == refs[i]) 107 last_addr = pic_addr[i] = nouveau_vp3_video_addr(dec, refs[i]) >> 8; 108 else 109 pic_addr[i] = null_addr; 110 } 111 if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom)) 112 nvc0_decoder_kick_ref(dec, target); 113 114 nouveau_pushbuf_space(push, 32 + codec_extra, num_refs, 0); 115 116 nouveau_pushbuf_refn(push, bo_refs, num_refs); 117 118 bsp_addr = bsp_bo->offset >> 8; 119 #if NOUVEAU_VP3_DEBUG_FENCE 120 comm_addr = (dec->fence_bo->offset + COMM_OFFSET)>>8; 121 #else 122 comm_addr = bsp_addr + (COMM_OFFSET>>8); 123 #endif 124 inter_addr = inter_bo->offset >> 8; 125 if (dec->fw_bo) 126 ucode_addr = dec->fw_bo->offset >> 8; 127 else 128 ucode_addr = 0; 129 130 BEGIN_NVC0(push, SUBC_VP(0x700), 7); 131 PUSH_DATA (push, caps); // 700 132 PUSH_DATA (push, comm_seq); // 704 133 PUSH_DATA (push, 0); // 708 fuc targets, ignored for nvc0 134 PUSH_DATA (push, dec->fw_sizes); // 70c 135 PUSH_DATA (push, bsp_addr+(VP_OFFSET>>8)); // 710 picparm_addr 136 PUSH_DATA (push, inter_addr); // 714 inter_parm 137 PUSH_DATA (push, inter_addr + slice_size + bucket_size); // 718 inter_data_ofs 138 139 if (bucket_size) { 140 uint64_t tmpimg_addr = dec->ref_bo->offset + dec->ref_stride * (dec->base.max_references+2); 141 142 BEGIN_NVC0(push, SUBC_VP(0x71c), 2); 143 PUSH_DATA (push, tmpimg_addr >> 8); // 71c 144 PUSH_DATA (push, inter_addr + slice_size); // 720 bucket_ofs 145 } 146 147 BEGIN_NVC0(push, SUBC_VP(0x724), 5); 148 PUSH_DATA (push, comm_addr); // 724 149 PUSH_DATA (push, ucode_addr); // 728 150 PUSH_DATA (push, pic_addr[16]); // 734 151 PUSH_DATA (push, pic_addr[0]); // 72c 152 PUSH_DATA (push, pic_addr[1]); // 730 153 154 if (dec->base.max_references > 2) { 155 int i; 156 157 BEGIN_NVC0(push, SUBC_VP(0x400), dec->base.max_references - 2); 158 for (i = 2; i < dec->base.max_references; ++i) { 159 assert(0x400 + (i - 2) * 4 < 0x438); 160 PUSH_DATA (push, pic_addr[i]); 161 } 162 } 163 164 if (codec == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 165 BEGIN_NVC0(push, SUBC_VP(0x438), 1); 166 PUSH_DATA (push, desc.h264->slice_count); 167 } 168 169 //debug_printf("Decoding %08lx with %08lx and %08lx\n", pic_addr[16], pic_addr[0], pic_addr[1]); 170 171 #if NOUVEAU_VP3_DEBUG_FENCE 172 BEGIN_NVC0(push, SUBC_VP(0x240), 3); 173 PUSH_DATAh(push, (dec->fence_bo->offset + 0x10)); 174 PUSH_DATA (push, (dec->fence_bo->offset + 0x10)); 175 PUSH_DATA (push, dec->fence_seq); 176 177 BEGIN_NVC0(push, SUBC_VP(0x300), 1); 178 PUSH_DATA (push, 1); 179 PUSH_KICK(push); 180 181 { 182 unsigned spin = 0; 183 do { 184 usleep(100); 185 if ((spin++ & 0xff) == 0xff) { 186 debug_printf("v%u: %u\n", dec->fence_seq, dec->fence_map[4]); 187 dump_comm_vp(dec, dec->comm, comm_seq, inter_bo, slice_size << 8); 188 } 189 } while (dec->fence_seq > dec->fence_map[4]); 190 } 191 dump_comm_vp(dec, dec->comm, comm_seq, inter_bo, slice_size << 8); 192 #else 193 BEGIN_NVC0(push, SUBC_VP(0x300), 1); 194 PUSH_DATA (push, 0); 195 PUSH_KICK (push); 196 #endif 197 } 198