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