Commit | Line | Data |
---|---|---|
107c76a4 PY |
1 | /* |
2 | * drivers/amlogic/amports/vavs.c | |
3 | * | |
4 | * Copyright (C) 2015 Amlogic, Inc. All rights reserved. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | */ | |
107c76a4 PY |
17 | #include <linux/kernel.h> |
18 | #include <linux/types.h> | |
19 | #include <linux/errno.h> | |
20 | #include <linux/interrupt.h> | |
21 | #include <linux/semaphore.h> | |
22 | #include <linux/timer.h> | |
23 | #include <linux/kfifo.h> | |
24 | #include <linux/delay.h> | |
25 | #include <linux/platform_device.h> | |
26 | #include <linux/amlogic/media/utils/amstream.h> | |
27 | #include <linux/amlogic/media/frame_sync/ptsserv.h> | |
28 | #include <linux/amlogic/media/canvas/canvas.h> | |
29 | #include <linux/amlogic/media/vfm/vframe_provider.h> | |
30 | #include <linux/amlogic/media/vfm/vframe_receiver.h> | |
31 | #include <linux/amlogic/media/vfm/vframe.h> | |
32 | #include <linux/amlogic/media/utils/vdec_reg.h> | |
d631e9c2 | 33 | #include "../../../stream_input/amports/streambuf_reg.h" |
107c76a4 PY |
34 | #include "../utils/amvdec.h" |
35 | #include <linux/amlogic/media/registers/register.h> | |
36 | #include "../../../stream_input/amports/amports_priv.h" | |
37 | #include <linux/dma-mapping.h> | |
38 | #include <linux/amlogic/media/codec_mm/codec_mm.h> | |
39 | #include <linux/slab.h> | |
40 | #include "avs_multi.h" | |
41 | #include <linux/amlogic/media/codec_mm/configs.h> | |
42 | #include "../utils/decoder_mmu_box.h" | |
43 | #include "../utils/decoder_bmmu_box.h" | |
44 | #include "../utils/firmware.h" | |
45 | #include "../../../common/chips/decoder_cpu_ver_info.h" | |
46 | #include <linux/amlogic/tee.h> | |
47 | ||
48 | #define DEBUG_MULTI_FLAG 0 | |
17a06af5 RZ |
49 | /* |
50 | #define DEBUG_WITH_SINGLE_MODE | |
51 | #define DEBUG_MULTI_WITH_AUTOMODE | |
52 | #define DEBUG_MULTI_FRAME_INS | |
53 | */ | |
54 | ||
55 | ||
56 | #define USE_DYNAMIC_BUF_NUM | |
107c76a4 | 57 | |
17a06af5 | 58 | #ifdef DEBUG_WITH_SINGLE_MODE |
107c76a4 PY |
59 | #define DRIVER_NAME "amvdec_avs" |
60 | #define MODULE_NAME "amvdec_avs" | |
17a06af5 RZ |
61 | #else |
62 | #define DRIVER_NAME "ammvdec_avs" | |
63 | #define MODULE_NAME "ammvdec_avs" | |
64 | #endif | |
107c76a4 PY |
65 | |
66 | #define MULTI_DRIVER_NAME "ammvdec_avs" | |
67 | ||
68 | #define ENABLE_USER_DATA | |
69 | ||
70 | #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ | |
71 | #define NV21 | |
72 | #endif | |
73 | ||
74 | #define USE_AVS_SEQ_INFO | |
75 | #define HANDLE_AVS_IRQ | |
76 | #define DEBUG_PTS | |
77 | ||
78 | #define CHECK_INTERVAL (HZ/100) | |
79 | ||
80 | #define I_PICTURE 0 | |
81 | #define P_PICTURE 1 | |
82 | #define B_PICTURE 2 | |
83 | ||
84 | #define LMEM_BUF_SIZE (0x500 * 2) | |
85 | ||
86 | /* #define ORI_BUFFER_START_ADDR 0x81000000 */ | |
87 | #define ORI_BUFFER_START_ADDR 0x80000000 | |
88 | ||
89 | #define INTERLACE_FLAG 0x80 | |
90 | #define TOP_FIELD_FIRST_FLAG 0x40 | |
91 | ||
92 | /* protocol registers */ | |
93 | #define AVS_PIC_RATIO AV_SCRATCH_0 | |
94 | #define AVS_PIC_WIDTH AV_SCRATCH_1 | |
95 | #define AVS_PIC_HEIGHT AV_SCRATCH_2 | |
96 | #define AVS_FRAME_RATE AV_SCRATCH_3 | |
97 | ||
98 | /*#define AVS_ERROR_COUNT AV_SCRATCH_6*/ | |
99 | #define AVS_SOS_COUNT AV_SCRATCH_7 | |
100 | #define AVS_BUFFERIN AV_SCRATCH_8 | |
101 | #define AVS_BUFFEROUT AV_SCRATCH_9 | |
102 | #define AVS_REPEAT_COUNT AV_SCRATCH_A | |
103 | #define AVS_TIME_STAMP AV_SCRATCH_B | |
104 | #define AVS_OFFSET_REG AV_SCRATCH_C | |
105 | #define MEM_OFFSET_REG AV_SCRATCH_F | |
106 | #define AVS_ERROR_RECOVERY_MODE AV_SCRATCH_G | |
17a06af5 | 107 | #define DECODE_PIC_COUNT AV_SCRATCH_G |
107c76a4 PY |
108 | |
109 | #define DECODE_MODE AV_SCRATCH_6 | |
110 | #define DECODE_MODE_SINGLE 0x0 | |
111 | #define DECODE_MODE_MULTI_FRAMEBASE 0x1 | |
112 | #define DECODE_MODE_MULTI_STREAMBASE 0x2 | |
17a06af5 | 113 | #define DECODE_MODE_MULTI_STREAMBASE_CONT 0x3 |
107c76a4 PY |
114 | |
115 | #define DECODE_STATUS AV_SCRATCH_H | |
116 | #define DECODE_STATUS_PIC_DONE 0x1 | |
117 | #define DECODE_STATUS_DECODE_BUF_EMPTY 0x2 | |
118 | #define DECODE_STATUS_SEARCH_BUF_EMPTY 0x3 | |
17a06af5 | 119 | #define DECODE_STATUS_SKIP_PIC_DONE 0x4 |
107c76a4 PY |
120 | #define DECODE_SEARCH_HEAD 0xff |
121 | ||
122 | #define DECODE_STOP_POS AV_SCRATCH_J | |
123 | ||
124 | #define DECODE_LMEM_BUF_ADR AV_SCRATCH_I | |
125 | ||
17a06af5 RZ |
126 | #define DECODE_CFG AV_SCRATCH_K |
127 | ||
1f676bcb PY |
128 | |
129 | ||
130 | ||
17a06af5 | 131 | #define VF_POOL_SIZE 64 |
107c76a4 PY |
132 | #define PUT_INTERVAL (HZ/100) |
133 | ||
134 | #if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/ | |
135 | #define INT_AMVENCODER INT_DOS_MAILBOX_1 | |
136 | #else | |
137 | /* #define AMVENC_DEV_VERSION "AML-MT" */ | |
138 | #define INT_AMVENCODER INT_MAILBOX_1A | |
139 | #endif | |
140 | ||
17a06af5 RZ |
141 | #ifdef USE_DYNAMIC_BUF_NUM |
142 | static unsigned int buf_spec_reg[] = { | |
143 | AV_SCRATCH_0, | |
144 | AV_SCRATCH_1, | |
145 | AV_SCRATCH_2, | |
146 | AV_SCRATCH_3, | |
147 | AV_SCRATCH_7, /*AVS_SOS_COUNT*/ | |
148 | AV_SCRATCH_D, /*DEBUG_REG2*/ | |
149 | AV_SCRATCH_E, /*DEBUG_REG1*/ | |
46448536 | 150 | AV_SCRATCH_M /*user_data_poc_number*/ |
17a06af5 RZ |
151 | }; |
152 | #endif | |
107c76a4 | 153 | |
1f676bcb PY |
154 | #define DEBUG_REG1 AV_SCRATCH_E |
155 | #define DEBUG_REG2 AV_SCRATCH_D | |
156 | ||
157 | ||
107c76a4 PY |
158 | static void check_timer_func(unsigned long arg); |
159 | static void vavs_work(struct work_struct *work); | |
160 | ||
161 | #define DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE 0x0001 | |
162 | static u32 dec_control = DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE; | |
163 | ||
164 | ||
165 | #define VPP_VD1_POSTBLEND (1 << 10) | |
166 | ||
167 | static int debug; | |
107c76a4 PY |
168 | static unsigned int debug_mask = 0xff; |
169 | ||
170 | /*for debug*/ | |
171 | /* | |
172 | udebug_flag: | |
173 | bit 0, enable ucode print | |
17a06af5 RZ |
174 | bit 1, enable ucode more print |
175 | bit 3, enable ucdode detail print | |
107c76a4 PY |
176 | bit [31:16] not 0, pos to dump lmem |
177 | bit 2, pop bits to lmem | |
178 | bit [11:8], pre-pop bits for alignment (when bit 2 is 1) | |
17a06af5 RZ |
179 | |
180 | avs only: | |
181 | bit [8], disable empty muitl-instance handling | |
182 | bit [9], enable writting of VC1_CONTROL_REG in ucode | |
107c76a4 PY |
183 | */ |
184 | static u32 udebug_flag; | |
185 | /* | |
186 | when udebug_flag[1:0] is not 0 | |
187 | udebug_pause_pos not 0, | |
188 | pause position | |
189 | */ | |
190 | static u32 udebug_pause_pos; | |
191 | /* | |
192 | when udebug_flag[1:0] is not 0 | |
193 | and udebug_pause_pos is not 0, | |
194 | pause only when DEBUG_REG2 is equal to this val | |
195 | */ | |
196 | static u32 udebug_pause_val; | |
197 | ||
198 | static u32 udebug_pause_decode_idx; | |
199 | ||
17a06af5 RZ |
200 | static u32 udebug_pause_ins_id; |
201 | ||
107c76a4 PY |
202 | static u32 force_fps; |
203 | ||
17a06af5 RZ |
204 | #ifdef DEBUG_MULTI_FRAME_INS |
205 | static u32 delay; | |
206 | #endif | |
207 | ||
107c76a4 PY |
208 | static u32 step; |
209 | ||
17a06af5 RZ |
210 | static u32 start_decoding_delay; |
211 | ||
107c76a4 PY |
212 | #define AVS_DEV_NUM 9 |
213 | static unsigned int max_decode_instance_num = AVS_DEV_NUM; | |
214 | static unsigned int max_process_time[AVS_DEV_NUM]; | |
215 | static unsigned int max_get_frame_interval[AVS_DEV_NUM]; | |
17a06af5 RZ |
216 | static unsigned int run_count[AVS_DEV_NUM]; |
217 | static unsigned int ins_udebug_flag[AVS_DEV_NUM]; | |
218 | #ifdef DEBUG_MULTI_FRAME_INS | |
219 | static unsigned int max_run_count[AVS_DEV_NUM]; | |
220 | #endif | |
221 | /* | |
222 | error_handle_policy: | |
223 | */ | |
224 | static unsigned int error_handle_policy = 3; | |
225 | ||
226 | static u32 again_threshold = 0; /*0x40;*/ | |
107c76a4 | 227 | |
17a06af5 | 228 | static unsigned int decode_timeout_val = 200; |
107c76a4 PY |
229 | static unsigned int start_decode_buf_level = 0x8000; |
230 | ||
231 | /******************************** | |
232 | firmware_sel | |
233 | 0: use avsp_trans long cabac ucode; | |
234 | 1: not use avsp_trans long cabac ucode | |
235 | in ucode: | |
236 | #define USE_EXT_BUFFER_ASSIGNMENT | |
237 | #undef USE_DYNAMIC_BUF_NUM | |
238 | ********************************/ | |
239 | static int firmware_sel; | |
240 | static int disable_longcabac_trans = 1; | |
b06eadf9 | 241 | static int pre_decode_buf_level = 0x800; |
107c76a4 PY |
242 | |
243 | ||
107c76a4 PY |
244 | static struct vframe_s *vavs_vf_peek(void *); |
245 | static struct vframe_s *vavs_vf_get(void *); | |
246 | static void vavs_vf_put(struct vframe_s *, void *); | |
247 | static int vavs_vf_states(struct vframe_states *states, void *); | |
248 | static int vavs_event_cb(int type, void *data, void *private_data); | |
249 | ||
250 | static const char vavs_dec_id[] = "vavs-dev"; | |
251 | ||
252 | #define PROVIDER_NAME "decoder.avs" | |
253 | static DEFINE_SPINLOCK(lock); | |
254 | static DEFINE_MUTEX(vavs_mutex); | |
255 | ||
256 | static const struct vframe_operations_s vavs_vf_provider = { | |
257 | .peek = vavs_vf_peek, | |
258 | .get = vavs_vf_get, | |
259 | .put = vavs_vf_put, | |
260 | .event_cb = vavs_event_cb, | |
261 | .vf_states = vavs_vf_states, | |
262 | }; | |
263 | /* | |
264 | static void *mm_blk_handle; | |
265 | */ | |
266 | static struct vframe_provider_s vavs_vf_prov; | |
267 | ||
268 | #define VF_BUF_NUM_MAX 16 | |
17a06af5 RZ |
269 | #ifdef DEBUG_MULTI_FRAME_INS |
270 | #define WORKSPACE_SIZE (16 * SZ_1M) | |
271 | #else | |
107c76a4 | 272 | #define WORKSPACE_SIZE (4 * SZ_1M) |
17a06af5 | 273 | #endif |
107c76a4 PY |
274 | #ifdef AVSP_LONG_CABAC |
275 | #define MAX_BMMU_BUFFER_NUM (VF_BUF_NUM_MAX + 2) | |
276 | #define WORKSPACE_SIZE_A (MAX_CODED_FRAME_SIZE + LOCAL_HEAP_SIZE) | |
277 | #else | |
278 | #define MAX_BMMU_BUFFER_NUM (VF_BUF_NUM_MAX + 1) | |
279 | #endif | |
280 | ||
281 | #define RV_AI_BUFF_START_ADDR 0x01a00000 | |
282 | #define LONG_CABAC_RV_AI_BUFF_START_ADDR 0x00000000 | |
283 | ||
17a06af5 RZ |
284 | /* 4 buffers not enough for multi inc*/ |
285 | static u32 vf_buf_num = 8; | |
107c76a4 PY |
286 | /*static u32 vf_buf_num_used;*/ |
287 | static u32 canvas_base = 128; | |
288 | #ifdef NV21 | |
bc26b20a | 289 | static int canvas_num = 2; /*NV21*/ |
107c76a4 | 290 | #else |
bc26b20a | 291 | static int canvas_num = 3; |
107c76a4 PY |
292 | #endif |
293 | ||
294 | #if 0 | |
295 | static struct vframe_s vfpool[VF_POOL_SIZE]; | |
296 | /*static struct vframe_s vfpool2[VF_POOL_SIZE];*/ | |
297 | static struct vframe_s *cur_vfpool; | |
298 | static unsigned char recover_flag; | |
299 | static s32 vfbuf_use[VF_BUF_NUM_MAX]; | |
300 | static u32 saved_resolution; | |
301 | static u32 frame_width, frame_height, frame_dur, frame_prog; | |
302 | static struct timer_list recycle_timer; | |
303 | static u32 stat; | |
304 | #endif | |
305 | static u32 buf_size = 32 * 1024 * 1024; | |
306 | #if 0 | |
307 | static u32 buf_offset; | |
308 | static u32 avi_flag; | |
309 | static u32 vavs_ratio; | |
310 | static u32 pic_type; | |
311 | #endif | |
312 | static u32 pts_by_offset = 1; | |
313 | #if 0 | |
314 | static u32 total_frame; | |
315 | static u32 next_pts; | |
316 | static unsigned char throw_pb_flag; | |
317 | #ifdef DEBUG_PTS | |
318 | static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed; | |
319 | #endif | |
320 | #endif | |
321 | static u32 radr, rval; | |
322 | static u32 dbg_cmd; | |
323 | #if 0 | |
324 | static struct dec_sysinfo vavs_amstream_dec_info; | |
325 | static struct vdec_info *gvs; | |
326 | static u32 fr_hint_status; | |
327 | static struct work_struct notify_work; | |
328 | static struct work_struct set_clk_work; | |
329 | static bool is_reset; | |
330 | #endif | |
331 | /*static struct vdec_s *vdec;*/ | |
332 | ||
333 | #ifdef AVSP_LONG_CABAC | |
334 | static struct work_struct long_cabac_wd_work; | |
335 | void *es_write_addr_virt; | |
336 | dma_addr_t es_write_addr_phy; | |
337 | ||
338 | void *bitstream_read_tmp; | |
339 | dma_addr_t bitstream_read_tmp_phy; | |
340 | void *avsp_heap_adr; | |
341 | static uint long_cabac_busy; | |
342 | #endif | |
343 | ||
344 | #if 0 | |
345 | #ifdef ENABLE_USER_DATA | |
346 | static void *user_data_buffer; | |
347 | static dma_addr_t user_data_buffer_phys; | |
348 | #endif | |
349 | static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); | |
350 | static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); | |
351 | static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); | |
352 | #endif | |
353 | static inline u32 index2canvas(u32 index) | |
354 | { | |
355 | const u32 canvas_tab[VF_BUF_NUM_MAX] = { | |
356 | 0x010100, 0x030302, 0x050504, 0x070706, | |
357 | 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e, | |
358 | 0x111110, 0x131312, 0x151514, 0x171716, | |
359 | 0x191918, 0x1b1b1a, 0x1d1d1c, 0x1f1f1e, | |
360 | }; | |
361 | const u32 canvas_tab_3[4] = { | |
362 | 0x010100, 0x040403, 0x070706, 0x0a0a09 | |
363 | }; | |
364 | ||
365 | if (canvas_num == 2) | |
366 | return canvas_tab[index] + (canvas_base << 16) | |
367 | + (canvas_base << 8) + canvas_base; | |
368 | ||
369 | return canvas_tab_3[index] + (canvas_base << 16) | |
370 | + (canvas_base << 8) + canvas_base; | |
371 | } | |
372 | ||
373 | static const u32 frame_rate_tab[16] = { | |
374 | 96000 / 30, /* forbidden */ | |
375 | 96000000 / 23976, /* 24000/1001 (23.967) */ | |
376 | 96000 / 24, | |
377 | 96000 / 25, | |
378 | 9600000 / 2997, /* 30000/1001 (29.97) */ | |
379 | 96000 / 30, | |
380 | 96000 / 50, | |
381 | 9600000 / 5994, /* 60000/1001 (59.94) */ | |
382 | 96000 / 60, | |
383 | /* > 8 reserved, use 24 */ | |
384 | 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, | |
385 | 96000 / 24, 96000 / 24, 96000 / 24 | |
386 | }; | |
387 | ||
388 | #define DECODE_BUFFER_NUM_MAX VF_BUF_NUM_MAX | |
17a06af5 RZ |
389 | #define PIC_PTS_NUM 64 |
390 | struct buf_pool_s { | |
391 | unsigned detached; | |
392 | struct vframe_s vf; | |
393 | }; | |
394 | ||
395 | #define buf_of_vf(vf) container_of(vf, struct buf_pool_s, vf) | |
396 | ||
397 | struct pic_pts_s { | |
398 | u32 pts; | |
399 | u64 pts64; | |
400 | u64 timestamp; | |
401 | unsigned short decode_pic_count; | |
402 | }; | |
403 | ||
107c76a4 PY |
404 | struct vdec_avs_hw_s { |
405 | spinlock_t lock; | |
406 | unsigned char m_ins_flag; | |
407 | struct platform_device *platform_dev; | |
408 | DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); | |
409 | DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); | |
410 | DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); | |
17a06af5 | 411 | struct buf_pool_s vfpool[VF_POOL_SIZE]; |
107c76a4 PY |
412 | s32 vfbuf_use[VF_BUF_NUM_MAX]; |
413 | unsigned char again_flag; | |
414 | unsigned char recover_flag; | |
415 | u32 frame_width; | |
416 | u32 frame_height; | |
417 | u32 frame_dur; | |
418 | u32 frame_prog; | |
419 | u32 saved_resolution; | |
420 | u32 avi_flag; | |
421 | u32 vavs_ratio; | |
422 | u32 pic_type; | |
423 | ||
424 | u32 vf_buf_num_used; | |
425 | u32 total_frame; | |
426 | u32 next_pts; | |
427 | unsigned char throw_pb_flag; | |
17a06af5 RZ |
428 | struct pic_pts_s pic_pts[PIC_PTS_NUM]; |
429 | int pic_pts_wr_pos; | |
430 | ||
107c76a4 PY |
431 | #ifdef DEBUG_PTS |
432 | u32 pts_hit; | |
433 | u32 pts_missed; | |
434 | u32 pts_i_hit; | |
435 | u32 pts_i_missed; | |
436 | #endif | |
437 | #ifdef ENABLE_USER_DATA | |
438 | struct work_struct userdata_push_work; | |
439 | void *user_data_buffer; | |
440 | dma_addr_t user_data_buffer_phys; | |
441 | #endif | |
46448536 PY |
442 | dma_addr_t lmem_addr; |
443 | ulong lmem_phy_addr; | |
107c76a4 PY |
444 | |
445 | u32 buf_offset; | |
446 | ||
447 | struct dec_sysinfo vavs_amstream_dec_info; | |
448 | struct vdec_info *gvs; | |
449 | u32 fr_hint_status; | |
450 | struct work_struct set_clk_work; | |
451 | bool is_reset; | |
452 | ||
453 | /*debug*/ | |
454 | u32 ucode_pause_pos; | |
455 | /**/ | |
456 | u32 decode_pic_count; | |
457 | u8 reset_decode_flag; | |
458 | u32 display_frame_count; | |
459 | u32 buf_status; | |
17a06af5 | 460 | u32 pre_parser_wr_ptr; |
107c76a4 PY |
461 | /* |
462 | buffer_status &= ~buf_recycle_status | |
463 | */ | |
464 | u32 buf_recycle_status; | |
465 | u32 seqinfo; | |
466 | u32 ctx_valid; | |
467 | u32 dec_control; | |
468 | void *mm_blk_handle; | |
469 | struct vframe_chunk_s *chunk; | |
470 | u32 stat; | |
471 | u8 init_flag; | |
472 | unsigned long buf_start; | |
473 | u32 buf_size; | |
474 | ||
475 | u32 reg_scratch_0; | |
476 | u32 reg_scratch_1; | |
477 | u32 reg_scratch_2; | |
478 | u32 reg_scratch_3; | |
479 | u32 reg_scratch_4; | |
480 | u32 reg_scratch_5; | |
481 | u32 reg_scratch_6; | |
482 | u32 reg_scratch_7; | |
483 | u32 reg_scratch_8; | |
484 | u32 reg_scratch_9; | |
485 | u32 reg_scratch_A; | |
486 | u32 reg_scratch_B; | |
487 | u32 reg_scratch_C; | |
488 | u32 reg_scratch_D; | |
489 | u32 reg_scratch_E; | |
490 | u32 reg_scratch_F; | |
491 | u32 reg_scratch_G; | |
492 | u32 reg_scratch_H; | |
493 | u32 reg_scratch_I; | |
494 | u32 reg_mb_width; | |
495 | u32 reg_viff_bit_cnt; | |
496 | u32 reg_canvas_addr; | |
497 | u32 reg_dbkr_canvas_addr; | |
498 | u32 reg_dbkw_canvas_addr; | |
499 | u32 reg_anc2_canvas_addr; | |
500 | u32 reg_anc0_canvas_addr; | |
501 | u32 reg_anc1_canvas_addr; | |
17a06af5 RZ |
502 | u32 reg_anc3_canvas_addr; |
503 | u32 reg_anc4_canvas_addr; | |
504 | u32 reg_anc5_canvas_addr; | |
107c76a4 PY |
505 | u32 slice_ver_pos_pic_type; |
506 | u32 vc1_control_reg; | |
507 | u32 avs_co_mb_wr_addr; | |
508 | u32 slice_start_byte_01; | |
509 | u32 slice_start_byte_23; | |
510 | u32 vcop_ctrl_reg; | |
511 | u32 iqidct_control; | |
512 | u32 rv_ai_mb_count; | |
513 | u32 slice_qp; | |
514 | u32 dc_scaler; | |
515 | u32 avsp_iq_wq_param_01; | |
516 | u32 avsp_iq_wq_param_23; | |
517 | u32 avsp_iq_wq_param_45; | |
518 | u32 avs_co_mb_rd_addr; | |
519 | u32 dblk_mb_wid_height; | |
520 | u32 mc_pic_w_h; | |
521 | u32 avs_co_mb_rw_ctl; | |
522 | u32 vld_decode_control; | |
523 | ||
524 | struct timer_list check_timer; | |
525 | u32 decode_timeout_count; | |
526 | unsigned long int start_process_time; | |
527 | u32 last_vld_level; | |
528 | u32 eos; | |
529 | u32 canvas_spec[DECODE_BUFFER_NUM_MAX]; | |
530 | struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2]; | |
531 | ||
532 | s32 refs[2]; | |
533 | int dec_result; | |
534 | struct timer_list recycle_timer; | |
535 | struct work_struct work; | |
536 | struct work_struct notify_work; | |
537 | atomic_t error_handler_run; | |
538 | struct work_struct fatal_error_wd_work; | |
539 | void (*vdec_cb)(struct vdec_s *, void *); | |
540 | void *vdec_cb_arg; | |
541 | /* for error handling */ | |
107c76a4 PY |
542 | u32 run_count; |
543 | u32 not_run_ready; | |
544 | u32 input_empty; | |
545 | u32 prepare_num; | |
546 | u32 put_num; | |
547 | u32 peek_num; | |
548 | u32 get_num; | |
549 | u32 drop_frame_count; | |
550 | u32 buffer_not_ready; | |
551 | int frameinfo_enable; | |
552 | struct firmware_s *fw; | |
17a06af5 RZ |
553 | u32 old_udebug_flag; |
554 | u32 decode_status_skip_pic_done_flag; | |
555 | u32 decode_decode_cont_start_code; | |
107c76a4 PY |
556 | }; |
557 | ||
558 | static void reset_process_time(struct vdec_avs_hw_s *hw); | |
559 | static void start_process_time(struct vdec_avs_hw_s *hw); | |
560 | static void vavs_save_regs(struct vdec_avs_hw_s *hw); | |
561 | ||
562 | struct vdec_avs_hw_s *ghw; | |
563 | ||
564 | #define MULTI_INSTANCE_PROVIDER_NAME "vdec.avs" | |
565 | ||
566 | #define DEC_RESULT_NONE 0 | |
567 | #define DEC_RESULT_DONE 1 | |
568 | #define DEC_RESULT_AGAIN 2 | |
569 | #define DEC_RESULT_ERROR 3 | |
570 | #define DEC_RESULT_FORCE_EXIT 4 | |
571 | #define DEC_RESULT_EOS 5 | |
572 | #define DEC_RESULT_GET_DATA 6 | |
573 | #define DEC_RESULT_GET_DATA_RETRY 7 | |
574 | #define DEC_RESULT_USERDATA 8 | |
575 | ||
17a06af5 | 576 | #define DECODE_ID(hw) (hw->m_ins_flag? hw_to_vdec(hw)->id : 0) |
107c76a4 PY |
577 | |
578 | #define PRINT_FLAG_ERROR 0x0 | |
579 | #define PRINT_FLAG_RUN_FLOW 0X0001 | |
580 | #define PRINT_FLAG_DECODING 0x0002 | |
17a06af5 | 581 | #define PRINT_FLAG_PTS 0x0004 |
107c76a4 PY |
582 | #define PRINT_FLAG_VFRAME_DETAIL 0x0010 |
583 | #define PRINT_FLAG_VLD_DETAIL 0x0020 | |
584 | #define PRINT_FLAG_DEC_DETAIL 0x0040 | |
585 | #define PRINT_FLAG_BUFFER_DETAIL 0x0080 | |
586 | #define PRINT_FLAG_FORCE_DONE 0x0100 | |
587 | #define PRINT_FLAG_COUNTER 0X0200 | |
588 | #define PRINT_FRAMEBASE_DATA 0x0400 | |
589 | #define PRINT_FLAG_PARA_DATA 0x1000 | |
590 | #define DEBUG_FLAG_PREPARE_MORE_INPUT 0x2000 | |
17a06af5 | 591 | #define DEBUG_FLAG_PRINT_REG 0x4000 |
107c76a4 PY |
592 | #define DEBUG_FLAG_DISABLE_TIMEOUT 0x10000 |
593 | #define DEBUG_WAIT_DECODE_DONE_WHEN_STOP 0x20000 | |
17a06af5 RZ |
594 | #define DEBUG_PIC_DONE_WHEN_UCODE_PAUSE 0x40000 |
595 | ||
596 | ||
597 | #undef DEBUG_REG | |
598 | #ifdef DEBUG_REG | |
599 | static void WRITE_VREG_DBG2(unsigned adr, unsigned val) | |
600 | { | |
601 | if (debug & DEBUG_FLAG_PRINT_REG) | |
602 | pr_info("%s(%x, %x)\n", __func__, adr, val); | |
603 | if (adr != 0) | |
604 | WRITE_VREG(adr, val); | |
605 | } | |
606 | ||
607 | #undef WRITE_VREG | |
608 | #define WRITE_VREG WRITE_VREG_DBG2 | |
609 | #endif | |
107c76a4 PY |
610 | |
611 | #undef pr_info | |
612 | #define pr_info printk | |
613 | static int debug_print(struct vdec_avs_hw_s *hw, | |
614 | int flag, const char *fmt, ...) | |
615 | { | |
616 | #define AVS_PRINT_BUF 256 | |
617 | unsigned char buf[AVS_PRINT_BUF]; | |
618 | int len = 0; | |
5c405a1b | 619 | int index = 0; |
620 | if (hw) | |
621 | index = hw->m_ins_flag ? DECODE_ID(hw) : 0; | |
107c76a4 PY |
622 | if (hw == NULL || |
623 | (flag == 0) || | |
624 | ((debug_mask & | |
625 | (1 << index)) | |
626 | && (debug & flag))) { | |
627 | va_list args; | |
628 | ||
629 | va_start(args, fmt); | |
630 | if (hw) | |
631 | len = sprintf(buf, "[%d]", index); | |
632 | vsnprintf(buf + len, AVS_PRINT_BUF - len, fmt, args); | |
17a06af5 | 633 | pr_info("%s", buf); |
107c76a4 PY |
634 | va_end(args); |
635 | } | |
636 | return 0; | |
637 | } | |
638 | ||
639 | static int debug_print_cont(struct vdec_avs_hw_s *hw, | |
640 | int flag, const char *fmt, ...) | |
641 | { | |
642 | unsigned char buf[AVS_PRINT_BUF]; | |
643 | int len = 0; | |
5c405a1b | 644 | int index = 0; |
645 | if (hw) | |
646 | index = hw->m_ins_flag ? DECODE_ID(hw) : 0; | |
107c76a4 PY |
647 | if (hw == NULL || |
648 | (flag == 0) || | |
649 | ((debug_mask & | |
650 | (1 << index)) | |
651 | && (debug & flag))) { | |
652 | va_list args; | |
653 | ||
654 | va_start(args, fmt); | |
655 | vsnprintf(buf + len, AVS_PRINT_BUF - len, fmt, args); | |
656 | pr_info("%s", buf); | |
657 | va_end(args); | |
658 | } | |
659 | return 0; | |
660 | } | |
661 | ||
17a06af5 RZ |
662 | static void avs_pts_check_in(struct vdec_avs_hw_s *hw, |
663 | unsigned short decode_pic_count, struct vframe_chunk_s *chunk) | |
664 | { | |
665 | if (chunk) | |
666 | debug_print(hw, PRINT_FLAG_PTS, | |
667 | "%s %d (wr pos %d), pts %d pts64 %ld timestamp %ld\n", | |
668 | __func__, decode_pic_count, hw->pic_pts_wr_pos, | |
669 | chunk->pts, (u64)(chunk->pts64), (u64)(chunk->timestamp)); | |
670 | else | |
671 | debug_print(hw, PRINT_FLAG_PTS, | |
672 | "%s %d, chunk is null\n", | |
673 | __func__, decode_pic_count); | |
674 | ||
675 | if (chunk) { | |
676 | hw->pic_pts[hw->pic_pts_wr_pos].pts = chunk->pts; | |
677 | hw->pic_pts[hw->pic_pts_wr_pos].pts64 = chunk->pts64; | |
678 | hw->pic_pts[hw->pic_pts_wr_pos].timestamp = chunk->timestamp; | |
679 | } else { | |
680 | hw->pic_pts[hw->pic_pts_wr_pos].pts = 0; | |
681 | hw->pic_pts[hw->pic_pts_wr_pos].pts64 = 0; | |
682 | hw->pic_pts[hw->pic_pts_wr_pos].timestamp = 0; | |
683 | } | |
684 | hw->pic_pts[hw->pic_pts_wr_pos].decode_pic_count | |
685 | = decode_pic_count; | |
686 | hw->pic_pts_wr_pos++; | |
687 | if (hw->pic_pts_wr_pos >= PIC_PTS_NUM) | |
688 | hw->pic_pts_wr_pos = 0; | |
689 | return; | |
690 | } | |
691 | ||
692 | static void clear_pts_buf(struct vdec_avs_hw_s *hw) | |
693 | { | |
694 | int i; | |
695 | debug_print(hw, PRINT_FLAG_PTS, | |
696 | "%s\n", __func__); | |
697 | hw->pic_pts_wr_pos = 0; | |
698 | for (i = 0; i < PIC_PTS_NUM; i++) { | |
699 | hw->pic_pts[hw->pic_pts_wr_pos].pts = 0; | |
700 | hw->pic_pts[hw->pic_pts_wr_pos].pts64 = 0; | |
701 | hw->pic_pts[hw->pic_pts_wr_pos].timestamp = 0; | |
702 | hw->pic_pts[hw->pic_pts_wr_pos].decode_pic_count = 0; | |
703 | } | |
704 | } | |
705 | ||
706 | static int set_vframe_pts(struct vdec_avs_hw_s *hw, | |
707 | unsigned short decode_pic_count, struct vframe_s *vf) | |
708 | { | |
709 | int i; | |
710 | int ret = -1; | |
711 | for (i = 0; i < PIC_PTS_NUM; i++) { | |
712 | if (hw->pic_pts[i].decode_pic_count == decode_pic_count) { | |
713 | vf->pts = hw->pic_pts[i].pts; | |
714 | vf->pts_us64 = hw->pic_pts[i].pts64; | |
715 | vf->timestamp = hw->pic_pts[i].timestamp; | |
716 | ret = 0; | |
717 | debug_print(hw, PRINT_FLAG_PTS, | |
718 | "%s %d (rd pos %d), pts %d pts64 %ld timestamp %ld\n", | |
719 | __func__, decode_pic_count, i, | |
720 | vf->pts, vf->pts_us64, vf->timestamp); | |
721 | ||
722 | break; | |
723 | } | |
724 | } | |
725 | return ret; | |
726 | } | |
727 | ||
728 | static void avs_vf_notify_receiver(struct vdec_avs_hw_s *hw, | |
729 | const char *provider_name, int event_type, void *data) | |
730 | { | |
731 | if (hw->m_ins_flag) | |
732 | vf_notify_receiver(hw_to_vdec(hw)->vf_provider_name, | |
733 | event_type, data); | |
734 | else | |
735 | vf_notify_receiver(provider_name, event_type, data); | |
736 | } | |
737 | ||
107c76a4 PY |
738 | static void set_frame_info(struct vdec_avs_hw_s *hw, struct vframe_s *vf, |
739 | unsigned int *duration) | |
740 | { | |
741 | int ar = 0; | |
742 | ||
743 | unsigned int pixel_ratio = READ_VREG(AVS_PIC_RATIO); | |
744 | hw->prepare_num++; | |
745 | #ifndef USE_AVS_SEQ_INFO | |
746 | if (hw->vavs_amstream_dec_info.width > 0 | |
747 | && hw->vavs_amstream_dec_info.height > 0) { | |
748 | vf->width = hw->vavs_amstream_dec_info.width; | |
749 | vf->height = hw->vavs_amstream_dec_info.height; | |
750 | } else | |
751 | #endif | |
752 | { | |
753 | vf->width = READ_VREG(AVS_PIC_WIDTH); | |
754 | vf->height = READ_VREG(AVS_PIC_HEIGHT); | |
755 | hw->frame_width = vf->width; | |
756 | hw->frame_height = vf->height; | |
757 | /* pr_info("%s: (%d,%d)\n", __func__,vf->width, vf->height);*/ | |
758 | } | |
759 | ||
760 | #ifndef USE_AVS_SEQ_INFO | |
761 | if (hw->vavs_amstream_dec_info.rate > 0) | |
762 | *duration = hw->vavs_amstream_dec_info.rate; | |
763 | else | |
764 | #endif | |
765 | { | |
766 | *duration = frame_rate_tab[READ_VREG(AVS_FRAME_RATE) & 0xf]; | |
767 | /* pr_info("%s: duration = %d\n", __func__, *duration); */ | |
768 | hw->frame_dur = *duration; | |
769 | schedule_work(&hw->notify_work); | |
770 | } | |
771 | ||
772 | if (hw->vavs_ratio == 0) { | |
773 | /* always stretch to 16:9 */ | |
774 | vf->ratio_control |= (0x90 << | |
775 | DISP_RATIO_ASPECT_RATIO_BIT); | |
776 | } else { | |
777 | switch (pixel_ratio) { | |
778 | case 1: | |
779 | ar = (vf->height * hw->vavs_ratio) / vf->width; | |
780 | break; | |
781 | case 2: | |
782 | ar = (vf->height * 3 * hw->vavs_ratio) / (vf->width * 4); | |
783 | break; | |
784 | case 3: | |
785 | ar = (vf->height * 9 * hw->vavs_ratio) / (vf->width * 16); | |
786 | break; | |
787 | case 4: | |
788 | ar = (vf->height * 100 * hw->vavs_ratio) / (vf->width * | |
789 | 221); | |
790 | break; | |
791 | default: | |
792 | ar = (vf->height * hw->vavs_ratio) / vf->width; | |
793 | break; | |
794 | } | |
795 | } | |
796 | ||
797 | ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX); | |
798 | ||
799 | vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT); | |
800 | /*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO; */ | |
801 | ||
802 | vf->flag = 0; | |
17a06af5 RZ |
803 | buf_of_vf(vf)->detached = 0; |
804 | ||
107c76a4 PY |
805 | } |
806 | ||
807 | #ifdef ENABLE_USER_DATA | |
808 | ||
809 | /*static struct work_struct userdata_push_work;*/ | |
810 | /* | |
811 | #define DUMP_LAST_REPORTED_USER_DATA | |
812 | */ | |
813 | static void userdata_push_process(struct vdec_avs_hw_s *hw) | |
814 | { | |
815 | unsigned int user_data_flags; | |
816 | unsigned int user_data_wp; | |
817 | unsigned int user_data_length; | |
818 | struct userdata_poc_info_t user_data_poc; | |
819 | #ifdef DUMP_LAST_REPORTED_USER_DATA | |
820 | int user_data_len; | |
821 | int wp_start; | |
822 | unsigned char *pdata; | |
823 | int nLeft; | |
824 | #endif | |
825 | ||
826 | user_data_flags = READ_VREG(AV_SCRATCH_N); | |
827 | user_data_wp = (user_data_flags >> 16) & 0xffff; | |
828 | user_data_length = user_data_flags & 0x7fff; | |
829 | ||
830 | #ifdef DUMP_LAST_REPORTED_USER_DATA | |
831 | dma_sync_single_for_cpu(amports_get_dma_device(), | |
832 | hw->user_data_buffer_phys, USER_DATA_SIZE, | |
833 | DMA_FROM_DEVICE); | |
834 | ||
835 | if (user_data_length & 0x07) | |
836 | user_data_len = (user_data_length + 8) & 0xFFFFFFF8; | |
837 | else | |
838 | user_data_len = user_data_length; | |
839 | ||
840 | if (user_data_wp >= user_data_len) { | |
841 | wp_start = user_data_wp - user_data_len; | |
842 | ||
843 | pdata = (unsigned char *)hw->user_data_buffer; | |
844 | pdata += wp_start; | |
845 | nLeft = user_data_len; | |
846 | while (nLeft >= 8) { | |
847 | pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", | |
848 | pdata[0], pdata[1], pdata[2], pdata[3], | |
849 | pdata[4], pdata[5], pdata[6], pdata[7]); | |
850 | nLeft -= 8; | |
851 | pdata += 8; | |
852 | } | |
853 | } else { | |
854 | wp_start = user_data_wp + | |
855 | USER_DATA_SIZE - user_data_len; | |
856 | ||
857 | pdata = (unsigned char *)hw->user_data_buffer; | |
858 | pdata += wp_start; | |
859 | nLeft = USER_DATA_SIZE - wp_start; | |
860 | ||
861 | while (nLeft >= 8) { | |
862 | pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", | |
863 | pdata[0], pdata[1], pdata[2], pdata[3], | |
864 | pdata[4], pdata[5], pdata[6], pdata[7]); | |
865 | nLeft -= 8; | |
866 | pdata += 8; | |
867 | } | |
868 | ||
869 | pdata = (unsigned char *)hw->user_data_buffer; | |
870 | nLeft = user_data_wp; | |
871 | while (nLeft >= 8) { | |
872 | pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", | |
873 | pdata[0], pdata[1], pdata[2], pdata[3], | |
874 | pdata[4], pdata[5], pdata[6], pdata[7]); | |
875 | nLeft -= 8; | |
876 | pdata += 8; | |
877 | } | |
878 | } | |
879 | #endif | |
880 | ||
881 | /* | |
882 | pr_info("pocinfo 0x%x, poc %d, wp 0x%x, len %d\n", | |
883 | READ_VREG(AV_SCRATCH_L), READ_VREG(AV_SCRATCH_M), | |
884 | user_data_wp, user_data_length); | |
885 | */ | |
886 | user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L); | |
887 | user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M); | |
888 | ||
889 | WRITE_VREG(AV_SCRATCH_N, 0); | |
890 | /* | |
891 | wakeup_userdata_poll(user_data_poc, user_data_wp, | |
892 | (unsigned long)hw->user_data_buffer, | |
893 | USER_DATA_SIZE, user_data_length); | |
894 | */ | |
895 | } | |
896 | ||
897 | static void userdata_push_do_work(struct work_struct *work) | |
898 | { | |
899 | struct vdec_avs_hw_s *hw = | |
900 | container_of(work, struct vdec_avs_hw_s, userdata_push_work); | |
901 | userdata_push_process(hw); | |
902 | } | |
903 | ||
904 | static u8 UserDataHandler(struct vdec_avs_hw_s *hw) | |
905 | { | |
906 | unsigned int user_data_flags; | |
907 | ||
908 | user_data_flags = READ_VREG(AV_SCRATCH_N); | |
909 | if (user_data_flags & (1 << 15)) { /* data ready */ | |
910 | if (hw->m_ins_flag) { | |
911 | hw->dec_result = DEC_RESULT_USERDATA; | |
912 | vdec_schedule_work(&hw->work); | |
913 | return 1; | |
914 | } else | |
915 | schedule_work(&hw->userdata_push_work); | |
916 | } | |
917 | return 0; | |
918 | } | |
919 | #endif | |
920 | ||
cc41710a | 921 | |
922 | static inline void avs_update_gvs(struct vdec_avs_hw_s *hw) | |
923 | { | |
924 | if (hw->gvs->frame_height != hw->frame_height) { | |
925 | hw->gvs->frame_width = hw->frame_width; | |
926 | hw->gvs->frame_height = hw->frame_height; | |
927 | } | |
928 | if (hw->gvs->frame_dur != hw->frame_dur) { | |
929 | hw->gvs->frame_dur = hw->frame_dur; | |
930 | if (hw->frame_dur != 0) | |
4cd99df0 | 931 | hw->gvs->frame_rate = ((96000 * 10 / hw->frame_dur) % 10) < 5 ? |
932 | 96000 / hw->frame_dur : (96000 / hw->frame_dur +1); | |
cc41710a | 933 | else |
934 | hw->gvs->frame_rate = -1; | |
935 | } | |
936 | ||
937 | hw->gvs->status = hw->stat; | |
938 | hw->gvs->error_count = READ_VREG(AV_SCRATCH_C); | |
939 | hw->gvs->drop_frame_count = hw->drop_frame_count; | |
940 | ||
941 | } | |
942 | ||
107c76a4 PY |
943 | #ifdef HANDLE_AVS_IRQ |
944 | static irqreturn_t vavs_isr(int irq, void *dev_id) | |
945 | #else | |
946 | static void vavs_isr(void) | |
947 | #endif | |
948 | { | |
107c76a4 PY |
949 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); |
950 | ||
1f676bcb | 951 | return IRQ_WAKE_THREAD; |
107c76a4 PY |
952 | } |
953 | /* | |
954 | *static int run_flag = 1; | |
955 | *static int step_flag; | |
956 | */ | |
957 | static int error_recovery_mode; /*0: blocky 1: mosaic*/ | |
958 | /* | |
959 | *static uint error_watchdog_threshold=10; | |
960 | *static uint error_watchdog_count; | |
961 | *static uint error_watchdog_buf_threshold = 0x4000000; | |
962 | */ | |
963 | ||
964 | static struct vframe_s *vavs_vf_peek(void *op_arg) | |
965 | { | |
966 | struct vframe_s *vf; | |
967 | struct vdec_avs_hw_s *hw = | |
968 | (struct vdec_avs_hw_s *)op_arg; | |
969 | hw->peek_num++; | |
970 | if (step == 2) | |
971 | return NULL; | |
972 | if (hw->recover_flag) | |
973 | return NULL; | |
974 | ||
975 | if (kfifo_peek(&hw->display_q, &vf)) { | |
976 | if (vf) { | |
977 | if (force_fps & 0x100) { | |
978 | u32 rate = force_fps & 0xff; | |
979 | ||
980 | if (rate) | |
981 | vf->duration = 96000/rate; | |
982 | else | |
983 | vf->duration = 0; | |
984 | } | |
985 | ||
986 | } | |
987 | return vf; | |
988 | } | |
989 | ||
990 | return NULL; | |
991 | ||
992 | } | |
993 | ||
994 | static struct vframe_s *vavs_vf_get(void *op_arg) | |
995 | { | |
996 | struct vframe_s *vf; | |
997 | struct vdec_avs_hw_s *hw = | |
998 | (struct vdec_avs_hw_s *)op_arg; | |
999 | ||
1000 | if (hw->recover_flag) | |
1001 | return NULL; | |
1002 | ||
1003 | if (step == 2) | |
1004 | return NULL; | |
1005 | else if (step == 1) | |
1006 | step = 2; | |
1007 | ||
1008 | if (kfifo_get(&hw->display_q, &vf)) { | |
1009 | if (vf) { | |
1010 | hw->get_num++; | |
1011 | if (force_fps & 0x100) { | |
1012 | u32 rate = force_fps & 0xff; | |
1013 | ||
1014 | if (rate) | |
1015 | vf->duration = 96000/rate; | |
1016 | else | |
1017 | vf->duration = 0; | |
1018 | } | |
1019 | ||
1020 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, | |
17a06af5 | 1021 | "%s, index = %d, w %d h %d, type 0x%x detached %d\n", |
107c76a4 PY |
1022 | __func__, |
1023 | vf->index, | |
1024 | vf->width, | |
1025 | vf->height, | |
17a06af5 RZ |
1026 | vf->type, |
1027 | buf_of_vf(vf)->detached); | |
107c76a4 PY |
1028 | } |
1029 | return vf; | |
1030 | } | |
1031 | ||
1032 | return NULL; | |
1033 | ||
1034 | } | |
1035 | ||
1036 | static void vavs_vf_put(struct vframe_s *vf, void *op_arg) | |
1037 | { | |
1038 | int i; | |
1039 | struct vdec_avs_hw_s *hw = | |
1040 | (struct vdec_avs_hw_s *)op_arg; | |
1041 | ||
1042 | if (vf) { | |
1043 | hw->put_num++; | |
1044 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, | |
17a06af5 | 1045 | "%s, index = %d, w %d h %d, type 0x%x detached 0x%x\n", |
107c76a4 PY |
1046 | __func__, |
1047 | vf->index, | |
1048 | vf->width, | |
1049 | vf->height, | |
17a06af5 RZ |
1050 | vf->type, |
1051 | buf_of_vf(vf)->detached); | |
107c76a4 PY |
1052 | } |
1053 | if (hw->recover_flag) | |
1054 | return; | |
1055 | ||
1056 | for (i = 0; i < VF_POOL_SIZE; i++) { | |
17a06af5 | 1057 | if (vf == &hw->vfpool[i].vf) |
107c76a4 PY |
1058 | break; |
1059 | } | |
1060 | if (i < VF_POOL_SIZE) | |
1061 | ||
1062 | kfifo_put(&hw->recycle_q, (const struct vframe_s *)vf); | |
1063 | ||
1064 | } | |
1065 | ||
1066 | static int vavs_event_cb(int type, void *data, void *private_data) | |
1067 | { | |
1068 | return 0; | |
1069 | } | |
1070 | ||
bc26b20a | 1071 | static int vavs_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) |
107c76a4 PY |
1072 | { |
1073 | struct vdec_avs_hw_s *hw = | |
1074 | (struct vdec_avs_hw_s *)vdec->private; | |
1075 | /*if (!(hw->stat & STAT_VDEC_RUN)) | |
1076 | return -1;*/ | |
1077 | if (!hw) | |
1078 | return -1; | |
1079 | ||
1080 | vstatus->frame_width = hw->frame_width; | |
1081 | vstatus->frame_height = hw->frame_height; | |
1082 | if (hw->frame_dur != 0) | |
4cd99df0 | 1083 | vstatus->frame_rate = ((96000 * 10 / hw->frame_dur) % 10) < 5 ? |
1084 | 96000 / hw->frame_dur : (96000 / hw->frame_dur +1); | |
107c76a4 PY |
1085 | else |
1086 | vstatus->frame_rate = -1; | |
1087 | vstatus->error_count = READ_VREG(AV_SCRATCH_C); | |
1088 | vstatus->status = hw->stat; | |
1089 | vstatus->bit_rate = hw->gvs->bit_rate; | |
1090 | vstatus->frame_dur = hw->frame_dur; | |
1091 | vstatus->frame_data = hw->gvs->frame_data; | |
1092 | vstatus->total_data = hw->gvs->total_data; | |
1093 | vstatus->frame_count = hw->gvs->frame_count; | |
1094 | vstatus->error_frame_count = hw->gvs->error_frame_count; | |
1095 | vstatus->drop_frame_count = hw->gvs->drop_frame_count; | |
4cd99df0 | 1096 | vstatus->i_decoded_frames = hw->gvs->i_decoded_frames; |
1097 | vstatus->i_lost_frames = hw->gvs->i_lost_frames; | |
1098 | vstatus->i_concealed_frames = hw->gvs->i_concealed_frames; | |
1099 | vstatus->p_decoded_frames = hw->gvs->p_decoded_frames; | |
1100 | vstatus->p_lost_frames = hw->gvs->p_lost_frames; | |
1101 | vstatus->p_concealed_frames = hw->gvs->p_concealed_frames; | |
1102 | vstatus->b_decoded_frames = hw->gvs->b_decoded_frames; | |
1103 | vstatus->b_lost_frames = hw->gvs->b_lost_frames; | |
1104 | vstatus->b_concealed_frames = hw->gvs->b_concealed_frames; | |
107c76a4 PY |
1105 | vstatus->total_data = hw->gvs->total_data; |
1106 | vstatus->samp_cnt = hw->gvs->samp_cnt; | |
1107 | vstatus->offset = hw->gvs->offset; | |
1108 | snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), | |
1109 | "%s", DRIVER_NAME); | |
1110 | ||
1111 | return 0; | |
1112 | } | |
1113 | ||
bc26b20a | 1114 | static int vavs_set_isreset(struct vdec_s *vdec, int isreset) |
107c76a4 PY |
1115 | { |
1116 | struct vdec_avs_hw_s *hw = | |
1117 | (struct vdec_avs_hw_s *)vdec->private; | |
1118 | ||
1119 | hw->is_reset = isreset; | |
1120 | return 0; | |
1121 | } | |
1122 | ||
1123 | static int vavs_vdec_info_init(struct vdec_avs_hw_s *hw) | |
1124 | { | |
107c76a4 PY |
1125 | |
1126 | hw->gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); | |
1127 | if (NULL == hw->gvs) { | |
1128 | pr_info("the struct of vdec status malloc failed.\n"); | |
1129 | return -ENOMEM; | |
1130 | } | |
107c76a4 PY |
1131 | |
1132 | return 0; | |
1133 | } | |
1134 | /****************************************/ | |
1135 | static int vavs_canvas_init(struct vdec_avs_hw_s *hw) | |
1136 | { | |
1137 | int i, ret; | |
1138 | u32 canvas_width, canvas_height; | |
1139 | u32 decbuf_size, decbuf_y_size, decbuf_uv_size; | |
1140 | unsigned long buf_start; | |
1141 | int need_alloc_buf_num; | |
1142 | struct vdec_s *vdec = NULL; | |
1143 | ||
1144 | if (hw->m_ins_flag) | |
1145 | vdec = hw_to_vdec(hw); | |
1146 | ||
107c76a4 PY |
1147 | if (buf_size <= 0x00400000) { |
1148 | /* SD only */ | |
1149 | canvas_width = 768; | |
1150 | canvas_height = 576; | |
1151 | decbuf_y_size = 0x80000; | |
1152 | decbuf_uv_size = 0x20000; | |
1153 | decbuf_size = 0x100000; | |
1154 | } else { | |
1155 | /* HD & SD */ | |
1156 | canvas_width = 1920; | |
1157 | canvas_height = 1088; | |
1158 | decbuf_y_size = 0x200000; | |
1159 | decbuf_uv_size = 0x80000; | |
1160 | decbuf_size = 0x300000; | |
1161 | } | |
1162 | ||
1163 | #ifdef AVSP_LONG_CABAC | |
1164 | need_alloc_buf_num = hw->vf_buf_num_used + 2; | |
1165 | #else | |
1166 | need_alloc_buf_num = hw->vf_buf_num_used + 1; | |
1167 | #endif | |
1168 | for (i = 0; i < need_alloc_buf_num; i++) { | |
1169 | ||
1170 | if (i == (need_alloc_buf_num - 1)) | |
1171 | decbuf_size = WORKSPACE_SIZE; | |
1172 | #ifdef AVSP_LONG_CABAC | |
1173 | else if (i == (need_alloc_buf_num - 2)) | |
1174 | decbuf_size = WORKSPACE_SIZE_A; | |
1175 | #endif | |
1176 | ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i, | |
1177 | decbuf_size, DRIVER_NAME, &buf_start); | |
1178 | if (ret < 0) | |
1179 | return ret; | |
1180 | if (i == (need_alloc_buf_num - 1)) { | |
1181 | if (firmware_sel == 1) | |
1182 | hw->buf_offset = buf_start - | |
1183 | RV_AI_BUFF_START_ADDR; | |
1184 | else | |
1185 | hw->buf_offset = buf_start - | |
1186 | LONG_CABAC_RV_AI_BUFF_START_ADDR; | |
1187 | continue; | |
1188 | } | |
1189 | #ifdef AVSP_LONG_CABAC | |
1190 | else if (i == (need_alloc_buf_num - 2)) { | |
1191 | avsp_heap_adr = codec_mm_phys_to_virt(buf_start); | |
1192 | continue; | |
1193 | } | |
1194 | #endif | |
1195 | if (hw->m_ins_flag) { | |
1196 | unsigned canvas; | |
1197 | ||
1198 | if (vdec->parallel_dec == 1) { | |
1199 | unsigned tmp; | |
1200 | if (canvas_u(hw->canvas_spec[i]) == 0xff) { | |
1201 | tmp = | |
1202 | vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); | |
1203 | hw->canvas_spec[i] &= ~(0xffff << 8); | |
1204 | hw->canvas_spec[i] |= tmp << 8; | |
1205 | hw->canvas_spec[i] |= tmp << 16; | |
1206 | } | |
1207 | if (canvas_y(hw->canvas_spec[i]) == 0xff) { | |
1208 | tmp = | |
1209 | vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id); | |
1210 | hw->canvas_spec[i] &= ~0xff; | |
1211 | hw->canvas_spec[i] |= tmp; | |
1212 | } | |
1213 | canvas = hw->canvas_spec[i]; | |
1214 | } else { | |
1215 | canvas = vdec->get_canvas(i, 2); | |
1216 | hw->canvas_spec[i] = canvas; | |
1217 | } | |
1218 | ||
1219 | hw->canvas_config[i][0].phy_addr = | |
1220 | buf_start; | |
1221 | hw->canvas_config[i][0].width = | |
1222 | canvas_width; | |
1223 | hw->canvas_config[i][0].height = | |
1224 | canvas_height; | |
1225 | hw->canvas_config[i][0].block_mode = | |
1226 | CANVAS_BLKMODE_32X32; | |
1227 | ||
1228 | hw->canvas_config[i][1].phy_addr = | |
1229 | buf_start + decbuf_y_size; | |
1230 | hw->canvas_config[i][1].width = | |
1231 | canvas_width; | |
1232 | hw->canvas_config[i][1].height = | |
1233 | canvas_height / 2; | |
1234 | hw->canvas_config[i][1].block_mode = | |
1235 | CANVAS_BLKMODE_32X32; | |
1236 | ||
1237 | } else { | |
1238 | #ifdef NV21 | |
1239 | canvas_config(canvas_base + canvas_num * i + 0, | |
1240 | buf_start, | |
1241 | canvas_width, canvas_height, | |
1242 | CANVAS_ADDR_NOWRAP, | |
1243 | CANVAS_BLKMODE_32X32); | |
1244 | canvas_config(canvas_base + canvas_num * i + 1, | |
1245 | buf_start + | |
1246 | decbuf_y_size, canvas_width, | |
1247 | canvas_height / 2, | |
1248 | CANVAS_ADDR_NOWRAP, | |
1249 | CANVAS_BLKMODE_32X32); | |
1250 | #else | |
1251 | canvas_config(canvas_num * i + 0, | |
1252 | buf_start, | |
1253 | canvas_width, canvas_height, | |
1254 | CANVAS_ADDR_NOWRAP, | |
1255 | CANVAS_BLKMODE_32X32); | |
1256 | canvas_config(canvas_num * i + 1, | |
1257 | buf_start + | |
1258 | decbuf_y_size, canvas_width / 2, | |
1259 | canvas_height / 2, | |
1260 | CANVAS_ADDR_NOWRAP, | |
1261 | CANVAS_BLKMODE_32X32); | |
1262 | canvas_config(canvas_num * i + 2, | |
1263 | buf_start + | |
1264 | decbuf_y_size + decbuf_uv_size, | |
1265 | canvas_width / 2, canvas_height / 2, | |
1266 | CANVAS_ADDR_NOWRAP, | |
1267 | CANVAS_BLKMODE_32X32); | |
1268 | #endif | |
17a06af5 RZ |
1269 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, |
1270 | "canvas config %d, addr %p\n", i, | |
107c76a4 | 1271 | (void *)buf_start); |
107c76a4 PY |
1272 | } |
1273 | } | |
1274 | return 0; | |
1275 | } | |
1276 | ||
bc26b20a | 1277 | static void vavs_recover(struct vdec_avs_hw_s *hw) |
107c76a4 PY |
1278 | { |
1279 | vavs_canvas_init(hw); | |
1280 | ||
1281 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); | |
1282 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1283 | ||
1284 | READ_VREG(DOS_SW_RESET0); | |
1285 | ||
1286 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); | |
1287 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1288 | ||
1289 | WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); | |
1290 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1291 | ||
1292 | if (firmware_sel == 1) { | |
1293 | WRITE_VREG(POWER_CTL_VLD, 0x10); | |
1294 | WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, | |
1295 | MEM_FIFO_CNT_BIT, 2); | |
1296 | WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, | |
1297 | MEM_LEVEL_CNT_BIT, 6); | |
1298 | } | |
1299 | ||
1300 | ||
1301 | if (firmware_sel == 0) { | |
1302 | /* fixed canvas index */ | |
1303 | WRITE_VREG(AV_SCRATCH_0, canvas_base); | |
1304 | WRITE_VREG(AV_SCRATCH_1, hw->vf_buf_num_used); | |
1305 | } else { | |
1306 | int ii; | |
17a06af5 | 1307 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 PY |
1308 | for (ii = 0; ii < 4; ii++) { |
1309 | WRITE_VREG(AV_SCRATCH_0 + ii, | |
1310 | (canvas_base + canvas_num * ii) | | |
1311 | ((canvas_base + canvas_num * ii + 1) | |
1312 | << 8) | | |
1313 | ((canvas_base + canvas_num * ii + 1) | |
1314 | << 16) | |
1315 | ); | |
1316 | } | |
17a06af5 RZ |
1317 | #else |
1318 | for (ii = 0; ii < hw->vf_buf_num_used; ii += 2) { | |
1319 | WRITE_VREG(buf_spec_reg[ii >> 1], | |
1320 | (canvas_base + canvas_num * ii) | | |
1321 | ((canvas_base + canvas_num * ii + 1) | |
1322 | << 8) | | |
1323 | ((canvas_base + canvas_num * ii + 2) | |
1324 | << 16) | | |
1325 | ((canvas_base + canvas_num * ii + 3) | |
1326 | << 24) | |
1327 | ); | |
1328 | } | |
1329 | #endif | |
107c76a4 PY |
1330 | } |
1331 | ||
1332 | /* notify ucode the buffer offset */ | |
1333 | WRITE_VREG(AV_SCRATCH_F, hw->buf_offset); | |
1334 | ||
1335 | /* disable PSCALE for hardware sharing */ | |
1336 | WRITE_VREG(PSCALE_CTRL, 0); | |
1337 | ||
17a06af5 | 1338 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 | 1339 | WRITE_VREG(AVS_SOS_COUNT, 0); |
17a06af5 | 1340 | #endif |
107c76a4 PY |
1341 | WRITE_VREG(AVS_BUFFERIN, 0); |
1342 | WRITE_VREG(AVS_BUFFEROUT, 0); | |
1343 | if (error_recovery_mode) | |
1344 | WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); | |
1345 | else | |
1346 | WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); | |
1347 | /* clear mailbox interrupt */ | |
1348 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); | |
1349 | ||
1350 | /* enable mailbox interrupt */ | |
1351 | WRITE_VREG(ASSIST_MBOX1_MASK, 1); | |
17a06af5 | 1352 | #ifndef USE_DYNAMIC_BUF_NUM /* def DEBUG_UCODE */ |
107c76a4 PY |
1353 | WRITE_VREG(AV_SCRATCH_D, 0); |
1354 | #endif | |
1355 | ||
1356 | #ifdef NV21 | |
1357 | SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); | |
1358 | #endif | |
1359 | ||
1360 | #ifdef PIC_DC_NEED_CLEAR | |
1361 | CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); | |
1362 | #endif | |
1363 | ||
1364 | #ifdef AVSP_LONG_CABAC | |
1365 | if (firmware_sel == 0) { | |
1366 | WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy); | |
1367 | WRITE_VREG(LONG_CABAC_REQ, 0); | |
1368 | WRITE_VREG(LONG_CABAC_PIC_SIZE, 0); | |
1369 | WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); | |
1370 | } | |
1371 | #endif | |
1372 | WRITE_VREG(AV_SCRATCH_5, 0); | |
1373 | ||
1374 | } | |
1375 | ||
1376 | #define MBY_MBX MB_MOTION_MODE /*0xc07*/ | |
1377 | #define AVS_CO_MB_WR_ADDR 0xc38 | |
1378 | #define AVS_CO_MB_RW_CTL 0xc3d | |
1379 | #define AVS_CO_MB_RD_ADDR 0xc39 | |
1380 | #define AVSP_IQ_WQ_PARAM_01 0x0e19 | |
1381 | #define AVSP_IQ_WQ_PARAM_23 0x0e1a | |
1382 | #define AVSP_IQ_WQ_PARAM_45 0x0e1b | |
1383 | ||
1384 | static void vavs_save_regs(struct vdec_avs_hw_s *hw) | |
1385 | { | |
1386 | hw->reg_scratch_0 = READ_VREG(AV_SCRATCH_0); | |
1387 | hw->reg_scratch_1 = READ_VREG(AV_SCRATCH_1); | |
1388 | hw->reg_scratch_2 = READ_VREG(AV_SCRATCH_2); | |
1389 | hw->reg_scratch_3 = READ_VREG(AV_SCRATCH_3); | |
1390 | hw->reg_scratch_4 = READ_VREG(AV_SCRATCH_4); | |
1391 | hw->reg_scratch_5 = READ_VREG(AV_SCRATCH_5); | |
1392 | hw->reg_scratch_6 = READ_VREG(AV_SCRATCH_6); | |
1393 | hw->reg_scratch_7 = READ_VREG(AV_SCRATCH_7); | |
1394 | hw->reg_scratch_8 = READ_VREG(AV_SCRATCH_8); | |
1395 | hw->reg_scratch_9 = READ_VREG(AV_SCRATCH_9); | |
1396 | hw->reg_scratch_A = READ_VREG(AV_SCRATCH_A); | |
1397 | hw->reg_scratch_B = READ_VREG(AV_SCRATCH_B); | |
1398 | hw->reg_scratch_C = READ_VREG(AV_SCRATCH_C); | |
1399 | hw->reg_scratch_D = READ_VREG(AV_SCRATCH_D); | |
1400 | hw->reg_scratch_E = READ_VREG(AV_SCRATCH_E); | |
1401 | hw->reg_scratch_F = READ_VREG(AV_SCRATCH_F); | |
1402 | hw->reg_scratch_G = READ_VREG(AV_SCRATCH_G); | |
1403 | hw->reg_scratch_H = READ_VREG(AV_SCRATCH_H); | |
1404 | hw->reg_scratch_I = READ_VREG(AV_SCRATCH_I); | |
1405 | ||
1406 | hw->reg_mb_width = READ_VREG(MB_WIDTH); | |
1407 | hw->reg_viff_bit_cnt = READ_VREG(VIFF_BIT_CNT); | |
1408 | ||
1409 | hw->reg_canvas_addr = READ_VREG(REC_CANVAS_ADDR); | |
17a06af5 RZ |
1410 | hw->reg_dbkr_canvas_addr = READ_VREG(DBKR_CANVAS_ADDR); |
1411 | hw->reg_dbkw_canvas_addr = READ_VREG(DBKW_CANVAS_ADDR); | |
1412 | hw->reg_anc2_canvas_addr = READ_VREG(ANC2_CANVAS_ADDR); | |
1413 | hw->reg_anc0_canvas_addr = READ_VREG(ANC0_CANVAS_ADDR); | |
1414 | hw->reg_anc1_canvas_addr = READ_VREG(ANC1_CANVAS_ADDR); | |
1415 | hw->reg_anc3_canvas_addr = READ_VREG(ANC3_CANVAS_ADDR); | |
1416 | hw->reg_anc4_canvas_addr = READ_VREG(ANC4_CANVAS_ADDR); | |
1417 | hw->reg_anc5_canvas_addr = READ_VREG(ANC5_CANVAS_ADDR); | |
1418 | ||
1419 | hw->slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE); | |
1420 | ||
1421 | hw->vc1_control_reg = READ_VREG(VC1_CONTROL_REG); | |
1422 | hw->avs_co_mb_wr_addr = READ_VREG(AVS_CO_MB_WR_ADDR); | |
1423 | hw->slice_start_byte_01 = READ_VREG(SLICE_START_BYTE_01); | |
1424 | hw->slice_start_byte_23 = READ_VREG(SLICE_START_BYTE_23); | |
1425 | hw->vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG); | |
1426 | hw->iqidct_control = READ_VREG(IQIDCT_CONTROL); | |
1427 | hw->rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT); | |
1428 | hw->slice_qp = READ_VREG(SLICE_QP); | |
1429 | ||
1430 | hw->dc_scaler = READ_VREG(DC_SCALER); | |
1431 | hw->avsp_iq_wq_param_01 = READ_VREG(AVSP_IQ_WQ_PARAM_01); | |
1432 | hw->avsp_iq_wq_param_23 = READ_VREG(AVSP_IQ_WQ_PARAM_23); | |
1433 | hw->avsp_iq_wq_param_45 = READ_VREG(AVSP_IQ_WQ_PARAM_45); | |
1434 | hw->avs_co_mb_rd_addr = READ_VREG(AVS_CO_MB_RD_ADDR); | |
1435 | hw->dblk_mb_wid_height = READ_VREG(DBLK_MB_WID_HEIGHT); | |
1436 | hw->mc_pic_w_h = READ_VREG(MC_PIC_W_H); | |
1437 | hw->avs_co_mb_rw_ctl = READ_VREG(AVS_CO_MB_RW_CTL); | |
1438 | ||
1439 | hw->vld_decode_control = READ_VREG(VLD_DECODE_CONTROL); | |
107c76a4 PY |
1440 | } |
1441 | ||
1442 | static void vavs_restore_regs(struct vdec_avs_hw_s *hw) | |
1443 | { | |
17a06af5 RZ |
1444 | debug_print(hw, PRINT_FLAG_DECODING, |
1445 | "%s scratch_8 (AVS_BUFFERIN) 0x%x, decode_pic_count = %d\n", | |
1446 | __func__, hw->reg_scratch_8, hw->decode_pic_count); | |
1447 | ||
107c76a4 PY |
1448 | WRITE_VREG(AV_SCRATCH_0, hw->reg_scratch_0); |
1449 | WRITE_VREG(AV_SCRATCH_1, hw->reg_scratch_1); | |
1450 | WRITE_VREG(AV_SCRATCH_2, hw->reg_scratch_2); | |
1451 | WRITE_VREG(AV_SCRATCH_3, hw->reg_scratch_3); | |
1452 | WRITE_VREG(AV_SCRATCH_4, hw->reg_scratch_4); | |
1453 | WRITE_VREG(AV_SCRATCH_5, hw->reg_scratch_5); | |
1454 | WRITE_VREG(AV_SCRATCH_6, hw->reg_scratch_6); | |
1455 | WRITE_VREG(AV_SCRATCH_7, hw->reg_scratch_7); | |
1456 | WRITE_VREG(AV_SCRATCH_8, hw->reg_scratch_8); | |
1457 | WRITE_VREG(AV_SCRATCH_9, hw->reg_scratch_9); | |
1458 | WRITE_VREG(AV_SCRATCH_A, hw->reg_scratch_A); | |
1459 | WRITE_VREG(AV_SCRATCH_B, hw->reg_scratch_B); | |
1460 | WRITE_VREG(AV_SCRATCH_C, hw->reg_scratch_C); | |
1461 | WRITE_VREG(AV_SCRATCH_D, hw->reg_scratch_D); | |
1462 | WRITE_VREG(AV_SCRATCH_E, hw->reg_scratch_E); | |
1463 | WRITE_VREG(AV_SCRATCH_F, hw->reg_scratch_F); | |
1464 | WRITE_VREG(AV_SCRATCH_G, hw->reg_scratch_G); | |
1465 | WRITE_VREG(AV_SCRATCH_H, hw->reg_scratch_H); | |
1466 | WRITE_VREG(AV_SCRATCH_I, hw->reg_scratch_I); | |
1467 | ||
1468 | WRITE_VREG(MB_WIDTH, hw->reg_mb_width); | |
1469 | WRITE_VREG(VIFF_BIT_CNT, hw->reg_viff_bit_cnt); | |
1470 | ||
1471 | WRITE_VREG(REC_CANVAS_ADDR, hw->reg_canvas_addr); | |
1472 | WRITE_VREG(DBKR_CANVAS_ADDR, hw->reg_dbkr_canvas_addr); | |
1473 | WRITE_VREG(DBKW_CANVAS_ADDR, hw->reg_dbkw_canvas_addr); | |
1474 | WRITE_VREG(ANC2_CANVAS_ADDR, hw->reg_anc2_canvas_addr); | |
1475 | WRITE_VREG(ANC0_CANVAS_ADDR, hw->reg_anc0_canvas_addr); | |
1476 | WRITE_VREG(ANC1_CANVAS_ADDR, hw->reg_anc1_canvas_addr); | |
17a06af5 RZ |
1477 | WRITE_VREG(ANC3_CANVAS_ADDR, hw->reg_anc3_canvas_addr); |
1478 | WRITE_VREG(ANC4_CANVAS_ADDR, hw->reg_anc4_canvas_addr); | |
1479 | WRITE_VREG(ANC5_CANVAS_ADDR, hw->reg_anc5_canvas_addr); | |
107c76a4 PY |
1480 | |
1481 | WRITE_VREG(SLICE_VER_POS_PIC_TYPE, hw->slice_ver_pos_pic_type); | |
1482 | ||
1483 | WRITE_VREG(VC1_CONTROL_REG, hw->vc1_control_reg); | |
1484 | WRITE_VREG(AVS_CO_MB_WR_ADDR, hw->avs_co_mb_wr_addr); | |
1485 | WRITE_VREG(SLICE_START_BYTE_01, hw->slice_start_byte_01); | |
1486 | WRITE_VREG(SLICE_START_BYTE_23, hw->slice_start_byte_23); | |
1487 | WRITE_VREG(VCOP_CTRL_REG, hw->vcop_ctrl_reg); | |
1488 | WRITE_VREG(IQIDCT_CONTROL, hw->iqidct_control); | |
1489 | WRITE_VREG(RV_AI_MB_COUNT, hw->rv_ai_mb_count); | |
1490 | WRITE_VREG(SLICE_QP, hw->slice_qp); | |
1491 | ||
1492 | WRITE_VREG(DC_SCALER, hw->dc_scaler); | |
1493 | WRITE_VREG(AVSP_IQ_WQ_PARAM_01, hw->avsp_iq_wq_param_01); | |
1494 | WRITE_VREG(AVSP_IQ_WQ_PARAM_23, hw->avsp_iq_wq_param_23); | |
1495 | WRITE_VREG(AVSP_IQ_WQ_PARAM_45, hw->avsp_iq_wq_param_45); | |
1496 | WRITE_VREG(AVS_CO_MB_RD_ADDR, hw->avs_co_mb_rd_addr); | |
1497 | WRITE_VREG(DBLK_MB_WID_HEIGHT, hw->dblk_mb_wid_height); | |
1498 | WRITE_VREG(MC_PIC_W_H, hw->mc_pic_w_h); | |
1499 | WRITE_VREG(AVS_CO_MB_RW_CTL, hw->avs_co_mb_rw_ctl); | |
1500 | ||
1501 | WRITE_VREG(VLD_DECODE_CONTROL, hw->vld_decode_control); | |
1502 | ||
1503 | } | |
1504 | ||
1505 | static int vavs_prot_init(struct vdec_avs_hw_s *hw) | |
1506 | { | |
1507 | int r = 0; | |
1508 | #if DEBUG_MULTI_FLAG > 0 | |
1509 | if (hw->decode_pic_count == 0) { | |
1510 | #endif | |
1511 | #if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ | |
1512 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); | |
1513 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1514 | ||
1515 | READ_VREG(DOS_SW_RESET0); | |
1516 | ||
1517 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); | |
1518 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1519 | ||
1520 | WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); | |
1521 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1522 | ||
1523 | #else | |
1524 | WRITE_RESET_REG(RESET0_REGISTER, | |
1525 | RESET_IQIDCT | RESET_MC | RESET_VLD_PART); | |
1526 | READ_RESET_REG(RESET0_REGISTER); | |
1527 | WRITE_RESET_REG(RESET0_REGISTER, | |
1528 | RESET_IQIDCT | RESET_MC | RESET_VLD_PART); | |
1529 | ||
1530 | WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK); | |
1531 | #endif | |
1532 | #if DEBUG_MULTI_FLAG > 0 | |
1533 | } | |
1534 | #endif | |
1535 | /***************** reset vld **********************************/ | |
1536 | WRITE_VREG(POWER_CTL_VLD, 0x10); | |
1537 | WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2); | |
1538 | WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, MEM_LEVEL_CNT_BIT, 6); | |
1539 | /*************************************************************/ | |
1540 | if (hw->m_ins_flag) { | |
1541 | int i; | |
1542 | if (hw->decode_pic_count == 0) { | |
1543 | r = vavs_canvas_init(hw); | |
17a06af5 | 1544 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 PY |
1545 | for (i = 0; i < 4; i++) { |
1546 | WRITE_VREG(AV_SCRATCH_0 + i, | |
1547 | hw->canvas_spec[i] | |
1548 | ); | |
1549 | } | |
17a06af5 | 1550 | #else |
46448536 PY |
1551 | for (i = 0; i < hw->vf_buf_num_used; i++) |
1552 | WRITE_VREG(buf_spec_reg[i], 0); | |
17a06af5 RZ |
1553 | for (i = 0; i < hw->vf_buf_num_used; i += 2) { |
1554 | WRITE_VREG(buf_spec_reg[i >> 1], | |
1555 | (hw->canvas_spec[i] & 0xffff) | | |
1556 | ((hw->canvas_spec[i + 1] & 0xffff) | |
1557 | << 16) | |
1558 | ); | |
1559 | debug_print(hw, PRINT_FLAG_DECODING, | |
1560 | "%s WRITE_VREG(0x%x, 0x%x)\n", | |
1561 | __func__, buf_spec_reg[i >> 1], READ_VREG(buf_spec_reg[i >> 1])); | |
1562 | } | |
1563 | #endif | |
107c76a4 PY |
1564 | } else |
1565 | vavs_restore_regs(hw); | |
1566 | ||
17a06af5 | 1567 | for (i = 0; i < hw->vf_buf_num_used; i++) { |
107c76a4 PY |
1568 | canvas_config_ex(canvas_y(hw->canvas_spec[i]), |
1569 | hw->canvas_config[i][0].phy_addr, | |
1570 | hw->canvas_config[i][0].width, | |
1571 | hw->canvas_config[i][0].height, | |
1572 | CANVAS_ADDR_NOWRAP, | |
1573 | hw->canvas_config[i][0].block_mode, | |
1574 | 0); | |
1575 | ||
1576 | canvas_config_ex(canvas_u(hw->canvas_spec[i]), | |
1577 | hw->canvas_config[i][1].phy_addr, | |
1578 | hw->canvas_config[i][1].width, | |
1579 | hw->canvas_config[i][1].height, | |
1580 | CANVAS_ADDR_NOWRAP, | |
1581 | hw->canvas_config[i][1].block_mode, | |
1582 | 0); | |
1583 | } | |
1584 | } else { | |
1585 | r = vavs_canvas_init(hw); | |
1586 | #ifdef NV21 | |
1587 | if (firmware_sel == 0) { | |
1588 | /* fixed canvas index */ | |
1589 | WRITE_VREG(AV_SCRATCH_0, canvas_base); | |
1590 | WRITE_VREG(AV_SCRATCH_1, hw->vf_buf_num_used); | |
1591 | } else { | |
1592 | int ii; | |
17a06af5 | 1593 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 PY |
1594 | for (ii = 0; ii < 4; ii++) { |
1595 | WRITE_VREG(AV_SCRATCH_0 + ii, | |
1596 | (canvas_base + canvas_num * ii) | | |
1597 | ((canvas_base + canvas_num * ii + 1) | |
1598 | << 8) | | |
1599 | ((canvas_base + canvas_num * ii + 1) | |
1600 | << 16) | |
1601 | ); | |
1602 | } | |
17a06af5 RZ |
1603 | #else |
1604 | for (ii = 0; ii < hw->vf_buf_num_used; ii += 2) { | |
1605 | WRITE_VREG(buf_spec_reg[ii >> 1], | |
1606 | (canvas_base + canvas_num * ii) | | |
1607 | ((canvas_base + canvas_num * ii + 1) | |
1608 | << 8) | | |
1609 | ((canvas_base + canvas_num * ii + 2) | |
1610 | << 16) | | |
1611 | ((canvas_base + canvas_num * ii + 3) | |
1612 | << 24) | |
1613 | ); | |
1614 | } | |
1615 | #endif | |
107c76a4 PY |
1616 | /* |
1617 | *WRITE_VREG(AV_SCRATCH_0, 0x010100); | |
1618 | *WRITE_VREG(AV_SCRATCH_1, 0x040403); | |
1619 | *WRITE_VREG(AV_SCRATCH_2, 0x070706); | |
1620 | *WRITE_VREG(AV_SCRATCH_3, 0x0a0a09); | |
1621 | */ | |
1622 | } | |
1623 | #else | |
1624 | /* index v << 16 | u << 8 | y */ | |
1625 | WRITE_VREG(AV_SCRATCH_0, 0x020100); | |
1626 | WRITE_VREG(AV_SCRATCH_1, 0x050403); | |
1627 | WRITE_VREG(AV_SCRATCH_2, 0x080706); | |
1628 | WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); | |
1629 | #endif | |
1630 | } | |
1631 | /* notify ucode the buffer offset */ | |
1632 | if (hw->decode_pic_count == 0) | |
1633 | WRITE_VREG(AV_SCRATCH_F, hw->buf_offset); | |
1634 | ||
1635 | /* disable PSCALE for hardware sharing */ | |
1636 | WRITE_VREG(PSCALE_CTRL, 0); | |
1637 | ||
1638 | if (hw->decode_pic_count == 0) { | |
17a06af5 | 1639 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 | 1640 | WRITE_VREG(AVS_SOS_COUNT, 0); |
17a06af5 | 1641 | #endif |
107c76a4 PY |
1642 | WRITE_VREG(AVS_BUFFERIN, 0); |
1643 | WRITE_VREG(AVS_BUFFEROUT, 0); | |
1644 | } | |
1645 | if (error_recovery_mode) | |
1646 | WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); | |
1647 | else | |
1648 | WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); | |
1649 | /* clear mailbox interrupt */ | |
1650 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); | |
1651 | ||
1652 | /* enable mailbox interrupt */ | |
1653 | WRITE_VREG(ASSIST_MBOX1_MASK, 1); | |
17a06af5 | 1654 | #ifndef USE_DYNAMIC_BUF_NUM /* def DEBUG_UCODE */ |
107c76a4 PY |
1655 | if (hw->decode_pic_count == 0) |
1656 | WRITE_VREG(AV_SCRATCH_D, 0); | |
1657 | #endif | |
1658 | ||
1659 | #ifdef NV21 | |
1660 | SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); | |
1661 | #endif | |
1662 | ||
1663 | #ifdef PIC_DC_NEED_CLEAR | |
1664 | CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); | |
1665 | #endif | |
17a06af5 RZ |
1666 | if (hw->m_ins_flag && start_decoding_delay > 0) |
1667 | msleep(start_decoding_delay); | |
107c76a4 | 1668 | |
17a06af5 RZ |
1669 | //pr_info("+++++++++++++++++++++++++++++++\n"); |
1670 | //pr_info("+++++++++++++++++++++++++++++++\n"); | |
1671 | //pr_info("+++++++++++++++++++++++++++++++\n"); | |
107c76a4 PY |
1672 | #ifdef AVSP_LONG_CABAC |
1673 | if (firmware_sel == 0) { | |
1674 | WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy); | |
1675 | WRITE_VREG(LONG_CABAC_REQ, 0); | |
1676 | WRITE_VREG(LONG_CABAC_PIC_SIZE, 0); | |
1677 | WRITE_VREG(LONG_CABAC_SRC_ADDR, 0); | |
1678 | } | |
1679 | #endif | |
1680 | ||
1681 | #ifdef ENABLE_USER_DATA | |
b06eadf9 | 1682 | if (hw->decode_pic_count == 0) { |
107c76a4 PY |
1683 | WRITE_VREG(AV_SCRATCH_N, (u32)(hw->user_data_buffer_phys - hw->buf_offset)); |
1684 | pr_debug("AV_SCRATCH_N = 0x%x\n", READ_VREG(AV_SCRATCH_N)); | |
46448536 PY |
1685 | } else |
1686 | WRITE_VREG(AV_SCRATCH_N, 0); | |
107c76a4 PY |
1687 | #endif |
1688 | if (hw->m_ins_flag) { | |
1689 | if (vdec_frame_based(hw_to_vdec(hw))) | |
1690 | WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE); | |
17a06af5 RZ |
1691 | else { |
1692 | if (hw->decode_status_skip_pic_done_flag) { | |
1693 | WRITE_VREG(DECODE_CFG, hw->decode_decode_cont_start_code); | |
1694 | WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE_CONT); | |
1695 | } else | |
1696 | WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE); | |
1697 | } | |
46448536 | 1698 | WRITE_VREG(DECODE_LMEM_BUF_ADR, (u32)hw->lmem_phy_addr); |
107c76a4 PY |
1699 | } else |
1700 | WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE); | |
107c76a4 | 1701 | |
17a06af5 RZ |
1702 | if (ins_udebug_flag[DECODE_ID(hw)] && |
1703 | (ins_udebug_flag[DECODE_ID(hw)] >> 16) == hw->decode_pic_count) { | |
1704 | WRITE_VREG(DECODE_STOP_POS, | |
1705 | ins_udebug_flag[DECODE_ID(hw)] & 0xffff); | |
107c76a4 | 1706 | } |
107c76a4 | 1707 | else |
17a06af5 RZ |
1708 | WRITE_VREG(DECODE_STOP_POS, udebug_flag); |
1709 | hw->old_udebug_flag = udebug_flag; | |
107c76a4 PY |
1710 | |
1711 | return r; | |
1712 | } | |
17a06af5 | 1713 | |
107c76a4 PY |
1714 | |
1715 | #ifdef AVSP_LONG_CABAC | |
1716 | static unsigned char es_write_addr[MAX_CODED_FRAME_SIZE] __aligned(64); | |
1717 | #endif | |
1718 | static void vavs_local_init(struct vdec_avs_hw_s *hw) | |
1719 | { | |
1720 | int i; | |
1721 | ||
17a06af5 RZ |
1722 | hw->vf_buf_num_used = vf_buf_num; |
1723 | ||
107c76a4 PY |
1724 | hw->vavs_ratio = hw->vavs_amstream_dec_info.ratio; |
1725 | ||
1726 | hw->avi_flag = (unsigned long) hw->vavs_amstream_dec_info.param; | |
1727 | ||
1728 | hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0; | |
1729 | ||
1730 | hw->throw_pb_flag = 1; | |
1731 | ||
1732 | hw->total_frame = 0; | |
1733 | hw->saved_resolution = 0; | |
1734 | hw->next_pts = 0; | |
1735 | ||
1736 | #ifdef DEBUG_PTS | |
1737 | hw->pts_hit = hw->pts_missed = hw->pts_i_hit = hw->pts_i_missed = 0; | |
1738 | #endif | |
1739 | INIT_KFIFO(hw->display_q); | |
1740 | INIT_KFIFO(hw->recycle_q); | |
1741 | INIT_KFIFO(hw->newframe_q); | |
1742 | ||
1743 | for (i = 0; i < VF_POOL_SIZE; i++) { | |
17a06af5 | 1744 | const struct vframe_s *vf = &hw->vfpool[i].vf; |
107c76a4 | 1745 | |
17a06af5 RZ |
1746 | hw->vfpool[i].vf.index = hw->vf_buf_num_used; |
1747 | hw->vfpool[i].vf.bufWidth = 1920; | |
1748 | hw->vfpool[i].detached = 0; | |
107c76a4 PY |
1749 | kfifo_put(&hw->newframe_q, vf); |
1750 | } | |
17a06af5 | 1751 | for (i = 0; i < hw->vf_buf_num_used; i++) |
107c76a4 PY |
1752 | hw->vfbuf_use[i] = 0; |
1753 | ||
1754 | /*cur_vfpool = vfpool;*/ | |
1755 | ||
1756 | if (hw->recover_flag == 1) | |
1757 | return; | |
1758 | ||
1759 | if (hw->mm_blk_handle) { | |
1760 | pr_info("decoder_bmmu_box_free\n"); | |
1761 | decoder_bmmu_box_free(hw->mm_blk_handle); | |
1762 | hw->mm_blk_handle = NULL; | |
1763 | } | |
1764 | ||
1765 | hw->mm_blk_handle = decoder_bmmu_box_alloc_box( | |
1766 | DRIVER_NAME, | |
1767 | 0, | |
1768 | MAX_BMMU_BUFFER_NUM, | |
1769 | 4 + PAGE_SHIFT, | |
1770 | CODEC_MM_FLAGS_CMA_CLEAR | | |
1771 | CODEC_MM_FLAGS_FOR_VDECODER); | |
1772 | if (hw->mm_blk_handle == NULL) | |
1773 | pr_info("Error, decoder_bmmu_box_alloc_box fail\n"); | |
1774 | ||
1775 | } | |
1776 | ||
1777 | static int vavs_vf_states(struct vframe_states *states, void *op_arg) | |
1778 | { | |
1779 | unsigned long flags; | |
1780 | struct vdec_avs_hw_s *hw = | |
1781 | (struct vdec_avs_hw_s *)op_arg; | |
1782 | ||
1783 | ||
1784 | spin_lock_irqsave(&lock, flags); | |
1785 | states->vf_pool_size = VF_POOL_SIZE; | |
1786 | states->buf_free_num = kfifo_len(&hw->newframe_q); | |
1787 | states->buf_avail_num = kfifo_len(&hw->display_q); | |
1788 | states->buf_recycle_num = kfifo_len(&hw->recycle_q); | |
1789 | if (step == 2) | |
1790 | states->buf_avail_num = 0; | |
1791 | spin_unlock_irqrestore(&lock, flags); | |
1792 | return 0; | |
1793 | } | |
1794 | ||
1795 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1796 | static void vavs_ppmgr_reset(void) | |
1797 | { | |
1798 | vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); | |
1799 | ||
1800 | vavs_local_init(ghw); | |
1801 | ||
1802 | pr_info("vavs: vf_ppmgr_reset\n"); | |
1803 | } | |
1804 | #endif | |
1805 | ||
1806 | static void vavs_local_reset(struct vdec_avs_hw_s *hw) | |
1807 | { | |
1808 | mutex_lock(&vavs_mutex); | |
1809 | hw->recover_flag = 1; | |
1810 | pr_info("error, local reset\n"); | |
1811 | amvdec_stop(); | |
1812 | msleep(100); | |
17a06af5 | 1813 | avs_vf_notify_receiver(hw, PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); |
107c76a4 PY |
1814 | vavs_local_init(hw); |
1815 | vavs_recover(hw); | |
1816 | ||
1817 | #ifdef ENABLE_USER_DATA | |
1818 | reset_userdata_fifo(1); | |
1819 | #endif | |
1820 | ||
1821 | amvdec_start(); | |
1822 | hw->recover_flag = 0; | |
1823 | #if 0 | |
1824 | error_watchdog_count = 0; | |
1825 | ||
1826 | pr_info("pc %x stream buf wp %x rp %x level %x\n", | |
1827 | READ_VREG(MPC_E), | |
1828 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
1829 | READ_VREG(VLD_MEM_VIFIFO_RP), | |
1830 | READ_VREG(VLD_MEM_VIFIFO_LEVEL)); | |
1831 | #endif | |
1832 | ||
1833 | ||
1834 | ||
1835 | mutex_unlock(&vavs_mutex); | |
1836 | } | |
1837 | ||
1838 | #if 0 | |
1839 | static struct work_struct fatal_error_wd_work; | |
1840 | static struct work_struct notify_work; | |
1841 | static atomic_t error_handler_run = ATOMIC_INIT(0); | |
1842 | #endif | |
1843 | static void vavs_fatal_error_handler(struct work_struct *work) | |
1844 | { | |
1845 | struct vdec_avs_hw_s *hw = | |
1846 | container_of(work, struct vdec_avs_hw_s, fatal_error_wd_work); | |
17a06af5 | 1847 | if (debug & AVS_DEBUG_OLD_ERROR_HANDLE) { |
107c76a4 PY |
1848 | mutex_lock(&vavs_mutex); |
1849 | pr_info("vavs fatal error reset !\n"); | |
1850 | amvdec_stop(); | |
1851 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1852 | vavs_ppmgr_reset(); | |
1853 | #else | |
1854 | vf_light_unreg_provider(&vavs_vf_prov); | |
1855 | vavs_local_init(hw); | |
1856 | vf_reg_provider(&vavs_vf_prov); | |
1857 | #endif | |
1858 | vavs_recover(hw); | |
1859 | amvdec_start(); | |
1860 | mutex_unlock(&vavs_mutex); | |
1861 | } else { | |
1862 | pr_info("avs fatal_error_handler\n"); | |
1863 | vavs_local_reset(hw); | |
1864 | } | |
1865 | atomic_set(&hw->error_handler_run, 0); | |
1866 | } | |
1867 | ||
1868 | static void vavs_notify_work(struct work_struct *work) | |
1869 | { | |
1870 | struct vdec_avs_hw_s *hw = | |
1871 | container_of(work, struct vdec_avs_hw_s, notify_work); | |
1872 | if (hw->fr_hint_status == VDEC_NEED_HINT) { | |
17a06af5 | 1873 | avs_vf_notify_receiver(hw, PROVIDER_NAME , |
107c76a4 PY |
1874 | VFRAME_EVENT_PROVIDER_FR_HINT , |
1875 | (void *)((unsigned long)hw->frame_dur)); | |
1876 | hw->fr_hint_status = VDEC_HINTED; | |
1877 | } | |
1878 | return; | |
1879 | } | |
1880 | ||
1881 | static void avs_set_clk(struct work_struct *work) | |
1882 | { | |
1883 | struct vdec_avs_hw_s *hw = | |
1884 | container_of(work, struct vdec_avs_hw_s, set_clk_work); | |
1885 | if (hw->frame_dur > 0 && hw->saved_resolution != | |
1886 | hw->frame_width * hw->frame_height * (96000 / hw->frame_dur)) { | |
1887 | int fps = 96000 / hw->frame_dur; | |
1888 | ||
1889 | hw->saved_resolution = hw->frame_width * hw->frame_height * fps; | |
1890 | if (firmware_sel == 0 && | |
17a06af5 | 1891 | (debug & AVS_DEBUG_USE_FULL_SPEED)) { |
107c76a4 PY |
1892 | vdec_source_changed(VFORMAT_AVS, |
1893 | 4096, 2048, 60); | |
1894 | } else { | |
1895 | vdec_source_changed(VFORMAT_AVS, | |
1896 | hw->frame_width, hw->frame_height, fps); | |
1897 | } | |
1898 | ||
1899 | } | |
1900 | } | |
1901 | ||
17a06af5 RZ |
1902 | #ifdef DEBUG_MULTI_WITH_AUTOMODE |
1903 | int delay_count = 0; | |
1904 | #endif | |
107c76a4 PY |
1905 | static void vavs_put_timer_func(unsigned long arg) |
1906 | { | |
1907 | struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)arg; | |
1908 | struct timer_list *timer = &hw->recycle_timer; | |
1909 | ||
1910 | #ifndef HANDLE_AVS_IRQ | |
1911 | vavs_isr(); | |
1912 | #endif | |
17a06af5 RZ |
1913 | #ifdef DEBUG_MULTI_WITH_AUTOMODE |
1914 | if (delay_count > 0) { | |
1915 | if (delay_count == 1) | |
1916 | amvdec_start(); | |
1917 | delay_count--; | |
1918 | } | |
1919 | #endif | |
107c76a4 PY |
1920 | if (READ_VREG(AVS_SOS_COUNT)) { |
1921 | if (!error_recovery_mode) { | |
1922 | #if 0 | |
17a06af5 | 1923 | if (debug & AVS_DEBUG_OLD_ERROR_HANDLE) { |
107c76a4 PY |
1924 | mutex_lock(&vavs_mutex); |
1925 | pr_info("vavs fatal error reset !\n"); | |
1926 | amvdec_stop(); | |
1927 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1928 | vavs_ppmgr_reset(); | |
1929 | #else | |
1930 | vf_light_unreg_provider(&vavs_vf_prov); | |
1931 | vavs_local_init(); | |
1932 | vf_reg_provider(&vavs_vf_prov); | |
1933 | #endif | |
1934 | vavs_recover(); | |
1935 | amvdec_start(); | |
1936 | mutex_unlock(&vavs_mutex); | |
1937 | } else { | |
1938 | vavs_local_reset(); | |
1939 | } | |
1940 | #else | |
1941 | if (!atomic_read(&hw->error_handler_run)) { | |
1942 | atomic_set(&hw->error_handler_run, 1); | |
1943 | pr_info("AVS_SOS_COUNT = %d\n", | |
1944 | READ_VREG(AVS_SOS_COUNT)); | |
1945 | pr_info("WP = 0x%x, RP = 0x%x, LEVEL = 0x%x, AVAIL = 0x%x, CUR_PTR = 0x%x\n", | |
1946 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
1947 | READ_VREG(VLD_MEM_VIFIFO_RP), | |
1948 | READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
1949 | READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL), | |
1950 | READ_VREG(VLD_MEM_VIFIFO_CURR_PTR)); | |
1951 | schedule_work(&hw->fatal_error_wd_work); | |
1952 | } | |
1953 | #endif | |
1954 | } | |
1955 | } | |
1956 | #if 0 | |
1957 | if (long_cabac_busy == 0 && | |
1958 | error_watchdog_threshold > 0 && | |
1959 | kfifo_len(&hw->display_q) == 0 && | |
1960 | READ_VREG(VLD_MEM_VIFIFO_LEVEL) > | |
1961 | error_watchdog_buf_threshold) { | |
1962 | pr_info("newq %d dispq %d recyq %d\r\n", | |
1963 | kfifo_len(&hw->newframe_q), | |
1964 | kfifo_len(&hw->display_q), | |
1965 | kfifo_len(&hw->recycle_q)); | |
1966 | pr_info("pc %x stream buf wp %x rp %x level %x\n", | |
1967 | READ_VREG(MPC_E), | |
1968 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
1969 | READ_VREG(VLD_MEM_VIFIFO_RP), | |
1970 | READ_VREG(VLD_MEM_VIFIFO_LEVEL)); | |
1971 | error_watchdog_count++; | |
1972 | if (error_watchdog_count >= error_watchdog_threshold) | |
1973 | vavs_local_reset(); | |
1974 | } else | |
1975 | error_watchdog_count = 0; | |
1976 | #endif | |
1977 | if (radr != 0) { | |
1978 | if (rval != 0) { | |
1979 | WRITE_VREG(radr, rval); | |
1980 | pr_info("WRITE_VREG(%x,%x)\n", radr, rval); | |
1981 | } else | |
1982 | pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); | |
1983 | rval = 0; | |
1984 | radr = 0; | |
1985 | } | |
1986 | if ((hw->ucode_pause_pos != 0) && | |
1987 | (hw->ucode_pause_pos != 0xffffffff) && | |
1988 | udebug_pause_pos != hw->ucode_pause_pos) { | |
1989 | hw->ucode_pause_pos = 0; | |
1990 | WRITE_VREG(DEBUG_REG1, 0); | |
1991 | } | |
1992 | ||
1993 | if (!kfifo_is_empty(&hw->recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) { | |
1994 | struct vframe_s *vf; | |
1995 | ||
1996 | if (kfifo_get(&hw->recycle_q, &vf)) { | |
17a06af5 | 1997 | if ((vf->index < hw->vf_buf_num_used) && |
107c76a4 PY |
1998 | (--hw->vfbuf_use[vf->index] == 0)) { |
1999 | debug_print(hw, PRINT_FLAG_DECODING, | |
2000 | "%s WRITE_VREG(AVS_BUFFERIN, 0x%x) for vf index of %d\n", | |
2001 | __func__, | |
2002 | ~(1 << vf->index), vf->index); | |
2003 | WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index)); | |
17a06af5 | 2004 | vf->index = hw->vf_buf_num_used; |
107c76a4 PY |
2005 | } |
2006 | kfifo_put(&hw->newframe_q, | |
2007 | (const struct vframe_s *)vf); | |
2008 | } | |
2009 | ||
2010 | } | |
2011 | ||
2012 | schedule_work(&hw->set_clk_work); | |
2013 | ||
2014 | timer->expires = jiffies + PUT_INTERVAL; | |
2015 | ||
2016 | add_timer(timer); | |
2017 | } | |
2018 | ||
2019 | #ifdef AVSP_LONG_CABAC | |
2020 | ||
2021 | static void long_cabac_do_work(struct work_struct *work) | |
2022 | { | |
2023 | int status = 0; | |
2024 | struct vdec_avs_hw_s *hw = gw; | |
2025 | #ifdef PERFORMANCE_DEBUG | |
2026 | pr_info("enter %s buf level (new %d, display %d, recycle %d)\r\n", | |
2027 | __func__, | |
2028 | kfifo_len(&hw->newframe_q), | |
2029 | kfifo_len(&hw->display_q), | |
2030 | kfifo_len(&hw->recycle_q) | |
2031 | ); | |
2032 | #endif | |
2033 | mutex_lock(&vavs_mutex); | |
2034 | long_cabac_busy = 1; | |
2035 | while (READ_VREG(LONG_CABAC_REQ)) { | |
2036 | if (process_long_cabac() < 0) { | |
2037 | status = -1; | |
2038 | break; | |
2039 | } | |
2040 | } | |
2041 | long_cabac_busy = 0; | |
2042 | mutex_unlock(&vavs_mutex); | |
2043 | #ifdef PERFORMANCE_DEBUG | |
2044 | pr_info("exit %s buf level (new %d, display %d, recycle %d)\r\n", | |
2045 | __func__, | |
2046 | kfifo_len(&hw->newframe_q), | |
2047 | kfifo_len(&hw->display_q), | |
2048 | kfifo_len(&hw->recycle_q) | |
2049 | ); | |
2050 | #endif | |
2051 | if (status < 0) { | |
2052 | pr_info("transcoding error, local reset\r\n"); | |
2053 | vavs_local_reset(hw); | |
2054 | } | |
2055 | ||
2056 | } | |
2057 | #endif | |
2058 | ||
2059 | #ifdef AVSP_LONG_CABAC | |
2060 | static void init_avsp_long_cabac_buf(void) | |
2061 | { | |
2062 | #if 0 | |
2063 | es_write_addr_phy = (unsigned long)codec_mm_alloc_for_dma( | |
2064 | "vavs", | |
2065 | PAGE_ALIGN(MAX_CODED_FRAME_SIZE)/PAGE_SIZE, | |
2066 | 0, CODEC_MM_FLAGS_DMA_CPU); | |
2067 | es_write_addr_virt = codec_mm_phys_to_virt(es_write_addr_phy); | |
2068 | ||
2069 | #elif 0 | |
2070 | es_write_addr_virt = | |
2071 | (void *)dma_alloc_coherent(amports_get_dma_device(), | |
2072 | MAX_CODED_FRAME_SIZE, &es_write_addr_phy, | |
2073 | GFP_KERNEL); | |
2074 | #else | |
2075 | /*es_write_addr_virt = kmalloc(MAX_CODED_FRAME_SIZE, GFP_KERNEL); | |
2076 | * es_write_addr_virt = (void *)__get_free_pages(GFP_KERNEL, | |
2077 | * get_order(MAX_CODED_FRAME_SIZE)); | |
2078 | */ | |
2079 | es_write_addr_virt = &es_write_addr[0]; | |
2080 | if (es_write_addr_virt == NULL) { | |
2081 | pr_err("%s: failed to alloc es_write_addr_virt buffer\n", | |
2082 | __func__); | |
2083 | return; | |
2084 | } | |
2085 | ||
2086 | es_write_addr_phy = dma_map_single(amports_get_dma_device(), | |
2087 | es_write_addr_virt, | |
2088 | MAX_CODED_FRAME_SIZE, DMA_BIDIRECTIONAL); | |
2089 | if (dma_mapping_error(amports_get_dma_device(), | |
2090 | es_write_addr_phy)) { | |
2091 | pr_err("%s: failed to map es_write_addr_virt buffer\n", | |
2092 | __func__); | |
2093 | /*kfree(es_write_addr_virt);*/ | |
2094 | es_write_addr_virt = NULL; | |
2095 | return; | |
2096 | } | |
2097 | #endif | |
2098 | ||
2099 | ||
2100 | #ifdef BITSTREAM_READ_TMP_NO_CACHE | |
2101 | bitstream_read_tmp = | |
2102 | (void *)dma_alloc_coherent(amports_get_dma_device(), | |
2103 | SVA_STREAM_BUF_SIZE, &bitstream_read_tmp_phy, | |
2104 | GFP_KERNEL); | |
2105 | ||
2106 | #else | |
2107 | ||
2108 | bitstream_read_tmp = kmalloc(SVA_STREAM_BUF_SIZE, GFP_KERNEL); | |
2109 | /*bitstream_read_tmp = (void *)__get_free_pages(GFP_KERNEL, | |
2110 | *get_order(MAX_CODED_FRAME_SIZE)); | |
2111 | */ | |
2112 | if (bitstream_read_tmp == NULL) { | |
2113 | pr_err("%s: failed to alloc bitstream_read_tmp buffer\n", | |
2114 | __func__); | |
2115 | return; | |
2116 | } | |
2117 | ||
2118 | bitstream_read_tmp_phy = dma_map_single(amports_get_dma_device(), | |
2119 | bitstream_read_tmp, | |
2120 | SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); | |
2121 | if (dma_mapping_error(amports_get_dma_device(), | |
2122 | bitstream_read_tmp_phy)) { | |
2123 | pr_err("%s: failed to map rpm buffer\n", __func__); | |
2124 | kfree(bitstream_read_tmp); | |
2125 | bitstream_read_tmp = NULL; | |
2126 | return; | |
2127 | } | |
2128 | #endif | |
2129 | } | |
2130 | #endif | |
2131 | ||
2132 | ||
2133 | static s32 vavs_init(struct vdec_avs_hw_s *hw) | |
2134 | { | |
2135 | int ret, size = -1; | |
2136 | struct firmware_s *fw; | |
2137 | u32 fw_size = 0x1000 * 16; | |
2138 | /*char *buf = vmalloc(0x1000 * 16); | |
2139 | ||
2140 | if (IS_ERR_OR_NULL(buf)) | |
2141 | return -ENOMEM; | |
2142 | */ | |
2143 | fw = vmalloc(sizeof(struct firmware_s) + fw_size); | |
2144 | if (IS_ERR_OR_NULL(fw)) | |
2145 | return -ENOMEM; | |
2146 | ||
2147 | pr_info("vavs_init\n"); | |
2148 | //init_timer(&hw->recycle_timer); | |
2149 | ||
2150 | //hw->stat |= STAT_TIMER_INIT; | |
2151 | ||
2152 | amvdec_enable(); | |
2153 | ||
2154 | //vdec_enable_DMC(NULL); | |
2155 | ||
2156 | vavs_local_init(hw); | |
2157 | ||
2158 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) | |
2159 | size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data); | |
2160 | else { | |
2161 | if (firmware_sel == 1) | |
2162 | size = get_firmware_data(VIDEO_DEC_AVS_NOCABAC, fw->data); | |
2163 | #ifdef AVSP_LONG_CABAC | |
2164 | else { | |
2165 | init_avsp_long_cabac_buf(); | |
2166 | size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data); | |
2167 | } | |
2168 | #endif | |
2169 | } | |
2170 | ||
2171 | if (size < 0) { | |
2172 | amvdec_disable(); | |
2173 | pr_err("get firmware fail."); | |
5c405a1b | 2174 | vfree(fw); |
107c76a4 PY |
2175 | return -1; |
2176 | } | |
2177 | ||
2178 | fw->len = size; | |
2179 | hw->fw = fw; | |
2180 | ||
2181 | if (hw->m_ins_flag) { | |
2182 | init_timer(&hw->check_timer); | |
2183 | hw->check_timer.data = (ulong) hw; | |
2184 | hw->check_timer.function = check_timer_func; | |
2185 | hw->check_timer.expires = jiffies + CHECK_INTERVAL; | |
2186 | ||
2187 | ||
2188 | //add_timer(&hw->check_timer); | |
2189 | hw->stat |= STAT_TIMER_ARM; | |
2190 | ||
2191 | INIT_WORK(&hw->work, vavs_work); | |
2192 | ||
2193 | hw->fw = fw; | |
2194 | return 0; | |
2195 | } | |
2196 | ||
2197 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) | |
2198 | ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, fw->data); | |
2199 | else if (firmware_sel == 1) | |
2200 | ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", fw->data); | |
2201 | else | |
2202 | ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, fw->data); | |
2203 | ||
2204 | if (ret < 0) { | |
2205 | amvdec_disable(); | |
2206 | /*vfree(buf);*/ | |
2207 | pr_err("AVS: the %s fw loading failed, err: %x\n", | |
2208 | tee_enabled() ? "TEE" : "local", ret); | |
2209 | return -EBUSY; | |
2210 | } | |
2211 | ||
2212 | /*vfree(buf);*/ | |
2213 | ||
2214 | hw->stat |= STAT_MC_LOAD; | |
2215 | ||
2216 | ||
2217 | /* enable AMRISC side protocol */ | |
2218 | ret = vavs_prot_init(hw); | |
2219 | if (ret < 0) | |
2220 | return ret; | |
2221 | ||
2222 | #ifdef HANDLE_AVS_IRQ | |
2223 | if (vdec_request_irq(VDEC_IRQ_1, vavs_isr, | |
2224 | "vavs-irq", (void *)hw)) { | |
2225 | amvdec_disable(); | |
2226 | pr_info("vavs irq register error.\n"); | |
2227 | return -ENOENT; | |
2228 | } | |
2229 | #endif | |
2230 | ||
2231 | hw->stat |= STAT_ISR_REG; | |
107c76a4 PY |
2232 | |
2233 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
2234 | vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, hw); | |
2235 | vf_reg_provider(&vavs_vf_prov); | |
17a06af5 | 2236 | avs_vf_notify_receiver(hw, PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); |
107c76a4 PY |
2237 | #else |
2238 | vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, hw); | |
2239 | vf_reg_provider(&vavs_vf_prov); | |
2240 | #endif | |
107c76a4 PY |
2241 | |
2242 | if (hw->vavs_amstream_dec_info.rate != 0) { | |
2243 | if (!hw->is_reset) | |
17a06af5 | 2244 | avs_vf_notify_receiver(hw, PROVIDER_NAME, |
107c76a4 PY |
2245 | VFRAME_EVENT_PROVIDER_FR_HINT, |
2246 | (void *)((unsigned long) | |
2247 | hw->vavs_amstream_dec_info.rate)); | |
2248 | hw->fr_hint_status = VDEC_HINTED; | |
2249 | } else | |
2250 | hw->fr_hint_status = VDEC_NEED_HINT; | |
2251 | ||
2252 | hw->stat |= STAT_VF_HOOK; | |
2253 | ||
2254 | hw->recycle_timer.data = (ulong)(hw); | |
2255 | hw->recycle_timer.function = vavs_put_timer_func; | |
2256 | hw->recycle_timer.expires = jiffies + PUT_INTERVAL; | |
107c76a4 PY |
2257 | |
2258 | add_timer(&hw->recycle_timer); | |
2259 | ||
2260 | hw->stat |= STAT_TIMER_ARM; | |
2261 | ||
2262 | #ifdef AVSP_LONG_CABAC | |
2263 | if (firmware_sel == 0) | |
2264 | INIT_WORK(&long_cabac_wd_work, long_cabac_do_work); | |
2265 | #endif | |
2266 | vdec_source_changed(VFORMAT_AVS, | |
2267 | 1920, 1080, 30); | |
17a06af5 RZ |
2268 | #ifdef DEBUG_MULTI_WITH_AUTOMODE |
2269 | if (start_decoding_delay == 0) | |
2270 | amvdec_start(); | |
2271 | else | |
2272 | delay_count = start_decoding_delay/10; | |
2273 | #else | |
107c76a4 | 2274 | amvdec_start(); |
17a06af5 | 2275 | #endif |
107c76a4 | 2276 | hw->stat |= STAT_VDEC_RUN; |
107c76a4 PY |
2277 | return 0; |
2278 | } | |
2279 | ||
2280 | static int amvdec_avs_probe(struct platform_device *pdev) | |
2281 | { | |
2282 | struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; | |
2283 | struct vdec_avs_hw_s *hw = NULL; | |
2284 | ||
2285 | if (pdata == NULL) { | |
2286 | pr_info("amvdec_avs memory resource undefined.\n"); | |
2287 | return -EFAULT; | |
2288 | } | |
2289 | ||
2290 | hw = (struct vdec_avs_hw_s *)devm_kzalloc(&pdev->dev, | |
2291 | sizeof(struct vdec_avs_hw_s), GFP_KERNEL); | |
2292 | if (hw == NULL) { | |
2293 | pr_info("\nammvdec_avs decoder driver alloc failed\n"); | |
2294 | return -ENOMEM; | |
2295 | } | |
2296 | pdata->private = hw; | |
2297 | ghw = hw; | |
2298 | atomic_set(&hw->error_handler_run, 0); | |
2299 | hw->m_ins_flag = 0; | |
2300 | ||
2301 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) | |
2302 | firmware_sel = 1; | |
2303 | ||
2304 | if (firmware_sel == 1) { | |
17a06af5 | 2305 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 | 2306 | vf_buf_num = 4; |
17a06af5 | 2307 | #endif |
107c76a4 PY |
2308 | canvas_base = 0; |
2309 | canvas_num = 3; | |
2310 | } else { | |
2311 | ||
2312 | canvas_base = 128; | |
2313 | canvas_num = 2; /*NV21*/ | |
2314 | } | |
2315 | ||
2316 | ||
2317 | if (pdata->sys_info) | |
2318 | hw->vavs_amstream_dec_info = *pdata->sys_info; | |
2319 | ||
2320 | pr_info("%s (%d,%d) %d\n", __func__, hw->vavs_amstream_dec_info.width, | |
2321 | hw->vavs_amstream_dec_info.height, hw->vavs_amstream_dec_info.rate); | |
2322 | ||
2323 | pdata->dec_status = vavs_dec_status; | |
2324 | pdata->set_isreset = vavs_set_isreset; | |
2325 | hw->is_reset = 0; | |
2326 | ||
2327 | pdata->user_data_read = NULL; | |
2328 | pdata->reset_userdata_fifo = NULL; | |
2329 | ||
2330 | vavs_vdec_info_init(hw); | |
2331 | ||
2332 | #ifdef ENABLE_USER_DATA | |
2333 | if (NULL == hw->user_data_buffer) { | |
2334 | hw->user_data_buffer = | |
2335 | dma_alloc_coherent(amports_get_dma_device(), | |
2336 | USER_DATA_SIZE, | |
2337 | &hw->user_data_buffer_phys, GFP_KERNEL); | |
2338 | if (!hw->user_data_buffer) { | |
2339 | pr_info("%s: Can not allocate hw->user_data_buffer\n", | |
2340 | __func__); | |
2341 | return -ENOMEM; | |
2342 | } | |
2343 | pr_debug("hw->user_data_buffer = 0x%p, hw->user_data_buffer_phys = 0x%x\n", | |
2344 | hw->user_data_buffer, (u32)hw->user_data_buffer_phys); | |
2345 | } | |
2346 | #endif | |
2347 | INIT_WORK(&hw->set_clk_work, avs_set_clk); | |
2348 | if (vavs_init(hw) < 0) { | |
2349 | pr_info("amvdec_avs init failed.\n"); | |
2350 | kfree(hw->gvs); | |
2351 | hw->gvs = NULL; | |
2352 | pdata->dec_status = NULL; | |
5c405a1b | 2353 | if (hw->fw) |
2354 | vfree(hw->fw); | |
2355 | hw->fw = NULL; | |
107c76a4 PY |
2356 | return -ENODEV; |
2357 | } | |
2358 | /*vdec = pdata;*/ | |
2359 | ||
2360 | INIT_WORK(&hw->fatal_error_wd_work, vavs_fatal_error_handler); | |
2361 | atomic_set(&hw->error_handler_run, 0); | |
2362 | #ifdef ENABLE_USER_DATA | |
2363 | INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); | |
2364 | #endif | |
2365 | INIT_WORK(&hw->notify_work, vavs_notify_work); | |
2366 | ||
2367 | return 0; | |
2368 | } | |
2369 | ||
2370 | static int amvdec_avs_remove(struct platform_device *pdev) | |
2371 | { | |
2372 | struct vdec_avs_hw_s *hw = ghw; | |
2373 | ||
2374 | cancel_work_sync(&hw->fatal_error_wd_work); | |
2375 | atomic_set(&hw->error_handler_run, 0); | |
2376 | #ifdef ENABLE_USER_DATA | |
2377 | cancel_work_sync(&hw->userdata_push_work); | |
2378 | #endif | |
2379 | cancel_work_sync(&hw->notify_work); | |
2380 | cancel_work_sync(&hw->set_clk_work); | |
2381 | if (hw->stat & STAT_VDEC_RUN) { | |
2382 | amvdec_stop(); | |
2383 | hw->stat &= ~STAT_VDEC_RUN; | |
2384 | } | |
2385 | ||
2386 | if (hw->stat & STAT_ISR_REG) { | |
2387 | vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id); | |
2388 | hw->stat &= ~STAT_ISR_REG; | |
2389 | } | |
2390 | ||
2391 | if (hw->stat & STAT_TIMER_ARM) { | |
2392 | del_timer_sync(&hw->recycle_timer); | |
2393 | hw->stat &= ~STAT_TIMER_ARM; | |
2394 | } | |
2395 | #ifdef AVSP_LONG_CABAC | |
2396 | if (firmware_sel == 0) { | |
2397 | mutex_lock(&vavs_mutex); | |
2398 | cancel_work_sync(&long_cabac_wd_work); | |
2399 | mutex_unlock(&vavs_mutex); | |
2400 | ||
2401 | if (es_write_addr_virt) { | |
2402 | #if 0 | |
2403 | codec_mm_free_for_dma("vavs", es_write_addr_phy); | |
2404 | #else | |
2405 | dma_unmap_single(amports_get_dma_device(), | |
2406 | es_write_addr_phy, | |
2407 | MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE); | |
2408 | /*kfree(es_write_addr_virt);*/ | |
2409 | es_write_addr_virt = NULL; | |
2410 | #endif | |
2411 | } | |
2412 | ||
2413 | #ifdef BITSTREAM_READ_TMP_NO_CACHE | |
2414 | if (bitstream_read_tmp) { | |
2415 | dma_free_coherent(amports_get_dma_device(), | |
2416 | SVA_STREAM_BUF_SIZE, bitstream_read_tmp, | |
2417 | bitstream_read_tmp_phy); | |
2418 | bitstream_read_tmp = NULL; | |
2419 | } | |
2420 | #else | |
2421 | if (bitstream_read_tmp) { | |
2422 | dma_unmap_single(amports_get_dma_device(), | |
2423 | bitstream_read_tmp_phy, | |
2424 | SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); | |
2425 | kfree(bitstream_read_tmp); | |
2426 | bitstream_read_tmp = NULL; | |
2427 | } | |
2428 | #endif | |
2429 | } | |
2430 | #endif | |
2431 | if (hw->stat & STAT_VF_HOOK) { | |
2432 | if (hw->fr_hint_status == VDEC_HINTED && !hw->is_reset) | |
17a06af5 | 2433 | avs_vf_notify_receiver(hw, PROVIDER_NAME, |
107c76a4 PY |
2434 | VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); |
2435 | hw->fr_hint_status = VDEC_NO_NEED_HINT; | |
2436 | vf_unreg_provider(&vavs_vf_prov); | |
2437 | hw->stat &= ~STAT_VF_HOOK; | |
2438 | } | |
2439 | ||
2440 | #ifdef ENABLE_USER_DATA | |
2441 | if (hw->user_data_buffer != NULL) { | |
2442 | dma_free_coherent( | |
2443 | amports_get_dma_device(), | |
2444 | USER_DATA_SIZE, | |
2445 | hw->user_data_buffer, | |
2446 | hw->user_data_buffer_phys); | |
2447 | hw->user_data_buffer = NULL; | |
2448 | hw->user_data_buffer_phys = 0; | |
2449 | } | |
2450 | #endif | |
2451 | ||
2452 | if (hw->fw) { | |
2453 | vfree(hw->fw); | |
2454 | hw->fw = NULL; | |
2455 | } | |
2456 | ||
2457 | amvdec_disable(); | |
2458 | //vdec_disable_DMC(NULL); | |
2459 | ||
2460 | hw->pic_type = 0; | |
2461 | if (hw->mm_blk_handle) { | |
2462 | decoder_bmmu_box_free(hw->mm_blk_handle); | |
2463 | hw->mm_blk_handle = NULL; | |
2464 | } | |
2465 | #ifdef DEBUG_PTS | |
2466 | pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, | |
2467 | hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); | |
2468 | pr_debug("total frame %d, hw->avi_flag %d, rate %d\n", hw->total_frame, hw->avi_flag, | |
2469 | hw->vavs_amstream_dec_info.rate); | |
2470 | #endif | |
2471 | kfree(hw->gvs); | |
2472 | hw->gvs = NULL; | |
2473 | ||
2474 | return 0; | |
2475 | } | |
2476 | ||
2477 | /****************************************/ | |
2478 | ||
2479 | static struct platform_driver amvdec_avs_driver = { | |
2480 | .probe = amvdec_avs_probe, | |
2481 | .remove = amvdec_avs_remove, | |
2482 | .driver = { | |
2483 | .name = DRIVER_NAME, | |
2484 | } | |
2485 | }; | |
2486 | ||
17a06af5 | 2487 | static void recycle_frames(struct vdec_avs_hw_s *hw); |
107c76a4 PY |
2488 | |
2489 | static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask) | |
2490 | { | |
2491 | struct vdec_avs_hw_s *hw = | |
2492 | (struct vdec_avs_hw_s *)vdec->private; | |
2493 | int ret = 1; | |
17a06af5 | 2494 | unsigned buf_busy_mask = (1 << hw->vf_buf_num_used) - 1; |
51b7cb07 | 2495 | |
2496 | if (work_pending(&hw->work) || | |
2497 | work_busy(&hw->work)) { | |
2498 | debug_print(hw, PRINT_FLAG_RUN_FLOW, | |
2499 | "avs work pending,not ready for run.\n"); | |
2500 | return 0; | |
2501 | } | |
2502 | ||
17a06af5 RZ |
2503 | #ifdef DEBUG_MULTI_FRAME_INS |
2504 | if ((DECODE_ID(hw) == 0) && run_count[0] > run_count[1] && | |
2505 | run_count[1] < max_run_count[1]) | |
2506 | return 0; | |
107c76a4 | 2507 | |
17a06af5 RZ |
2508 | if ((DECODE_ID(hw) == 1) && run_count[1] >= run_count[0] && |
2509 | run_count[0] < max_run_count[0]) | |
2510 | return 0; | |
2511 | ||
2512 | if (max_run_count[DECODE_ID(hw)] > 0 && | |
2513 | run_count[DECODE_ID(hw)] >= max_run_count[DECODE_ID(hw)]) | |
2514 | return 0; | |
2515 | #endif | |
b06eadf9 | 2516 | if (vdec_stream_based(vdec) && (hw->init_flag == 0) |
46448536 PY |
2517 | && pre_decode_buf_level != 0) { |
2518 | u32 rp, wp, level; | |
2519 | ||
2520 | rp = STBUF_READ(&vdec->vbuf, get_rp); | |
2521 | wp = STBUF_READ(&vdec->vbuf, get_wp); | |
2522 | if (wp < rp) | |
2523 | level = vdec->input.size + wp - rp; | |
2524 | else | |
2525 | level = wp - rp; | |
2526 | ||
2527 | if (level < pre_decode_buf_level) { | |
2528 | hw->not_run_ready++; | |
2529 | return 0; | |
2530 | } | |
2531 | } | |
2532 | ||
17a06af5 RZ |
2533 | if (hw->reset_decode_flag == 0 && |
2534 | hw->again_flag == 0 && | |
2535 | (hw->buf_status & buf_busy_mask) == buf_busy_mask) { | |
2536 | recycle_frames(hw); | |
2537 | if (hw->buf_recycle_status == 0) | |
2538 | ret = 0; | |
2539 | } | |
2540 | ||
2541 | if (again_threshold > 0 && | |
2542 | hw->pre_parser_wr_ptr != 0 && | |
2543 | hw->again_flag && | |
2544 | (!vdec_frame_based(vdec))) { | |
2545 | u32 parser_wr_ptr = | |
d631e9c2 | 2546 | STBUF_READ(&vdec->vbuf, get_rp); |
17a06af5 RZ |
2547 | if (parser_wr_ptr >= hw->pre_parser_wr_ptr && |
2548 | (parser_wr_ptr - hw->pre_parser_wr_ptr) < | |
2549 | again_threshold) { | |
2550 | int r = vdec_sync_input(vdec); | |
2551 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, | |
2552 | "%s buf lelvel:%x\n", __func__, r); | |
2553 | ret = 0; | |
2554 | } | |
2555 | } | |
107c76a4 PY |
2556 | |
2557 | if (ret) | |
2558 | hw->not_run_ready = 0; | |
2559 | else | |
2560 | hw->not_run_ready++; | |
2561 | ||
2562 | if (ret != 0) { | |
2563 | if (vdec->parallel_dec == 1) | |
2564 | return (unsigned long)(CORE_MASK_VDEC_1); | |
2565 | else | |
2566 | return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC); | |
2567 | } else | |
2568 | return 0; | |
2569 | } | |
2570 | ||
2571 | static void vavs_work(struct work_struct *work) | |
2572 | { | |
2573 | struct vdec_avs_hw_s *hw = | |
2574 | container_of(work, struct vdec_avs_hw_s, work); | |
2575 | struct vdec_s *vdec = hw_to_vdec(hw); | |
2576 | if (hw->dec_result != DEC_RESULT_AGAIN) | |
2577 | debug_print(hw, PRINT_FLAG_RUN_FLOW, | |
2578 | "ammvdec_avs: vavs_work,result=%d,status=%d\n", | |
2579 | hw->dec_result, hw_to_vdec(hw)->next_status); | |
2580 | hw->again_flag = 0; | |
2581 | if (hw->dec_result == DEC_RESULT_USERDATA) { | |
2582 | userdata_push_process(hw); | |
2583 | return; | |
2584 | } else if (hw->dec_result == DEC_RESULT_DONE) { | |
b06eadf9 | 2585 | |
107c76a4 PY |
2586 | if (!hw->ctx_valid) |
2587 | hw->ctx_valid = 1; | |
17a06af5 RZ |
2588 | #ifdef DEBUG_MULTI_FRAME_INS |
2589 | msleep(delay); | |
2590 | #endif | |
107c76a4 PY |
2591 | vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); |
2592 | } else if (hw->dec_result == DEC_RESULT_AGAIN | |
2593 | && (hw_to_vdec(hw)->next_status != | |
2594 | VDEC_STATUS_DISCONNECTED)) { | |
2595 | /* | |
2596 | stream base: stream buf empty or timeout | |
2597 | frame base: vdec_prepare_input fail | |
2598 | */ | |
2599 | hw->again_flag = 1; | |
2600 | if (!vdec_has_more_input(hw_to_vdec(hw))) { | |
2601 | hw->dec_result = DEC_RESULT_EOS; | |
2602 | vdec_schedule_work(&hw->work); | |
2603 | return; | |
2604 | } | |
2605 | } else if (hw->dec_result == DEC_RESULT_GET_DATA | |
2606 | && (hw_to_vdec(hw)->next_status != | |
2607 | VDEC_STATUS_DISCONNECTED)) { | |
2608 | if (!vdec_has_more_input(hw_to_vdec(hw))) { | |
2609 | hw->dec_result = DEC_RESULT_EOS; | |
2610 | vdec_schedule_work(&hw->work); | |
2611 | return; | |
2612 | } | |
2613 | debug_print(hw, PRINT_FLAG_VLD_DETAIL, | |
2614 | "%s DEC_RESULT_GET_DATA %x %x %x\n", | |
2615 | __func__, | |
2616 | READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
2617 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
2618 | READ_VREG(VLD_MEM_VIFIFO_RP)); | |
2619 | vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); | |
2620 | vdec_clean_input(hw_to_vdec(hw)); | |
2621 | return; | |
2622 | } else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) { | |
2623 | debug_print(hw, PRINT_FLAG_ERROR, | |
2624 | "%s: force exit\n", __func__); | |
2625 | if (hw->stat & STAT_ISR_REG) { | |
2626 | amvdec_stop(); | |
2627 | /*disable mbox interrupt */ | |
2628 | WRITE_VREG(ASSIST_MBOX1_MASK, 0); | |
2629 | vdec_free_irq(VDEC_IRQ_1, (void *)hw); | |
2630 | hw->stat &= ~STAT_ISR_REG; | |
2631 | } | |
2632 | } else if (hw->dec_result == DEC_RESULT_EOS) { | |
17a06af5 RZ |
2633 | debug_print(hw, PRINT_FLAG_DECODING, |
2634 | "%s: end of stream\n", __func__); | |
107c76a4 PY |
2635 | if (hw->stat & STAT_VDEC_RUN) { |
2636 | amvdec_stop(); | |
2637 | hw->stat &= ~STAT_VDEC_RUN; | |
2638 | } | |
2639 | hw->eos = 1; | |
2640 | vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk); | |
2641 | vdec_clean_input(hw_to_vdec(hw)); | |
2642 | } | |
2643 | if (hw->stat & STAT_VDEC_RUN) { | |
2644 | #if DEBUG_MULTI_FLAG == 1 | |
2645 | #else | |
2646 | amvdec_stop(); | |
2647 | #endif | |
2648 | hw->stat &= ~STAT_VDEC_RUN; | |
2649 | } | |
2650 | /*wait_vmmpeg12_search_done(hw);*/ | |
2651 | if (hw->stat & STAT_TIMER_ARM) { | |
2652 | del_timer_sync(&hw->check_timer); | |
2653 | hw->stat &= ~STAT_TIMER_ARM; | |
2654 | } | |
b06eadf9 P |
2655 | if (hw->dec_result == DEC_RESULT_DONE) |
2656 | hw->buf_recycle_status = 0; | |
2657 | debug_print(hw, PRINT_FLAG_RUN_FLOW, "work end %d\n", hw->dec_result); | |
107c76a4 PY |
2658 | if (vdec->parallel_dec == 1) |
2659 | vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1); | |
2660 | else | |
2661 | vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); | |
2662 | ||
2663 | if (hw->vdec_cb) { | |
2664 | hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg); | |
2665 | debug_print(hw, 0x80000, | |
2666 | "%s:\n", __func__); | |
2667 | } | |
2668 | } | |
2669 | ||
2670 | ||
2671 | static void reset_process_time(struct vdec_avs_hw_s *hw) | |
2672 | { | |
2673 | if (!hw->m_ins_flag) | |
2674 | return; | |
2675 | if (hw->start_process_time) { | |
2676 | unsigned process_time = | |
2677 | 1000 * (jiffies - hw->start_process_time) / HZ; | |
2678 | hw->start_process_time = 0; | |
2679 | if (process_time > max_process_time[DECODE_ID(hw)]) | |
2680 | max_process_time[DECODE_ID(hw)] = process_time; | |
2681 | } | |
2682 | } | |
2683 | static void start_process_time(struct vdec_avs_hw_s *hw) | |
2684 | { | |
2685 | hw->decode_timeout_count = 2; | |
2686 | hw->start_process_time = jiffies; | |
2687 | } | |
2688 | ||
2689 | static void handle_decoding_error(struct vdec_avs_hw_s *hw) | |
2690 | { | |
2691 | int i; | |
2692 | unsigned long flags; | |
2693 | struct vframe_s *vf; | |
2694 | spin_lock_irqsave(&lock, flags); | |
2695 | for (i = 0; i < VF_POOL_SIZE; i++) { | |
17a06af5 RZ |
2696 | vf = &hw->vfpool[i].vf; |
2697 | if (vf->index < hw->vf_buf_num_used) { | |
2698 | hw->vfpool[i].detached = 1; | |
2699 | hw->vfbuf_use[vf->index] = 0; | |
2700 | } | |
107c76a4 | 2701 | } |
17a06af5 RZ |
2702 | if (error_handle_policy & 0x2) { |
2703 | while (!kfifo_is_empty(&hw->display_q)) { | |
2704 | if (kfifo_get(&hw->display_q, &vf)) { | |
2705 | if (buf_of_vf(vf)->detached !=0) { | |
2706 | debug_print(hw, PRINT_FLAG_DECODING, | |
2707 | "%s recycle %d => newframe_q\n", | |
2708 | __func__, | |
2709 | vf->index); | |
2710 | vf->index = hw->vf_buf_num_used; | |
2711 | buf_of_vf(vf)->detached = 0; | |
2712 | kfifo_put(&hw->newframe_q, | |
2713 | (const struct vframe_s *)vf); | |
2714 | } | |
2715 | } | |
2716 | ||
2717 | } | |
2718 | } | |
2719 | clear_pts_buf(hw); | |
2720 | hw->decode_pic_count = 0; | |
107c76a4 | 2721 | hw->reset_decode_flag = 1; |
17a06af5 | 2722 | hw->pre_parser_wr_ptr = 0; |
107c76a4 | 2723 | hw->buf_status = 0; |
17a06af5 | 2724 | hw->throw_pb_flag = 1; |
107c76a4 PY |
2725 | spin_unlock_irqrestore(&lock, flags); |
2726 | } | |
2727 | ||
2728 | static void timeout_process(struct vdec_avs_hw_s *hw) | |
2729 | { | |
2730 | struct vdec_s *vdec = hw_to_vdec(hw); | |
2731 | amvdec_stop(); | |
17a06af5 RZ |
2732 | if (error_handle_policy & 0x1) { |
2733 | handle_decoding_error(hw); | |
2734 | } else { | |
2735 | vavs_save_regs(hw); | |
2736 | ||
2737 | if (hw->decode_pic_count == 0) | |
2738 | hw->decode_pic_count++; | |
2739 | } | |
2740 | hw->dec_result = DEC_RESULT_DONE; | |
2741 | ||
107c76a4 | 2742 | debug_print(hw, PRINT_FLAG_ERROR, |
1f676bcb PY |
2743 | "%s decoder timeout, status=%d, level=%d, bit_cnt=0x%x\n", |
2744 | __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VIFF_BIT_CNT)); | |
107c76a4 | 2745 | reset_process_time(hw); |
107c76a4 PY |
2746 | vdec_schedule_work(&hw->work); |
2747 | } | |
2748 | ||
2749 | ||
2750 | static void recycle_frame_bufferin(struct vdec_avs_hw_s *hw) | |
2751 | { | |
2752 | if (!kfifo_is_empty(&hw->recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) { | |
2753 | struct vframe_s *vf; | |
2754 | ||
2755 | if (kfifo_get(&hw->recycle_q, &vf)) { | |
17a06af5 RZ |
2756 | if (buf_of_vf(vf)->detached) { |
2757 | debug_print(hw, 0, | |
2758 | "%s recycle detached vf, index=%d detched %d used %d\n", | |
2759 | __func__, vf->index, | |
2760 | buf_of_vf(vf)->detached, | |
2761 | hw->vfbuf_use[vf->index]); | |
2762 | } | |
2763 | if ((vf->index < hw->vf_buf_num_used) && | |
2764 | (buf_of_vf(vf)->detached == 0) && | |
107c76a4 PY |
2765 | (--hw->vfbuf_use[vf->index] == 0)) { |
2766 | hw->buf_recycle_status |= (1 << vf->index); | |
2767 | WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index)); | |
2768 | debug_print(hw, PRINT_FLAG_DECODING, | |
2769 | "%s WRITE_VREG(AVS_BUFFERIN, 0x%x) for vf index of %d => buf_recycle_status 0x%x\n", | |
2770 | __func__, | |
2771 | READ_VREG(AVS_BUFFERIN), vf->index, | |
2772 | hw->buf_recycle_status); | |
2773 | } | |
17a06af5 RZ |
2774 | vf->index = hw->vf_buf_num_used; |
2775 | buf_of_vf(vf)->detached = 0; | |
107c76a4 PY |
2776 | kfifo_put(&hw->newframe_q, |
2777 | (const struct vframe_s *)vf); | |
2778 | } | |
2779 | ||
2780 | } | |
2781 | ||
2782 | } | |
2783 | ||
2784 | static void recycle_frames(struct vdec_avs_hw_s *hw) | |
2785 | { | |
2786 | while (!kfifo_is_empty(&hw->recycle_q)) { | |
2787 | struct vframe_s *vf; | |
2788 | ||
2789 | if (kfifo_get(&hw->recycle_q, &vf)) { | |
17a06af5 RZ |
2790 | if (buf_of_vf(vf)->detached) { |
2791 | debug_print(hw, 0, | |
2792 | "%s recycle detached vf, index=%d detched %d used %d\n", | |
2793 | __func__, vf->index, | |
2794 | buf_of_vf(vf)->detached, | |
2795 | hw->vfbuf_use[vf->index]); | |
2796 | } | |
2797 | ||
2798 | ||
2799 | if ((vf->index < hw->vf_buf_num_used) && | |
2800 | (buf_of_vf(vf)->detached == 0) && | |
107c76a4 PY |
2801 | (--hw->vfbuf_use[vf->index] == 0)) { |
2802 | hw->buf_recycle_status |= (1 << vf->index); | |
2803 | debug_print(hw, PRINT_FLAG_DECODING, | |
2804 | "%s for vf index of %d => buf_recycle_status 0x%x\n", | |
2805 | __func__, | |
2806 | vf->index, | |
2807 | hw->buf_recycle_status); | |
2808 | } | |
17a06af5 RZ |
2809 | vf->index = hw->vf_buf_num_used; |
2810 | buf_of_vf(vf)->detached = 0; | |
107c76a4 PY |
2811 | kfifo_put(&hw->newframe_q, |
2812 | (const struct vframe_s *)vf); | |
2813 | } | |
2814 | ||
2815 | } | |
2816 | ||
2817 | } | |
2818 | ||
2819 | ||
2820 | static void check_timer_func(unsigned long arg) | |
2821 | { | |
2822 | struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)arg; | |
2823 | struct vdec_s *vdec = hw_to_vdec(hw); | |
2824 | unsigned int timeout_val = decode_timeout_val; | |
2825 | unsigned long flags; | |
2826 | ||
2827 | if (hw->m_ins_flag && | |
17a06af5 | 2828 | (debug & |
107c76a4 PY |
2829 | DEBUG_WAIT_DECODE_DONE_WHEN_STOP) == 0 && |
2830 | vdec->next_status == | |
2831 | VDEC_STATUS_DISCONNECTED) { | |
2832 | hw->dec_result = DEC_RESULT_FORCE_EXIT; | |
2833 | vdec_schedule_work(&hw->work); | |
2834 | debug_print(hw, | |
2835 | 0, "vdec requested to be disconnected\n"); | |
2836 | return; | |
2837 | } | |
2838 | ||
2839 | /*recycle*/ | |
b06eadf9 | 2840 | if (!hw->m_ins_flag) { |
107c76a4 PY |
2841 | spin_lock_irqsave(&lock, flags); |
2842 | recycle_frame_bufferin(hw); | |
2843 | spin_unlock_irqrestore(&lock, flags); | |
2844 | } | |
17a06af5 RZ |
2845 | |
2846 | if (hw->m_ins_flag) { | |
2847 | if ((READ_VREG(AV_SCRATCH_5) & 0xf) != 0 && | |
2848 | (READ_VREG(AV_SCRATCH_5) & 0xff00) != 0){ | |
2849 | /*ucode buffer empty*/ | |
2850 | if ((kfifo_len(&hw->recycle_q) == 0) && | |
2851 | (kfifo_len(&hw->display_q) == 0)) { | |
2852 | debug_print(hw, | |
2853 | 0, "AV_SCRATCH_5=0x%x, recover ucode buffer_status\n", | |
2854 | READ_VREG(AV_SCRATCH_5)); | |
2855 | WRITE_VREG(AV_SCRATCH_5, 0x10); | |
2856 | /*let ucode to recover buffer_status*/ | |
2857 | } | |
2858 | } | |
2859 | } | |
2860 | if (radr != 0) { | |
107c76a4 PY |
2861 | if (rval != 0) { |
2862 | WRITE_VREG(radr, rval); | |
2863 | pr_info("WRITE_VREG(%x,%x)\n", radr, rval); | |
2864 | } else | |
2865 | pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr)); | |
2866 | rval = 0; | |
2867 | radr = 0; | |
2868 | } | |
17a06af5 RZ |
2869 | |
2870 | if (udebug_flag != hw->old_udebug_flag) { | |
2871 | WRITE_VREG(DECODE_STOP_POS, udebug_flag); | |
2872 | hw->old_udebug_flag = udebug_flag; | |
2873 | } | |
107c76a4 PY |
2874 | if (dbg_cmd != 0) { |
2875 | if (dbg_cmd == 1) { | |
2876 | int r = vdec_sync_input(vdec); | |
2877 | dbg_cmd = 0; | |
2878 | pr_info( | |
2879 | "vdec_sync_input=>0x%x, (lev %x, wp %x rp %x, prp %x, pwp %x)\n", | |
2880 | r, | |
2881 | READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
2882 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
2883 | READ_VREG(VLD_MEM_VIFIFO_RP), | |
d631e9c2 HZ |
2884 | STBUF_READ(&vdec->vbuf, get_rp), |
2885 | STBUF_READ(&vdec->vbuf, get_wp)); | |
107c76a4 PY |
2886 | } |
2887 | } | |
2888 | ||
17a06af5 | 2889 | if ((debug & DEBUG_FLAG_DISABLE_TIMEOUT) == 0 && |
107c76a4 PY |
2890 | (timeout_val > 0) && |
2891 | (hw->start_process_time > 0) && | |
2892 | ((1000 * (jiffies - hw->start_process_time) / HZ) | |
2893 | > timeout_val)) { | |
2894 | if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) { | |
2895 | if (hw->decode_timeout_count > 0) | |
2896 | hw->decode_timeout_count--; | |
2897 | if (hw->decode_timeout_count == 0) | |
2898 | timeout_process(hw); | |
2899 | } | |
2900 | hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL); | |
2901 | } | |
2902 | ||
2903 | if (READ_VREG(AVS_SOS_COUNT)) { | |
2904 | if (!error_recovery_mode) { | |
2905 | amvdec_stop(); | |
17a06af5 RZ |
2906 | if (error_handle_policy & 0x1) { |
2907 | handle_decoding_error(hw); | |
2908 | } else { | |
2909 | vavs_save_regs(hw); | |
2910 | ||
2911 | if (hw->decode_pic_count == 0) | |
2912 | hw->decode_pic_count++; | |
2913 | } | |
2914 | hw->dec_result = DEC_RESULT_DONE; | |
2915 | ||
107c76a4 PY |
2916 | debug_print(hw, PRINT_FLAG_ERROR, |
2917 | "%s decoder error, status=%d, level=%d, AVS_SOS_COUNT=0x%x\n", | |
2918 | __func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
2919 | READ_VREG(AVS_SOS_COUNT)); | |
107c76a4 | 2920 | reset_process_time(hw); |
107c76a4 PY |
2921 | vdec_schedule_work(&hw->work); |
2922 | } | |
2923 | } | |
2924 | ||
2925 | if ((hw->ucode_pause_pos != 0) && | |
2926 | (hw->ucode_pause_pos != 0xffffffff) && | |
2927 | udebug_pause_pos != hw->ucode_pause_pos) { | |
2928 | hw->ucode_pause_pos = 0; | |
2929 | WRITE_VREG(DEBUG_REG1, 0); | |
2930 | } | |
2931 | ||
2932 | if (vdec->next_status == VDEC_STATUS_DISCONNECTED) { | |
2933 | hw->dec_result = DEC_RESULT_FORCE_EXIT; | |
2934 | vdec_schedule_work(&hw->work); | |
2935 | pr_info("vdec requested to be disconnected\n"); | |
2936 | return; | |
2937 | } | |
2938 | ||
2939 | mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); | |
2940 | } | |
2941 | ||
2942 | static int avs_hw_ctx_restore(struct vdec_avs_hw_s *hw) | |
2943 | { | |
2944 | /*int r = 0;*/ | |
107c76a4 | 2945 | vavs_prot_init(hw); |
17a06af5 | 2946 | |
107c76a4 PY |
2947 | return 0; |
2948 | } | |
2949 | ||
2950 | static unsigned char get_data_check_sum | |
2951 | (struct vdec_avs_hw_s *hw, int size) | |
2952 | { | |
2953 | int jj; | |
2954 | int sum = 0; | |
2955 | u8 *data = NULL; | |
2956 | ||
2957 | if (!hw->chunk->block->is_mapped) | |
2958 | data = codec_mm_vmap(hw->chunk->block->start + | |
2959 | hw->chunk->offset, size); | |
2960 | else | |
2961 | data = ((u8 *)hw->chunk->block->start_virt) + | |
2962 | hw->chunk->offset; | |
2963 | ||
2964 | for (jj = 0; jj < size; jj++) | |
2965 | sum += data[jj]; | |
2966 | ||
2967 | if (!hw->chunk->block->is_mapped) | |
2968 | codec_mm_unmap_phyaddr(data); | |
2969 | return sum; | |
2970 | } | |
2971 | ||
2972 | static void run(struct vdec_s *vdec, unsigned long mask, | |
2973 | void (*callback)(struct vdec_s *, void *), | |
2974 | void *arg) | |
2975 | { | |
2976 | struct vdec_avs_hw_s *hw = | |
2977 | (struct vdec_avs_hw_s *)vdec->private; | |
2978 | int save_reg = READ_VREG(POWER_CTL_VLD); | |
2979 | int size, ret; | |
2980 | /* reset everything except DOS_TOP[1] and APB_CBUS[0]*/ | |
b06eadf9 | 2981 | debug_print(hw, PRINT_FLAG_RUN_FLOW,"run in\n"); |
d631e9c2 HZ |
2982 | if (vdec_stream_based(vdec)) { |
2983 | hw->pre_parser_wr_ptr = | |
2984 | STBUF_READ(&vdec->vbuf, get_wp); | |
2985 | } | |
17a06af5 | 2986 | #if 1 |
107c76a4 PY |
2987 | #if DEBUG_MULTI_FLAG > 0 |
2988 | if (hw->decode_pic_count == 0) { | |
2989 | #endif | |
2990 | WRITE_VREG(DOS_SW_RESET0, 0xfffffff0); | |
2991 | WRITE_VREG(DOS_SW_RESET0, 0); | |
2992 | WRITE_VREG(POWER_CTL_VLD, save_reg); | |
2993 | hw->run_count++; | |
17a06af5 | 2994 | run_count[DECODE_ID(hw)] = hw->run_count; |
107c76a4 PY |
2995 | vdec_reset_core(vdec); |
2996 | #if DEBUG_MULTI_FLAG > 0 | |
2997 | } | |
17a06af5 RZ |
2998 | #endif |
2999 | #else | |
3000 | vdec_reset_core(vdec); | |
107c76a4 PY |
3001 | #endif |
3002 | hw->vdec_cb_arg = arg; | |
3003 | hw->vdec_cb = callback; | |
3004 | ||
3005 | size = vdec_prepare_input(vdec, &hw->chunk); | |
3006 | if (debug & DEBUG_FLAG_PREPARE_MORE_INPUT) { | |
3007 | if (size < start_decode_buf_level) { | |
3008 | /*debug_print(hw, PRINT_FLAG_VLD_DETAIL, | |
3009 | "DEC_RESULT_AGAIN %x %x %x\n", | |
3010 | READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
3011 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
3012 | READ_VREG(VLD_MEM_VIFIFO_RP));*/ | |
3013 | ||
3014 | hw->input_empty++; | |
3015 | hw->dec_result = DEC_RESULT_AGAIN; | |
3016 | vdec_schedule_work(&hw->work); | |
3017 | return; | |
3018 | } | |
3019 | } else { | |
3020 | if (size < 0) { | |
3021 | hw->input_empty++; | |
3022 | hw->dec_result = DEC_RESULT_AGAIN; | |
3023 | vdec_schedule_work(&hw->work); | |
3024 | return; | |
3025 | } | |
3026 | } | |
3027 | if (input_frame_based(vdec)) { | |
3028 | u8 *data = NULL; | |
3029 | ||
3030 | if (!hw->chunk->block->is_mapped) | |
3031 | data = codec_mm_vmap(hw->chunk->block->start + | |
3032 | hw->chunk->offset, size); | |
3033 | else | |
3034 | data = ((u8 *)hw->chunk->block->start_virt) + | |
3035 | hw->chunk->offset; | |
3036 | ||
17a06af5 | 3037 | if (debug & PRINT_FLAG_RUN_FLOW |
107c76a4 PY |
3038 | ) { |
3039 | debug_print(hw, 0, | |
3040 | "%s decode_pic_count %d buf_recycle_status 0x%x: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n", | |
3041 | __func__, hw->decode_pic_count, | |
3042 | hw->buf_recycle_status, | |
3043 | size, get_data_check_sum(hw, size), | |
3044 | data[0], data[1], data[2], data[3], | |
3045 | data[4], data[5], data[size - 4], | |
3046 | data[size - 3], data[size - 2], | |
3047 | data[size - 1]); | |
3048 | } | |
17a06af5 | 3049 | if (debug & PRINT_FRAMEBASE_DATA |
107c76a4 PY |
3050 | ) { |
3051 | int jj; | |
3052 | ||
3053 | for (jj = 0; jj < size; jj++) { | |
3054 | if ((jj & 0xf) == 0) | |
3055 | debug_print(hw, | |
3056 | PRINT_FRAMEBASE_DATA, | |
3057 | "%06x:", jj); | |
3058 | debug_print(hw, | |
3059 | PRINT_FRAMEBASE_DATA, | |
3060 | "%02x ", data[jj]); | |
3061 | if (((jj + 1) & 0xf) == 0) | |
3062 | debug_print(hw, | |
3063 | PRINT_FRAMEBASE_DATA, | |
3064 | "\n"); | |
3065 | } | |
3066 | } | |
3067 | ||
3068 | if (!hw->chunk->block->is_mapped) | |
3069 | codec_mm_unmap_phyaddr(data); | |
3070 | } else | |
3071 | debug_print(hw, PRINT_FLAG_RUN_FLOW, | |
3072 | "%s decode_pic_count %d buf_recycle_status 0x%x: %x %x %x %x %x size 0x%x\n", | |
3073 | __func__, | |
3074 | hw->decode_pic_count, | |
3075 | hw->buf_recycle_status, | |
3076 | READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
3077 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
3078 | READ_VREG(VLD_MEM_VIFIFO_RP), | |
d631e9c2 HZ |
3079 | STBUF_READ(&vdec->vbuf, get_rp), |
3080 | STBUF_READ(&vdec->vbuf, get_wp), | |
107c76a4 PY |
3081 | size); |
3082 | ||
3083 | ||
3084 | hw->input_empty = 0; | |
3085 | debug_print(hw, PRINT_FLAG_RUN_FLOW, | |
3086 | "%s,%d, size=%d\n", __func__, __LINE__, size); | |
17a06af5 RZ |
3087 | |
3088 | /*vdec_enable_input(vdec); | |
3089 | need run after VC1_CONTROL_REG is configured | |
3090 | */ | |
107c76a4 PY |
3091 | hw->init_flag = 1; |
3092 | ||
3093 | if (hw->chunk) | |
3094 | debug_print(hw, PRINT_FLAG_RUN_FLOW, | |
3095 | "input chunk offset %d, size %d\n", | |
3096 | hw->chunk->offset, hw->chunk->size); | |
3097 | ||
3098 | hw->dec_result = DEC_RESULT_NONE; | |
3099 | /*vdec->mc_loaded = 0;*/ | |
3100 | if (vdec->mc_loaded) { | |
3101 | /*firmware have load before, | |
3102 | and not changes to another. | |
3103 | ignore reload. | |
3104 | */ | |
3105 | } else { | |
3106 | ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_AVS, "avs_multi", vdec, | |
3107 | hw->fw->data, hw->fw->len); | |
3108 | if (ret < 0) { | |
3109 | pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, | |
3110 | hw->fw->name, tee_enabled() ? "TEE" : "local", ret); | |
3111 | hw->dec_result = DEC_RESULT_FORCE_EXIT; | |
3112 | vdec_schedule_work(&hw->work); | |
3113 | return; | |
3114 | } | |
3115 | vdec->mc_loaded = 1; | |
3116 | vdec->mc_type = VFORMAT_AVS; | |
3117 | } | |
107c76a4 PY |
3118 | if (avs_hw_ctx_restore(hw) < 0) { |
3119 | hw->dec_result = DEC_RESULT_ERROR; | |
3120 | debug_print(hw, PRINT_FLAG_ERROR, | |
3121 | "ammvdec_avs: error HW context restore\n"); | |
3122 | vdec_schedule_work(&hw->work); | |
3123 | return; | |
3124 | } | |
17a06af5 RZ |
3125 | |
3126 | /* | |
3127 | This configureation of VC1_CONTROL_REG will | |
3128 | pop bits (even no data in the stream buffer) if input is enabled, | |
3129 | so it can only be configured before vdec_enable_input() is called. | |
3130 | So move this code from ucode to here | |
3131 | */ | |
3132 | #define DISABLE_DBLK_HCMD 0 | |
3133 | #define DISABLE_MC_HCMD 0 | |
3134 | WRITE_VREG(VC1_CONTROL_REG, (DISABLE_DBLK_HCMD<<6) | | |
3135 | (DISABLE_MC_HCMD<<5) | (1 << 7) | (0xc <<8) | (1<<14)); | |
1f676bcb PY |
3136 | if (vdec_frame_based(vdec)) { |
3137 | size = hw->chunk->size + | |
3138 | (hw->chunk->offset & (VDEC_FIFO_ALIGN - 1)); | |
3139 | } | |
3140 | ||
3141 | ||
17a06af5 RZ |
3142 | vdec_enable_input(vdec); |
3143 | /**/ | |
3144 | ||
107c76a4 PY |
3145 | /*wmb();*/ |
3146 | hw->stat |= STAT_MC_LOAD; | |
3147 | hw->last_vld_level = 0; | |
3148 | ||
3149 | debug_print(hw, PRINT_FLAG_DECODING, | |
3150 | "%s READ_VREG(AVS_BUFFERIN)=0x%x, recycle_q num %d\n", | |
3151 | __func__, READ_VREG(AVS_BUFFERIN), | |
3152 | kfifo_len(&hw->recycle_q)); | |
17a06af5 | 3153 | WRITE_VREG(VIFF_BIT_CNT, size * 8); |
1f676bcb | 3154 | |
17a06af5 RZ |
3155 | if (hw->reset_decode_flag) |
3156 | WRITE_VREG(DECODE_STATUS, 0); | |
3157 | else { | |
3158 | recycle_frames(hw); | |
3159 | avs_pts_check_in(hw, | |
3160 | hw->decode_pic_count & 0xffff, | |
3161 | hw->chunk); | |
3162 | ||
3163 | WRITE_VREG(DECODE_STATUS, | |
3164 | (hw->decode_pic_count & 0xffff) | | |
3165 | ((~hw->buf_recycle_status) << 16)); | |
107c76a4 | 3166 | } |
b06eadf9 | 3167 | |
107c76a4 | 3168 | hw->reset_decode_flag = 0; |
b06eadf9 | 3169 | //hw->decode_status_skip_pic_done_flag = 0; |
107c76a4 PY |
3170 | start_process_time(hw); |
3171 | #if DEBUG_MULTI_FLAG == 1 | |
3172 | if (hw->decode_pic_count > 0) | |
3173 | WRITE_VREG(DECODE_STATUS, 0xff); | |
3174 | else | |
3175 | #endif | |
3176 | amvdec_start(); | |
3177 | hw->stat |= STAT_VDEC_RUN; | |
3178 | ||
3179 | hw->stat |= STAT_TIMER_ARM; | |
3180 | ||
3181 | mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL); | |
3182 | } | |
3183 | ||
3184 | static void reset(struct vdec_s *vdec) | |
3185 | { | |
3186 | } | |
3187 | ||
3188 | static irqreturn_t vmavs_isr_thread_fn(struct vdec_s *vdec, int irq) | |
3189 | { | |
1f676bcb PY |
3190 | struct vdec_avs_hw_s *hw = |
3191 | (struct vdec_avs_hw_s *)vdec->private; | |
3192 | u32 reg; | |
3193 | struct vframe_s *vf = NULL; | |
3194 | u32 dur; | |
3195 | u32 repeat_count; | |
3196 | u32 picture_type; | |
3197 | u32 buffer_index; | |
3198 | u32 frame_size; | |
3199 | bool force_interlaced_frame = false; | |
3200 | unsigned int pts, pts_valid = 0, offset = 0; | |
3201 | u64 pts_us64; | |
3202 | u32 debug_tag; | |
3203 | u32 buffer_status_debug; | |
3204 | //struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)dev_id; | |
3205 | ||
3206 | /*if (debug & AVS_DEBUG_UCODE) { | |
3207 | if (READ_VREG(AV_SCRATCH_E) != 0) { | |
3208 | pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_E), | |
3209 | READ_VREG(AV_SCRATCH_D)); | |
3210 | WRITE_VREG(AV_SCRATCH_E, 0); | |
3211 | } | |
3212 | }*/ | |
3213 | ||
b06eadf9 P |
3214 | debug_print(hw, PRINT_FLAG_RUN_FLOW, "READ_VREG(AVS_BUFFEROUT) 0x%x, READ_VREG(DECODE_STATUS) 0x%x READ_VREG(AV_SCRATCH_N) 0x%x, READ_VREG(DEBUG_REG1) 0x%x\n", |
3215 | READ_VREG(AVS_BUFFEROUT),READ_VREG(DECODE_STATUS), READ_VREG(AV_SCRATCH_N), READ_VREG(DEBUG_REG1)); | |
3216 | ||
1f676bcb PY |
3217 | debug_tag = READ_VREG(DEBUG_REG1); |
3218 | buffer_status_debug = debug_tag >> 16; | |
3219 | debug_tag &= 0xffff; | |
3220 | /* if (debug_tag & 0x10000) { | |
3221 | int i; | |
3222 | dma_sync_single_for_cpu( | |
3223 | amports_get_dma_device(), | |
3224 | hw->lmem_phy_addr, | |
3225 | LMEM_BUF_SIZE, | |
3226 | DMA_FROM_DEVICE); | |
3227 | ||
3228 | debug_print(hw, 0, | |
3229 | "LMEM<tag %x>:\n", debug_tag); | |
3230 | ||
3231 | for (i = 0; i < 0x400; i += 4) { | |
3232 | int ii; | |
3233 | unsigned short *lmem_ptr = hw->lmem_addr; | |
3234 | if ((i & 0xf) == 0) | |
3235 | debug_print_cont(hw, 0, "%03x: ", i); | |
3236 | for (ii = 0; ii < 4; ii++) { | |
3237 | debug_print_cont(hw, 0, "%04x ", | |
3238 | lmem_ptr[i + 3 - ii]); | |
3239 | } | |
3240 | if (((i + ii) & 0xf) == 0) | |
3241 | debug_print_cont(hw, 0, "\n"); | |
3242 | } | |
3243 | ||
3244 | if (((udebug_pause_pos & 0xffff) | |
3245 | == (debug_tag & 0xffff)) && | |
3246 | (udebug_pause_decode_idx == 0 || | |
3247 | udebug_pause_decode_idx == hw->decode_pic_count) && | |
3248 | (udebug_pause_val == 0 || | |
3249 | udebug_pause_val == READ_VREG(DEBUG_REG2))) { | |
3250 | udebug_pause_pos &= 0xffff; | |
3251 | hw->ucode_pause_pos = udebug_pause_pos; | |
3252 | } | |
3253 | else if (debug_tag & 0x20000) | |
3254 | hw->ucode_pause_pos = 0xffffffff; | |
3255 | if (hw->ucode_pause_pos) | |
3256 | reset_process_time(hw); | |
3257 | else | |
3258 | WRITE_VREG(DEBUG_REG1, 0); | |
3259 | } else*/ if (debug_tag != 0) { | |
3260 | debug_print(hw, 1, | |
3261 | "dbg%x: %x buffer_status 0x%x l/w/r %x %x %x bitcnt %x AVAIL %x\n", | |
3262 | debug_tag, | |
3263 | READ_VREG(DEBUG_REG2), | |
3264 | buffer_status_debug, | |
3265 | READ_VREG(VLD_MEM_VIFIFO_LEVEL), | |
3266 | READ_VREG(VLD_MEM_VIFIFO_WP), | |
3267 | READ_VREG(VLD_MEM_VIFIFO_RP), | |
3268 | READ_VREG(VIFF_BIT_CNT), | |
3269 | READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL)); | |
3270 | ||
3271 | if (((udebug_pause_pos & 0xffff) | |
3272 | == (debug_tag & 0xffff)) && | |
3273 | (udebug_pause_decode_idx == 0 || | |
3274 | udebug_pause_decode_idx == hw->decode_pic_count) && | |
3275 | (udebug_pause_val == 0 || | |
3276 | udebug_pause_val == READ_VREG(DEBUG_REG2)) && | |
3277 | (udebug_pause_ins_id == 0 || | |
3278 | DECODE_ID(hw) == (udebug_pause_ins_id -1))) { | |
3279 | udebug_pause_pos &= 0xffff; | |
3280 | hw->ucode_pause_pos = udebug_pause_pos; | |
3281 | if (debug & DEBUG_PIC_DONE_WHEN_UCODE_PAUSE) { | |
3282 | hw->decode_pic_count++; | |
3283 | if ((hw->decode_pic_count & 0xffff) == 0) { | |
3284 | /*make ucode do not handle it as first picture*/ | |
3285 | hw->decode_pic_count++; | |
3286 | } | |
3287 | reset_process_time(hw); | |
3288 | hw->dec_result = DEC_RESULT_DONE; | |
3289 | amvdec_stop(); | |
3290 | vavs_save_regs(hw); | |
3291 | debug_print(hw, PRINT_FLAG_DECODING, | |
3292 | "%s ucode pause, force done, decode_pic_count = %d, bit_cnt=0x%x\n", | |
3293 | __func__, | |
3294 | hw->decode_pic_count, | |
3295 | READ_VREG(VIFF_BIT_CNT)); | |
3296 | vdec_schedule_work(&hw->work); | |
3297 | return IRQ_HANDLED; | |
3298 | } | |
3299 | } | |
3300 | if (hw->ucode_pause_pos) | |
3301 | reset_process_time(hw); | |
3302 | else | |
3303 | WRITE_VREG(DEBUG_REG1, 0); | |
3304 | return IRQ_HANDLED; | |
3305 | } else { | |
3306 | debug_print(hw, PRINT_FLAG_DECODING, | |
3307 | "%s decode_status 0x%x, buffer_status 0x%x\n", | |
3308 | __func__, | |
3309 | READ_VREG(DECODE_STATUS), | |
3310 | buffer_status_debug); | |
3311 | } | |
3312 | ||
3313 | #ifdef AVSP_LONG_CABAC | |
3314 | if (firmware_sel == 0 && READ_VREG(LONG_CABAC_REQ)) { | |
3315 | #ifdef PERFORMANCE_DEBUG | |
3316 | pr_info("%s:schedule long_cabac_wd_work\r\n", __func__); | |
3317 | #endif | |
3318 | pr_info("schedule long_cabac_wd_work and requested from %d\n", | |
3319 | (READ_VREG(LONG_CABAC_REQ) >> 8)&0xFF); | |
3320 | schedule_work(&long_cabac_wd_work); | |
3321 | } | |
3322 | #endif | |
3323 | ||
3324 | #ifdef ENABLE_USER_DATA | |
3325 | if (UserDataHandler(hw)) | |
3326 | return IRQ_HANDLED; | |
3327 | #endif | |
3328 | reg = READ_VREG(AVS_BUFFEROUT); | |
3329 | if (reg) { | |
3330 | unsigned short decode_pic_count | |
3331 | = READ_VREG(DECODE_PIC_COUNT); | |
3332 | debug_print(hw, PRINT_FLAG_DECODING, "AVS_BUFFEROUT=0x%x decode_pic_count %d\n", | |
3333 | reg, decode_pic_count); | |
3334 | if (pts_by_offset) { | |
3335 | offset = READ_VREG(AVS_OFFSET_REG); | |
3336 | debug_print(hw, PRINT_FLAG_DECODING, "AVS OFFSET=%x\n", offset); | |
36114cbd | 3337 | if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) { |
3338 | if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, &pts, | |
3339 | &frame_size, 0, &pts_us64) == 0) { | |
3340 | pts_valid = 1; | |
1f676bcb | 3341 | #ifdef DEBUG_PTS |
36114cbd | 3342 | hw->pts_hit++; |
1f676bcb | 3343 | #endif |
36114cbd | 3344 | } else { |
1f676bcb | 3345 | #ifdef DEBUG_PTS |
36114cbd | 3346 | hw->pts_missed++; |
1f676bcb | 3347 | #endif |
36114cbd | 3348 | } |
1f676bcb PY |
3349 | } |
3350 | } | |
3351 | ||
3352 | repeat_count = READ_VREG(AVS_REPEAT_COUNT); | |
3353 | #ifdef USE_DYNAMIC_BUF_NUM | |
3354 | buffer_index = | |
3355 | ((reg & 0x7) + | |
3356 | (((reg >> 8) & 0x3) << 3) - 1) & 0x1f; | |
3357 | #else | |
3358 | if (firmware_sel == 0) | |
3359 | buffer_index = | |
3360 | ((reg & 0x7) + | |
3361 | (((reg >> 8) & 0x3) << 3) - 1) & 0x1f; | |
3362 | else | |
3363 | buffer_index = | |
3364 | ((reg & 0x7) - 1) & 3; | |
3365 | #endif | |
3366 | picture_type = (reg >> 3) & 7; | |
3367 | #ifdef DEBUG_PTS | |
3368 | if (picture_type == I_PICTURE) { | |
3369 | /* pr_info("I offset 0x%x, pts_valid %d\n", | |
3370 | * offset, pts_valid); | |
3371 | */ | |
3372 | if (!pts_valid) | |
3373 | hw->pts_i_missed++; | |
3374 | else | |
3375 | hw->pts_i_hit++; | |
3376 | } | |
3377 | #endif | |
3378 | ||
3379 | if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE) | |
3380 | && hw->frame_width == 1920 && hw->frame_height == 1080) { | |
3381 | force_interlaced_frame = true; | |
3382 | } | |
3383 | ||
3384 | if (hw->throw_pb_flag && picture_type != I_PICTURE) { | |
3385 | ||
3386 | debug_print(hw, PRINT_FLAG_DECODING, | |
3387 | "%s WRITE_VREG(AVS_BUFFERIN, 0x%x) for throwing picture with type of %d\n", | |
3388 | __func__, | |
3389 | ~(1 << buffer_index), picture_type); | |
3390 | ||
3391 | WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index)); | |
3392 | } else if (reg & INTERLACE_FLAG || force_interlaced_frame) { /* interlace */ | |
3393 | hw->throw_pb_flag = 0; | |
3394 | ||
3395 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, | |
3396 | "interlace, picture type %d\n", | |
3397 | picture_type); | |
3398 | ||
3399 | if (kfifo_get(&hw->newframe_q, &vf) == 0) { | |
3400 | pr_info | |
3401 | ("fatal error, no available buffer slot."); | |
3402 | return IRQ_HANDLED; | |
3403 | } | |
3404 | set_frame_info(hw, vf, &dur); | |
3405 | vf->bufWidth = 1920; | |
3406 | hw->pic_type = 2; | |
3407 | if ((picture_type == I_PICTURE) && pts_valid) { | |
3408 | vf->pts = pts; | |
b06eadf9 | 3409 | vf->pts_us64 = pts_us64; |
1f676bcb PY |
3410 | if ((repeat_count > 1) && hw->avi_flag) { |
3411 | /* hw->next_pts = pts + | |
3412 | * (hw->vavs_amstream_dec_info.rate * | |
3413 | * repeat_count >> 1)*15/16; | |
3414 | */ | |
3415 | hw->next_pts = | |
3416 | pts + | |
3417 | (dur * repeat_count >> 1) * | |
3418 | 15 / 16; | |
3419 | } else | |
3420 | hw->next_pts = 0; | |
3421 | } else { | |
3422 | vf->pts = hw->next_pts; | |
b06eadf9 P |
3423 | if (vf->pts == 0) { |
3424 | vf->pts_us64 = 0; | |
3425 | } | |
1f676bcb PY |
3426 | if ((repeat_count > 1) && hw->avi_flag) { |
3427 | /* vf->duration = | |
3428 | * hw->vavs_amstream_dec_info.rate * | |
3429 | * repeat_count >> 1; | |
3430 | */ | |
3431 | vf->duration = dur * repeat_count >> 1; | |
3432 | if (hw->next_pts != 0) { | |
3433 | hw->next_pts += | |
3434 | ((vf->duration) - | |
3435 | ((vf->duration) >> 4)); | |
3436 | } | |
3437 | } else { | |
3438 | /* vf->duration = | |
3439 | * hw->vavs_amstream_dec_info.rate >> 1; | |
3440 | */ | |
3441 | vf->duration = dur >> 1; | |
3442 | hw->next_pts = 0; | |
3443 | } | |
3444 | } | |
3445 | vf->signal_type = 0; | |
3446 | vf->index = buffer_index; | |
3447 | vf->duration_pulldown = 0; | |
3448 | if (force_interlaced_frame) { | |
3449 | vf->type = VIDTYPE_INTERLACE_TOP; | |
3450 | }else{ | |
3451 | vf->type = | |
3452 | (reg & TOP_FIELD_FIRST_FLAG) | |
3453 | ? VIDTYPE_INTERLACE_TOP | |
3454 | : VIDTYPE_INTERLACE_BOTTOM; | |
3455 | } | |
3456 | #ifdef NV21 | |
3457 | vf->type |= VIDTYPE_VIU_NV21; | |
3458 | #endif | |
3459 | if (hw->m_ins_flag) { | |
3460 | vf->canvas0Addr = vf->canvas1Addr = -1; | |
3461 | vf->plane_num = 2; | |
3462 | ||
3463 | vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; | |
3464 | vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; | |
3465 | ||
3466 | vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; | |
3467 | vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; | |
3468 | } else | |
3469 | vf->canvas0Addr = vf->canvas1Addr = | |
3470 | index2canvas(buffer_index); | |
3471 | vf->type_original = vf->type; | |
3472 | ||
3473 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, | |
3474 | "buffer_index %d, canvas addr %x\n", | |
3475 | buffer_index, vf->canvas0Addr); | |
b06eadf9 P |
3476 | vf->pts = (pts_valid)?pts:0; |
3477 | //vf->pts_us64 = (pts_valid) ? pts_us64 : 0; | |
1f676bcb PY |
3478 | hw->vfbuf_use[buffer_index]++; |
3479 | vf->mem_handle = | |
3480 | decoder_bmmu_box_get_mem_handle( | |
3481 | hw->mm_blk_handle, | |
3482 | buffer_index); | |
3483 | ||
3484 | if (hw->m_ins_flag && vdec_frame_based(hw_to_vdec(hw))) | |
3485 | set_vframe_pts(hw, decode_pic_count, vf); | |
b06eadf9 | 3486 | |
36114cbd | 3487 | if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) { |
3488 | vf->pts_us64 = offset; | |
3489 | vf->pts = 0; | |
3490 | } | |
b06eadf9 P |
3491 | |
3492 | debug_print(hw, PRINT_FLAG_PTS, | |
3493 | "interlace1 vf->pts = %d, vf->pts_us64 = %lld, pts_valid = %d\n", vf->pts, vf->pts_us64, pts_valid); | |
1f676bcb PY |
3494 | kfifo_put(&hw->display_q, |
3495 | (const struct vframe_s *)vf); | |
3496 | avs_vf_notify_receiver(hw, PROVIDER_NAME, | |
3497 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
3498 | NULL); | |
3499 | ||
3500 | if (kfifo_get(&hw->newframe_q, &vf) == 0) { | |
3501 | pr_info("fatal error, no available buffer slot."); | |
3502 | return IRQ_HANDLED; | |
3503 | } | |
3504 | set_frame_info(hw, vf, &dur); | |
3505 | vf->bufWidth = 1920; | |
3506 | if (force_interlaced_frame) | |
3507 | vf->pts = 0; | |
3508 | else | |
3509 | vf->pts = hw->next_pts; | |
b06eadf9 P |
3510 | |
3511 | if (vf->pts == 0) { | |
3512 | vf->pts_us64 = 0; | |
3513 | } | |
3514 | ||
1f676bcb PY |
3515 | if ((repeat_count > 1) && hw->avi_flag) { |
3516 | /* vf->duration = hw->vavs_amstream_dec_info.rate * | |
3517 | * repeat_count >> 1; | |
3518 | */ | |
3519 | vf->duration = dur * repeat_count >> 1; | |
3520 | if (hw->next_pts != 0) { | |
3521 | hw->next_pts += | |
3522 | ((vf->duration) - | |
3523 | ((vf->duration) >> 4)); | |
3524 | } | |
3525 | } else { | |
3526 | /* vf->duration = hw->vavs_amstream_dec_info.rate | |
3527 | * >> 1; | |
3528 | */ | |
3529 | vf->duration = dur >> 1; | |
3530 | hw->next_pts = 0; | |
3531 | } | |
3532 | vf->signal_type = 0; | |
3533 | vf->index = buffer_index; | |
3534 | vf->duration_pulldown = 0; | |
3535 | if (force_interlaced_frame) { | |
3536 | vf->type = VIDTYPE_INTERLACE_BOTTOM; | |
3537 | } else { | |
3538 | vf->type = | |
3539 | (reg & TOP_FIELD_FIRST_FLAG) ? | |
3540 | VIDTYPE_INTERLACE_BOTTOM : | |
3541 | VIDTYPE_INTERLACE_TOP; | |
3542 | } | |
3543 | #ifdef NV21 | |
3544 | vf->type |= VIDTYPE_VIU_NV21; | |
3545 | #endif | |
3546 | if (hw->m_ins_flag) { | |
3547 | vf->canvas0Addr = vf->canvas1Addr = -1; | |
3548 | vf->plane_num = 2; | |
3549 | ||
3550 | vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; | |
3551 | vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; | |
3552 | ||
3553 | vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; | |
3554 | vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; | |
3555 | } else | |
3556 | vf->canvas0Addr = vf->canvas1Addr = | |
3557 | index2canvas(buffer_index); | |
3558 | vf->type_original = vf->type; | |
3559 | vf->pts_us64 = 0; | |
3560 | hw->vfbuf_use[buffer_index]++; | |
3561 | vf->mem_handle = | |
3562 | decoder_bmmu_box_get_mem_handle( | |
3563 | hw->mm_blk_handle, | |
3564 | buffer_index); | |
3565 | ||
3566 | if (hw->m_ins_flag && vdec_frame_based(hw_to_vdec(hw))) | |
3567 | set_vframe_pts(hw, decode_pic_count, vf); | |
36114cbd | 3568 | |
3569 | if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) { | |
3570 | vf->pts_us64 = offset; | |
3571 | vf->pts = 0; | |
3572 | } | |
b06eadf9 P |
3573 | debug_print(hw, PRINT_FLAG_PTS, |
3574 | "interlace2 vf->pts = %d, vf->pts_us64 = %lld, pts_valid = %d\n", vf->pts, vf->pts_us64, pts_valid); | |
1f676bcb PY |
3575 | kfifo_put(&hw->display_q, |
3576 | (const struct vframe_s *)vf); | |
3577 | avs_vf_notify_receiver(hw, PROVIDER_NAME, | |
3578 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
3579 | NULL); | |
3580 | hw->total_frame++; | |
3581 | } else { /* progressive */ | |
3582 | hw->throw_pb_flag = 0; | |
3583 | ||
3584 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, | |
3585 | "progressive picture type %d\n", | |
3586 | picture_type); | |
3587 | if (kfifo_get(&hw->newframe_q, &vf) == 0) { | |
3588 | pr_info | |
3589 | ("fatal error, no available buffer slot."); | |
3590 | return IRQ_HANDLED; | |
3591 | } | |
3592 | set_frame_info(hw, vf, &dur); | |
3593 | vf->bufWidth = 1920; | |
3594 | hw->pic_type = 1; | |
3595 | ||
3596 | if ((picture_type == I_PICTURE) && pts_valid) { | |
3597 | vf->pts = pts; | |
3598 | if ((repeat_count > 1) && hw->avi_flag) { | |
3599 | /* hw->next_pts = pts + | |
3600 | * (hw->vavs_amstream_dec_info.rate * | |
3601 | * repeat_count)*15/16; | |
3602 | */ | |
3603 | hw->next_pts = | |
3604 | pts + | |
3605 | (dur * repeat_count) * 15 / 16; | |
3606 | } else | |
3607 | hw->next_pts = 0; | |
3608 | } else { | |
3609 | vf->pts = hw->next_pts; | |
b06eadf9 P |
3610 | if (vf->pts == 0) { |
3611 | vf->pts_us64 = 0; | |
3612 | } | |
1f676bcb PY |
3613 | if ((repeat_count > 1) && hw->avi_flag) { |
3614 | /* vf->duration = | |
3615 | * hw->vavs_amstream_dec_info.rate * | |
3616 | * repeat_count; | |
3617 | */ | |
3618 | vf->duration = dur * repeat_count; | |
3619 | if (hw->next_pts != 0) { | |
3620 | hw->next_pts += | |
3621 | ((vf->duration) - | |
3622 | ((vf->duration) >> 4)); | |
3623 | } | |
3624 | } else { | |
3625 | /* vf->duration = | |
3626 | * hw->vavs_amstream_dec_info.rate; | |
3627 | */ | |
3628 | vf->duration = dur; | |
3629 | hw->next_pts = 0; | |
3630 | } | |
3631 | } | |
3632 | vf->signal_type = 0; | |
3633 | vf->index = buffer_index; | |
3634 | vf->duration_pulldown = 0; | |
3635 | vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; | |
3636 | #ifdef NV21 | |
3637 | vf->type |= VIDTYPE_VIU_NV21; | |
3638 | #endif | |
3639 | if (hw->m_ins_flag) { | |
3640 | vf->canvas0Addr = vf->canvas1Addr = -1; | |
3641 | vf->plane_num = 2; | |
3642 | ||
3643 | vf->canvas0_config[0] = hw->canvas_config[buffer_index][0]; | |
3644 | vf->canvas0_config[1] = hw->canvas_config[buffer_index][1]; | |
3645 | ||
3646 | vf->canvas1_config[0] = hw->canvas_config[buffer_index][0]; | |
3647 | vf->canvas1_config[1] = hw->canvas_config[buffer_index][1]; | |
3648 | } else | |
3649 | vf->canvas0Addr = vf->canvas1Addr = | |
3650 | index2canvas(buffer_index); | |
3651 | vf->type_original = vf->type; | |
3652 | ||
b06eadf9 P |
3653 | vf->pts = (pts_valid)?pts:0; |
3654 | //vf->pts_us64 = (pts_valid) ? pts_us64 : 0; | |
1f676bcb PY |
3655 | debug_print(hw, PRINT_FLAG_VFRAME_DETAIL, |
3656 | "buffer_index %d, canvas addr %x\n", | |
3657 | buffer_index, vf->canvas0Addr); | |
b06eadf9 P |
3658 | debug_print(hw, PRINT_FLAG_PTS, |
3659 | "progressive vf->pts = %d, vf->pts_us64 = %lld, pts_valid = %d\n", vf->pts, vf->pts_us64, pts_valid); | |
1f676bcb PY |
3660 | hw->vfbuf_use[buffer_index]++; |
3661 | vf->mem_handle = | |
3662 | decoder_bmmu_box_get_mem_handle( | |
3663 | hw->mm_blk_handle, | |
3664 | buffer_index); | |
3665 | ||
3666 | if (hw->m_ins_flag && vdec_frame_based(hw_to_vdec(hw))) | |
3667 | set_vframe_pts(hw, decode_pic_count, vf); | |
36114cbd | 3668 | |
3669 | if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) { | |
3670 | vf->pts_us64 = offset; | |
3671 | vf->pts = 0; | |
3672 | } | |
85193e3c | 3673 | vdec_vframe_ready(hw_to_vdec(hw), vf); |
1f676bcb PY |
3674 | kfifo_put(&hw->display_q, |
3675 | (const struct vframe_s *)vf); | |
3676 | avs_vf_notify_receiver(hw, PROVIDER_NAME, | |
3677 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
3678 | NULL); | |
3679 | hw->total_frame++; | |
3680 | } | |
3681 | ||
3682 | /*count info*/ | |
3683 | vdec_count_info(hw->gvs, 0, offset); | |
4cd99df0 | 3684 | if (offset) { |
3685 | if (picture_type == I_PICTURE) { | |
3686 | hw->gvs->i_decoded_frames++; | |
3687 | } else if (picture_type == P_PICTURE) { | |
3688 | hw->gvs->p_decoded_frames++; | |
3689 | } else if (picture_type == B_PICTURE) { | |
3690 | hw->gvs->b_decoded_frames++; | |
3691 | } | |
3692 | } | |
1f676bcb PY |
3693 | avs_update_gvs(hw); |
3694 | vdec_fill_vdec_frame(hw_to_vdec(hw), NULL, hw->gvs, vf, 0); | |
85193e3c | 3695 | |
1f676bcb PY |
3696 | /* pr_info("PicType = %d, PTS = 0x%x\n", |
3697 | * picture_type, vf->pts); | |
3698 | */ | |
3699 | WRITE_VREG(AVS_BUFFEROUT, 0); | |
3700 | } | |
3701 | //WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); | |
3702 | ||
3703 | ||
3704 | if (hw->m_ins_flag) { | |
3705 | u32 status_reg = READ_VREG(DECODE_STATUS); | |
3706 | u32 decode_status = status_reg & 0xff; | |
3707 | if (hw->dec_result == DEC_RESULT_DONE || | |
3708 | hw->dec_result == DEC_RESULT_AGAIN) { | |
3709 | debug_print(hw, PRINT_FLAG_DECODING, | |
3710 | "%s !!! READ_VREG(DECODE_STATUS) = 0x%x, decode_status 0x%x, buf_status 0x%x, dec_result = 0x%x, decode_pic_count = %d bit_cnt=0x%x\n", | |
3711 | __func__, status_reg, decode_status, | |
3712 | hw->buf_status, | |
3713 | hw->dec_result, hw->decode_pic_count, | |
3714 | READ_VREG(VIFF_BIT_CNT)); | |
3715 | return IRQ_HANDLED; | |
3716 | } else if (decode_status == DECODE_STATUS_PIC_DONE || | |
3717 | decode_status == DECODE_STATUS_SKIP_PIC_DONE) { | |
3718 | hw->buf_status = (status_reg >> 16) & 0xffff; | |
3719 | if (decode_status == DECODE_STATUS_SKIP_PIC_DONE) { | |
3720 | hw->decode_status_skip_pic_done_flag = 1; | |
3721 | hw->decode_decode_cont_start_code = (status_reg >> 8) & 0xff; | |
b06eadf9 P |
3722 | } else |
3723 | hw->decode_status_skip_pic_done_flag = 0; | |
1f676bcb PY |
3724 | hw->decode_pic_count++; |
3725 | if ((hw->decode_pic_count & 0xffff) == 0) { | |
3726 | /*make ucode do not handle it as first picture*/ | |
3727 | hw->decode_pic_count++; | |
3728 | } | |
3729 | reset_process_time(hw); | |
3730 | hw->dec_result = DEC_RESULT_DONE; | |
3731 | #if DEBUG_MULTI_FLAG == 1 | |
3732 | WRITE_VREG(DECODE_STATUS, 0); | |
3733 | #else | |
3734 | amvdec_stop(); | |
3735 | #endif | |
3736 | vavs_save_regs(hw); | |
3737 | debug_print(hw, PRINT_FLAG_DECODING, | |
3738 | "%s %s, READ_VREG(DECODE_STATUS) = 0x%x, decode_status 0x%x, buf_status 0x%x, dec_result = 0x%x, decode_pic_count = %d, bit_cnt=0x%x\n", | |
3739 | __func__, | |
3740 | (decode_status == DECODE_STATUS_PIC_DONE) ? | |
3741 | "DECODE_STATUS_PIC_DONE" : "DECODE_STATUS_SKIP_PIC_DONE", | |
3742 | status_reg, decode_status, | |
3743 | hw->buf_status, | |
3744 | hw->dec_result, hw->decode_pic_count, | |
3745 | READ_VREG(VIFF_BIT_CNT)); | |
3746 | vdec_schedule_work(&hw->work); | |
3747 | return IRQ_HANDLED; | |
3748 | } else if (decode_status == DECODE_STATUS_DECODE_BUF_EMPTY || | |
3749 | decode_status == DECODE_STATUS_SEARCH_BUF_EMPTY) { | |
3750 | hw->buf_status = (status_reg >> 16) & 0xffff; | |
3751 | reset_process_time(hw); | |
3752 | #if DEBUG_MULTI_FLAG == 1 | |
3753 | WRITE_VREG(DECODE_STATUS, 0); | |
3754 | #else | |
3755 | amvdec_stop(); | |
3756 | #endif | |
3757 | if (vdec_frame_based(hw_to_vdec(hw))) { | |
3758 | hw->dec_result = DEC_RESULT_DONE; | |
3759 | if (hw->decode_pic_count == 0) { | |
3760 | hw->decode_pic_count++; | |
3761 | } | |
3762 | vavs_save_regs(hw); | |
3763 | } else | |
3764 | hw->dec_result = DEC_RESULT_AGAIN; | |
3765 | ||
3766 | debug_print(hw, PRINT_FLAG_DECODING, | |
b06eadf9 | 3767 | "%s BUF_EMPTY, READ_VREG(DECODE_STATUS) = 0x%x, decode_status 0x%x, buf_status 0x%x, scratch_8 (AVS_BUFFERIN) 0x%x, dec_result = 0x%x, decode_pic_count = %d, bit_cnt=0x%x, hw->decode_status_skip_pic_done_flag = %d, hw->decode_decode_cont_start_code = 0x%x\n", |
1f676bcb PY |
3768 | __func__, status_reg, decode_status, |
3769 | hw->buf_status, | |
3770 | hw->reg_scratch_8, | |
3771 | hw->dec_result, hw->decode_pic_count, | |
b06eadf9 | 3772 | READ_VREG(VIFF_BIT_CNT), hw->decode_status_skip_pic_done_flag, hw->decode_decode_cont_start_code); |
1f676bcb PY |
3773 | vdec_schedule_work(&hw->work); |
3774 | return IRQ_HANDLED; | |
3775 | } | |
3776 | } | |
3777 | ||
3778 | ||
3779 | #ifdef HANDLE_AVS_IRQ | |
3780 | return IRQ_HANDLED; | |
3781 | #else | |
3782 | return; | |
3783 | #endif | |
107c76a4 PY |
3784 | } |
3785 | ||
1f676bcb | 3786 | |
107c76a4 PY |
3787 | static irqreturn_t vmavs_isr(struct vdec_s *vdec, int irq) |
3788 | { | |
107c76a4 | 3789 | |
1f676bcb PY |
3790 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); |
3791 | ||
3792 | return IRQ_WAKE_THREAD; | |
3793 | //return vavs_isr(0, hw); | |
107c76a4 PY |
3794 | |
3795 | } | |
3796 | ||
3797 | static void vmavs_dump_state(struct vdec_s *vdec) | |
3798 | { | |
3799 | struct vdec_avs_hw_s *hw = | |
3800 | (struct vdec_avs_hw_s *)vdec->private; | |
17a06af5 | 3801 | int i; |
107c76a4 PY |
3802 | debug_print(hw, 0, |
3803 | "====== %s\n", __func__); | |
3804 | ||
3805 | debug_print(hw, 0, | |
3806 | "width/height (%d/%d), dur %d\n", | |
3807 | hw->frame_width, | |
3808 | hw->frame_height, | |
3809 | hw->frame_dur | |
3810 | ); | |
3811 | ||
3812 | debug_print(hw, 0, | |
17a06af5 | 3813 | "is_framebase(%d), decode_status 0x%x, buf_status 0x%x, buf_recycle_status 0x%x, throw %d, eos %d, state 0x%x, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n", |
107c76a4 PY |
3814 | vdec_frame_based(vdec), |
3815 | READ_VREG(DECODE_STATUS) & 0xff, | |
3816 | hw->buf_status, | |
3817 | hw->buf_recycle_status, | |
17a06af5 | 3818 | hw->throw_pb_flag, |
107c76a4 PY |
3819 | hw->eos, |
3820 | hw->stat, | |
3821 | hw->dec_result, | |
3822 | hw->decode_pic_count, | |
3823 | hw->display_frame_count, | |
3824 | hw->run_count, | |
3825 | hw->not_run_ready, | |
3826 | hw->input_empty | |
3827 | ); | |
3828 | ||
3829 | if (vf_get_receiver(vdec->vf_provider_name)) { | |
3830 | enum receviver_start_e state = | |
3831 | vf_notify_receiver(vdec->vf_provider_name, | |
3832 | VFRAME_EVENT_PROVIDER_QUREY_STATE, | |
3833 | NULL); | |
3834 | debug_print(hw, 0, | |
3835 | "\nreceiver(%s) state %d\n", | |
3836 | vdec->vf_provider_name, | |
3837 | state); | |
3838 | } | |
3839 | ||
3840 | debug_print(hw, 0, | |
3841 | "%s, newq(%d/%d), dispq(%d/%d)recycleq(%d/%d) drop %d vf peek %d, prepare/get/put (%d/%d/%d)\n", | |
3842 | __func__, | |
3843 | kfifo_len(&hw->newframe_q), | |
3844 | VF_POOL_SIZE, | |
3845 | kfifo_len(&hw->display_q), | |
3846 | VF_POOL_SIZE, | |
3847 | kfifo_len(&hw->recycle_q), | |
3848 | VF_POOL_SIZE, | |
3849 | hw->drop_frame_count, | |
3850 | hw->peek_num, | |
3851 | hw->prepare_num, | |
3852 | hw->get_num, | |
3853 | hw->put_num | |
3854 | ); | |
3855 | ||
17a06af5 RZ |
3856 | debug_print(hw, 0, "vfbuf_use:\n"); |
3857 | for (i = 0; i < hw->vf_buf_num_used; i++) | |
3858 | debug_print(hw, 0, "%d: vf_buf_use %d\n", | |
3859 | i, hw->vfbuf_use[i]); | |
3860 | ||
107c76a4 PY |
3861 | debug_print(hw, 0, |
3862 | "DECODE_STATUS=0x%x\n", | |
3863 | READ_VREG(DECODE_STATUS)); | |
3864 | debug_print(hw, 0, | |
3865 | "MPC_E=0x%x\n", | |
3866 | READ_VREG(MPC_E)); | |
3867 | debug_print(hw, 0, | |
3868 | "DECODE_MODE=0x%x\n", | |
3869 | READ_VREG(DECODE_MODE)); | |
17a06af5 RZ |
3870 | debug_print(hw, 0, |
3871 | "wait_buf_status, AV_SCRATCH_5=0x%x\n", | |
3872 | READ_VREG(AV_SCRATCH_5)); | |
107c76a4 PY |
3873 | debug_print(hw, 0, |
3874 | "MBY_MBX=0x%x\n", | |
3875 | READ_VREG(MBY_MBX)); | |
3876 | debug_print(hw, 0, | |
3877 | "VIFF_BIT_CNT=0x%x\n", | |
3878 | READ_VREG(VIFF_BIT_CNT)); | |
3879 | debug_print(hw, 0, | |
3880 | "VLD_MEM_VIFIFO_LEVEL=0x%x\n", | |
3881 | READ_VREG(VLD_MEM_VIFIFO_LEVEL)); | |
3882 | debug_print(hw, 0, | |
3883 | "VLD_MEM_VIFIFO_WP=0x%x\n", | |
3884 | READ_VREG(VLD_MEM_VIFIFO_WP)); | |
3885 | debug_print(hw, 0, | |
3886 | "VLD_MEM_VIFIFO_RP=0x%x\n", | |
3887 | READ_VREG(VLD_MEM_VIFIFO_RP)); | |
3888 | debug_print(hw, 0, | |
3889 | "PARSER_VIDEO_RP=0x%x\n", | |
d631e9c2 | 3890 | STBUF_READ(&vdec->vbuf, get_rp)); |
107c76a4 PY |
3891 | debug_print(hw, 0, |
3892 | "PARSER_VIDEO_WP=0x%x\n", | |
d631e9c2 | 3893 | STBUF_READ(&vdec->vbuf, get_wp)); |
107c76a4 PY |
3894 | |
3895 | if (vdec_frame_based(vdec) && | |
3896 | (debug & PRINT_FRAMEBASE_DATA) | |
3897 | ) { | |
3898 | int jj; | |
3899 | if (hw->chunk && hw->chunk->block && | |
3900 | hw->chunk->size > 0) { | |
3901 | u8 *data = NULL; | |
3902 | ||
3903 | if (!hw->chunk->block->is_mapped) | |
3904 | data = codec_mm_vmap(hw->chunk->block->start + | |
3905 | hw->chunk->offset, hw->chunk->size); | |
3906 | else | |
3907 | data = ((u8 *)hw->chunk->block->start_virt) | |
3908 | + hw->chunk->offset; | |
3909 | ||
3910 | debug_print(hw, 0, | |
3911 | "frame data size 0x%x\n", | |
3912 | hw->chunk->size); | |
3913 | for (jj = 0; jj < hw->chunk->size; jj++) { | |
3914 | if ((jj & 0xf) == 0) | |
3915 | debug_print(hw, | |
3916 | PRINT_FRAMEBASE_DATA, | |
3917 | "%06x:", jj); | |
3918 | debug_print_cont(hw, | |
3919 | PRINT_FRAMEBASE_DATA, | |
3920 | "%02x ", data[jj]); | |
3921 | if (((jj + 1) & 0xf) == 0) | |
3922 | debug_print_cont(hw, | |
3923 | PRINT_FRAMEBASE_DATA, | |
3924 | "\n"); | |
3925 | } | |
3926 | ||
3927 | if (!hw->chunk->block->is_mapped) | |
3928 | codec_mm_unmap_phyaddr(data); | |
3929 | } | |
3930 | } | |
3931 | ||
3932 | } | |
3933 | ||
17a06af5 | 3934 | int ammvdec_avs_probe(struct platform_device *pdev) |
107c76a4 PY |
3935 | { |
3936 | struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; | |
3937 | struct vdec_avs_hw_s *hw = NULL; | |
3938 | ||
17a06af5 RZ |
3939 | if (vdec_get_debug_flags() & 0x8) |
3940 | return amvdec_avs_probe(pdev); | |
3941 | ||
107c76a4 PY |
3942 | pr_info("ammvdec_avs probe start.\n"); |
3943 | ||
3944 | if (pdata == NULL) { | |
3945 | pr_info("ammvdec_avs platform data undefined.\n"); | |
3946 | return -EFAULT; | |
3947 | } | |
107c76a4 PY |
3948 | |
3949 | hw = (struct vdec_avs_hw_s *)devm_kzalloc(&pdev->dev, | |
3950 | sizeof(struct vdec_avs_hw_s), GFP_KERNEL); | |
3951 | if (hw == NULL) { | |
3952 | pr_info("\nammvdec_avs decoder driver alloc failed\n"); | |
3953 | return -ENOMEM; | |
3954 | } | |
107c76a4 PY |
3955 | /*atomic_set(&hw->error_handler_run, 0);*/ |
3956 | hw->m_ins_flag = 1; | |
107c76a4 PY |
3957 | |
3958 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) | |
3959 | firmware_sel = 1; | |
107c76a4 PY |
3960 | |
3961 | if (firmware_sel == 1) { | |
17a06af5 | 3962 | #ifndef USE_DYNAMIC_BUF_NUM |
107c76a4 | 3963 | vf_buf_num = 4; |
17a06af5 | 3964 | #endif |
107c76a4 PY |
3965 | canvas_base = 0; |
3966 | canvas_num = 3; | |
3967 | } else { | |
3968 | pr_info("Error, do not support longcabac work around!!!"); | |
3969 | return -ENOMEM; | |
3970 | } | |
107c76a4 PY |
3971 | |
3972 | if (pdata->sys_info) | |
3973 | hw->vavs_amstream_dec_info = *pdata->sys_info; | |
107c76a4 PY |
3974 | |
3975 | hw->is_reset = 0; | |
3976 | pdata->user_data_read = NULL; | |
3977 | pdata->reset_userdata_fifo = NULL; | |
3978 | ||
107c76a4 PY |
3979 | pdata->private = hw; |
3980 | pdata->dec_status = vavs_dec_status; | |
3981 | pdata->set_isreset = vavs_set_isreset; | |
3982 | pdata->run_ready = run_ready; | |
3983 | pdata->run = run; | |
3984 | pdata->reset = reset; | |
3985 | pdata->irq_handler = vmavs_isr; | |
3986 | pdata->threaded_irq_handler = vmavs_isr_thread_fn; | |
3987 | pdata->dump_state = vmavs_dump_state; | |
3988 | ||
107c76a4 PY |
3989 | vavs_vdec_info_init(hw); |
3990 | ||
107c76a4 PY |
3991 | #ifdef ENABLE_USER_DATA |
3992 | if (NULL == hw->user_data_buffer) { | |
3993 | hw->user_data_buffer = | |
3994 | dma_alloc_coherent(amports_get_dma_device(), | |
3995 | USER_DATA_SIZE, | |
3996 | &hw->user_data_buffer_phys, GFP_KERNEL); | |
3997 | if (!hw->user_data_buffer) { | |
3998 | pr_info("%s: Can not allocate hw->user_data_buffer\n", | |
3999 | __func__); | |
4000 | return -ENOMEM; | |
4001 | } | |
4002 | pr_debug("hw->user_data_buffer = 0x%p, hw->user_data_buffer_phys = 0x%x\n", | |
4003 | hw->user_data_buffer, (u32)hw->user_data_buffer_phys); | |
4004 | } | |
4005 | #endif | |
46448536 | 4006 | /*hw->lmem_addr = kmalloc(LMEM_BUF_SIZE, GFP_KERNEL); |
107c76a4 PY |
4007 | if (hw->lmem_addr == NULL) { |
4008 | pr_err("%s: failed to alloc lmem buffer\n", __func__); | |
4009 | return -1; | |
4010 | } | |
4011 | hw->lmem_phy_addr = dma_map_single(amports_get_dma_device(), | |
4012 | hw->lmem_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); | |
4013 | if (dma_mapping_error(amports_get_dma_device(), | |
4014 | hw->lmem_phy_addr)) { | |
4015 | pr_err("%s: failed to map lmem buffer\n", __func__); | |
4016 | kfree(hw->lmem_addr); | |
4017 | hw->lmem_addr = NULL; | |
4018 | return -1; | |
46448536 | 4019 | }*/ |
107c76a4 | 4020 | /*INIT_WORK(&hw->set_clk_work, avs_set_clk);*/ |
46448536 PY |
4021 | hw->lmem_addr = (dma_addr_t)dma_alloc_coherent(amports_get_dma_device(), |
4022 | LMEM_BUF_SIZE, (dma_addr_t *)&hw->lmem_phy_addr, GFP_KERNEL); | |
4023 | if (hw->lmem_addr == 0) { | |
4024 | pr_err("%s: failed to alloc lmem buffer\n", __func__); | |
4025 | return -1; | |
4026 | } | |
107c76a4 | 4027 | |
107c76a4 PY |
4028 | if (vavs_init(hw) < 0) { |
4029 | pr_info("amvdec_avs init failed.\n"); | |
4030 | kfree(hw->gvs); | |
4031 | hw->gvs = NULL; | |
4032 | pdata->dec_status = NULL; | |
4033 | return -ENODEV; | |
4034 | } | |
4035 | ||
4036 | /*INIT_WORK(&hw->fatal_error_wd_work, vavs_fatal_error_handler); | |
4037 | atomic_set(&hw->error_handler_run, 0);*/ | |
4038 | #if 0 | |
4039 | #ifdef ENABLE_USER_DATA | |
4040 | INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); | |
4041 | #endif | |
4042 | #endif | |
4043 | INIT_WORK(&hw->notify_work, vavs_notify_work); | |
4044 | ||
4045 | if (pdata->use_vfm_path) { | |
4046 | snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, | |
4047 | VFM_DEC_PROVIDER_NAME); | |
4048 | hw->frameinfo_enable = 1; | |
4049 | } | |
4050 | else | |
4051 | snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, | |
4052 | MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); | |
4053 | if (pdata->parallel_dec == 1) { | |
4054 | int i; | |
4055 | for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) | |
4056 | hw->canvas_spec[i] = 0xffffff; | |
4057 | } | |
4058 | vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, | |
4059 | &vavs_vf_provider, hw); | |
4060 | ||
4061 | platform_set_drvdata(pdev, pdata); | |
4062 | ||
4063 | hw->platform_dev = pdev; | |
4064 | ||
4065 | vdec_set_prepare_level(pdata, start_decode_buf_level); | |
4066 | ||
cc41710a | 4067 | vdec_set_vframe_comm(pdata, DRIVER_NAME); |
4068 | ||
107c76a4 PY |
4069 | if (pdata->parallel_dec == 1) |
4070 | vdec_core_request(pdata, CORE_MASK_VDEC_1); | |
4071 | else { | |
4072 | vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | |
4073 | | CORE_MASK_COMBINE); | |
4074 | } | |
4075 | ||
4076 | /*INIT_WORK(&hw->userdata_push_work, userdata_push_do_work);*/ | |
17a06af5 RZ |
4077 | |
4078 | ||
107c76a4 PY |
4079 | return 0; |
4080 | } | |
4081 | ||
17a06af5 | 4082 | int ammvdec_avs_remove(struct platform_device *pdev) |
107c76a4 | 4083 | { |
107c76a4 | 4084 | |
17a06af5 RZ |
4085 | if (vdec_get_debug_flags() & 0x8) |
4086 | return amvdec_avs_remove(pdev); | |
4087 | else { | |
4088 | struct vdec_avs_hw_s *hw = | |
4089 | (struct vdec_avs_hw_s *) | |
4090 | (((struct vdec_s *)(platform_get_drvdata(pdev)))->private); | |
4091 | struct vdec_s *vdec = hw_to_vdec(hw); | |
4092 | int i; | |
107c76a4 | 4093 | |
17a06af5 RZ |
4094 | if (hw->stat & STAT_VDEC_RUN) { |
4095 | amvdec_stop(); | |
4096 | hw->stat &= ~STAT_VDEC_RUN; | |
4097 | } | |
107c76a4 | 4098 | |
17a06af5 RZ |
4099 | if (hw->stat & STAT_ISR_REG) { |
4100 | vdec_free_irq(VDEC_IRQ_1, (void *)hw); | |
4101 | hw->stat &= ~STAT_ISR_REG; | |
4102 | } | |
107c76a4 | 4103 | |
17a06af5 RZ |
4104 | if (hw->stat & STAT_TIMER_ARM) { |
4105 | del_timer_sync(&hw->check_timer); | |
4106 | hw->stat &= ~STAT_TIMER_ARM; | |
4107 | } | |
107c76a4 | 4108 | |
17a06af5 RZ |
4109 | cancel_work_sync(&hw->work); |
4110 | cancel_work_sync(&hw->notify_work); | |
107c76a4 | 4111 | |
17a06af5 RZ |
4112 | if (hw->mm_blk_handle) { |
4113 | decoder_bmmu_box_free(hw->mm_blk_handle); | |
4114 | hw->mm_blk_handle = NULL; | |
107c76a4 | 4115 | } |
17a06af5 RZ |
4116 | if (vdec->parallel_dec == 1) |
4117 | vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1); | |
4118 | else | |
4119 | vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC); | |
4120 | vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED); | |
107c76a4 | 4121 | |
17a06af5 RZ |
4122 | if (vdec->parallel_dec == 1) { |
4123 | for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) { | |
4124 | vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id); | |
4125 | vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id); | |
4126 | } | |
4127 | } | |
4128 | #ifdef ENABLE_USER_DATA | |
4129 | if (hw->user_data_buffer != NULL) { | |
4130 | dma_free_coherent( | |
4131 | amports_get_dma_device(), | |
4132 | USER_DATA_SIZE, | |
4133 | hw->user_data_buffer, | |
4134 | hw->user_data_buffer_phys); | |
4135 | hw->user_data_buffer = NULL; | |
4136 | hw->user_data_buffer_phys = 0; | |
4137 | } | |
4138 | #endif | |
46448536 | 4139 | /*if (hw->lmem_addr) { |
17a06af5 RZ |
4140 | dma_unmap_single(amports_get_dma_device(), |
4141 | hw->lmem_phy_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); | |
4142 | kfree(hw->lmem_addr); | |
4143 | hw->lmem_addr = NULL; | |
46448536 PY |
4144 | }*/ |
4145 | if (hw->lmem_addr) { | |
4146 | dma_free_coherent(amports_get_dma_device(), | |
4147 | LMEM_BUF_SIZE, (void *)hw->lmem_addr, | |
4148 | hw->lmem_phy_addr); | |
4149 | hw->lmem_addr = 0; | |
4150 | } | |
107c76a4 | 4151 | |
17a06af5 RZ |
4152 | if (hw->fw) { |
4153 | vfree(hw->fw); | |
4154 | hw->fw = NULL; | |
4155 | } | |
107c76a4 | 4156 | |
17a06af5 RZ |
4157 | pr_info("ammvdec_avs removed.\n"); |
4158 | if (hw->gvs) { | |
4159 | kfree(hw->gvs); | |
4160 | hw->gvs = NULL; | |
4161 | } | |
107c76a4 | 4162 | |
17a06af5 | 4163 | return 0; |
107c76a4 | 4164 | } |
17a06af5 | 4165 | } |
107c76a4 | 4166 | |
107c76a4 | 4167 | |
17a06af5 RZ |
4168 | #ifdef DEBUG_MULTI_WITH_AUTOMODE |
4169 | struct stream_buf_s *get_vbuf(void); | |
4170 | s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec); | |
107c76a4 PY |
4171 | |
4172 | ||
17a06af5 | 4173 | static s32 vavs_init2(struct vdec_avs_hw_s *hw) |
107c76a4 | 4174 | { |
17a06af5 RZ |
4175 | int size = -1; |
4176 | struct firmware_s *fw; | |
4177 | u32 fw_size = 0x1000 * 16; | |
107c76a4 | 4178 | |
17a06af5 RZ |
4179 | fw = vmalloc(sizeof(struct firmware_s) + fw_size); |
4180 | if (IS_ERR_OR_NULL(fw)) | |
4181 | return -ENOMEM; | |
107c76a4 | 4182 | |
17a06af5 | 4183 | pr_info("vavs_init\n"); |
107c76a4 | 4184 | |
17a06af5 | 4185 | amvdec_enable(); |
107c76a4 PY |
4186 | |
4187 | ||
17a06af5 | 4188 | vavs_local_init(hw); |
107c76a4 | 4189 | |
17a06af5 RZ |
4190 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) |
4191 | size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data); | |
4192 | else { | |
4193 | if (firmware_sel == 1) | |
4194 | size = get_firmware_data(VIDEO_DEC_AVS_NOCABAC, fw->data); | |
4195 | #ifdef AVSP_LONG_CABAC | |
4196 | else { | |
4197 | init_avsp_long_cabac_buf(); | |
4198 | size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data); | |
4199 | } | |
4200 | #endif | |
4201 | } | |
107c76a4 | 4202 | |
17a06af5 RZ |
4203 | if (size < 0) { |
4204 | amvdec_disable(); | |
4205 | pr_err("get firmware fail."); | |
4206 | /*vfree(buf);*/ | |
4207 | return -1; | |
4208 | } | |
107c76a4 | 4209 | |
17a06af5 RZ |
4210 | fw->len = size; |
4211 | hw->fw = fw; | |
4212 | if (hw->m_ins_flag) { | |
4213 | init_timer(&hw->check_timer); | |
4214 | hw->check_timer.data = (ulong) hw; | |
4215 | hw->check_timer.function = check_timer_func; | |
4216 | hw->check_timer.expires = jiffies + CHECK_INTERVAL; | |
107c76a4 | 4217 | |
107c76a4 | 4218 | |
17a06af5 RZ |
4219 | //add_timer(&hw->check_timer); |
4220 | hw->stat |= STAT_TIMER_ARM; | |
107c76a4 | 4221 | |
17a06af5 | 4222 | INIT_WORK(&hw->work, vavs_work); |
107c76a4 | 4223 | |
17a06af5 RZ |
4224 | hw->fw = fw; |
4225 | } | |
4226 | return 0; | |
4227 | } | |
107c76a4 | 4228 | |
17a06af5 RZ |
4229 | unsigned int debug_flag2; |
4230 | static int vavs_prot_init2(struct vdec_avs_hw_s *hw, unsigned char post_flag) | |
4231 | { | |
4232 | int r = 0; | |
4233 | /* | |
4234 | * 2: assist | |
4235 | * 3: vld_reset | |
4236 | * 4: vld_part_reset | |
4237 | * 5: vfifo reset | |
4238 | * 6: iqidct | |
4239 | * 7: mc | |
4240 | * 8: dblk | |
4241 | * 9: pic_dc | |
4242 | * 10: psc | |
4243 | * 11: mcpu | |
4244 | * 12: ccpu | |
4245 | * 13: ddr | |
4246 | * 14: afifo | |
4247 | */ | |
4248 | unsigned char run_flag; | |
4249 | #ifdef OOO | |
4250 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) /*| (1 << 4)*/); | |
4251 | WRITE_VREG(DOS_SW_RESET0, 0); | |
4252 | ||
4253 | READ_VREG(DOS_SW_RESET0); | |
4254 | ||
4255 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) /*| (1 << 4)*/); | |
4256 | WRITE_VREG(DOS_SW_RESET0, 0); | |
4257 | ||
4258 | WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8)); | |
4259 | WRITE_VREG(DOS_SW_RESET0, 0); | |
4260 | #endif | |
4261 | /***************** reset vld **********************************/ | |
4262 | #ifdef OOO | |
4263 | WRITE_VREG(POWER_CTL_VLD, 0x10); | |
4264 | WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2); | |
4265 | WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8, MEM_LEVEL_CNT_BIT, 6); | |
4266 | #endif | |
4267 | if (start_decoding_delay & 0x80000) | |
4268 | msleep(start_decoding_delay&0xffff); | |
4269 | ||
4270 | if (debug_flag2 & 0x1) | |
4271 | run_flag = post_flag; | |
4272 | else | |
4273 | run_flag = !post_flag; | |
4274 | if (run_flag) { | |
4275 | if (hw->m_ins_flag) { | |
4276 | int i; | |
4277 | if (hw->decode_pic_count == 0) { | |
4278 | r = vavs_canvas_init(hw); | |
4279 | #ifndef USE_DYNAMIC_BUF_NUM | |
4280 | for (i = 0; i < 4; i++) { | |
4281 | WRITE_VREG(AV_SCRATCH_0 + i, | |
4282 | hw->canvas_spec[i] | |
4283 | ); | |
4284 | } | |
4285 | #else | |
4286 | for (i = 0; i < hw->vf_buf_num_used; i += 2) { | |
4287 | WRITE_VREG(buf_spec_reg[i >> 1], | |
4288 | (hw->canvas_spec[i] & 0xffff) | | |
4289 | ((hw->canvas_spec[i + 1] & 0xffff) | |
4290 | << 16) | |
4291 | ); | |
4292 | } | |
4293 | #endif | |
4294 | } else | |
4295 | vavs_restore_regs(hw); | |
4296 | ||
4297 | for (i = 0; i < hw->vf_buf_num_used; i++) { | |
4298 | canvas_config_ex(canvas_y(hw->canvas_spec[i]), | |
4299 | hw->canvas_config[i][0].phy_addr, | |
4300 | hw->canvas_config[i][0].width, | |
4301 | hw->canvas_config[i][0].height, | |
4302 | CANVAS_ADDR_NOWRAP, | |
4303 | hw->canvas_config[i][0].block_mode, | |
4304 | 0); | |
4305 | ||
4306 | canvas_config_ex(canvas_u(hw->canvas_spec[i]), | |
4307 | hw->canvas_config[i][1].phy_addr, | |
4308 | hw->canvas_config[i][1].width, | |
4309 | hw->canvas_config[i][1].height, | |
4310 | CANVAS_ADDR_NOWRAP, | |
4311 | hw->canvas_config[i][1].block_mode, | |
4312 | 0); | |
4313 | } | |
4314 | } | |
4315 | } | |
4316 | ||
4317 | if (debug_flag2 & 0x2) | |
4318 | run_flag = post_flag; | |
4319 | else | |
4320 | run_flag = !post_flag; | |
4321 | if (run_flag) { | |
4322 | ||
4323 | /* notify ucode the buffer offset */ | |
4324 | if (hw->decode_pic_count == 0) | |
4325 | WRITE_VREG(AV_SCRATCH_F, hw->buf_offset); | |
4326 | #ifdef OOO | |
4327 | /* disable PSCALE for hardware sharing */ | |
4328 | WRITE_VREG(PSCALE_CTRL, 0); | |
4329 | #endif | |
4330 | } | |
4331 | if (start_decoding_delay & 0x40000) | |
4332 | msleep(start_decoding_delay&0xffff); | |
4333 | ||
4334 | if (debug_flag2 & 0x4) | |
4335 | run_flag = post_flag; | |
4336 | else | |
4337 | run_flag = !post_flag; | |
4338 | if (run_flag) { | |
4339 | if (hw->decode_pic_count == 0) { | |
4340 | #ifndef USE_DYNAMIC_BUF_NUM | |
4341 | WRITE_VREG(AVS_SOS_COUNT, 0); | |
4342 | #endif | |
4343 | WRITE_VREG(AVS_BUFFERIN, 0); | |
4344 | WRITE_VREG(AVS_BUFFEROUT, 0); | |
4345 | } | |
4346 | if (error_recovery_mode) | |
4347 | WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0); | |
4348 | else | |
4349 | WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1); | |
4350 | /* clear mailbox interrupt */ | |
4351 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); | |
4352 | ||
4353 | /* enable mailbox interrupt */ | |
4354 | WRITE_VREG(ASSIST_MBOX1_MASK, 1); | |
4355 | } | |
4356 | ||
4357 | if (debug_flag2 & 0x8) | |
4358 | run_flag = post_flag; | |
4359 | else | |
4360 | run_flag = !post_flag; | |
4361 | if (run_flag) { | |
4362 | ||
4363 | #ifndef USE_DYNAMIC_BUF_NUM /* def DEBUG_UCODE */ | |
4364 | if (hw->decode_pic_count == 0) | |
4365 | WRITE_VREG(AV_SCRATCH_D, 0); | |
4366 | #endif | |
4367 | if (start_decoding_delay & 0x10000) | |
4368 | msleep(start_decoding_delay&0xffff); | |
4369 | #ifdef NV21 | |
4370 | SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); | |
4371 | #endif | |
4372 | if (start_decoding_delay & 0x20000) | |
4373 | msleep(start_decoding_delay&0xffff); | |
4374 | ||
4375 | ||
4376 | #ifdef PIC_DC_NEED_CLEAR | |
4377 | CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31); | |
4378 | #endif | |
4379 | } | |
4380 | if (debug_flag2 & 0x10) | |
4381 | run_flag = post_flag; | |
4382 | else | |
4383 | run_flag = !post_flag; | |
4384 | if (run_flag) { | |
4385 | #ifdef ENABLE_USER_DATA | |
4386 | if (firmware_sel == 0) { | |
4387 | pr_info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! firmware_sel is 0\n"); | |
4388 | WRITE_VREG(AV_SCRATCH_N, (u32)(hw->user_data_buffer_phys - hw->buf_offset)); | |
4389 | pr_debug("AV_SCRATCH_N = 0x%x\n", READ_VREG(AV_SCRATCH_N)); | |
4390 | } | |
4391 | #endif | |
4392 | } | |
4393 | ||
4394 | if (debug_flag2 & 0x20) | |
4395 | run_flag = post_flag; | |
4396 | else | |
4397 | run_flag = !post_flag; | |
4398 | if (run_flag) { | |
4399 | if (hw->m_ins_flag) { | |
4400 | if (vdec_frame_based(hw_to_vdec(hw))) | |
4401 | WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE); | |
4402 | else | |
4403 | WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE); | |
46448536 | 4404 | WRITE_VREG(DECODE_LMEM_BUF_ADR, (u32)hw->lmem_phy_addr); |
17a06af5 RZ |
4405 | } else |
4406 | WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE); | |
4407 | WRITE_VREG(DECODE_STOP_POS, udebug_flag); | |
4408 | hw->old_udebug_flag = udebug_flag; | |
4409 | } | |
4410 | return r; | |
4411 | } | |
4412 | ||
4413 | static void init_hw(struct vdec_s *vdec) | |
4414 | { | |
4415 | struct vdec_avs_hw_s *hw = | |
4416 | (struct vdec_avs_hw_s *)vdec->private; | |
4417 | int ret; | |
4418 | pr_info("%s, %d\n", __func__, __LINE__); | |
4419 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) | |
4420 | ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, hw->fw->data); | |
4421 | else if (firmware_sel == 1) | |
4422 | ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", hw->fw->data); | |
4423 | else | |
4424 | ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, hw->fw->data); | |
4425 | ||
4426 | if (ret < 0) { | |
4427 | amvdec_disable(); | |
4428 | /*vfree(buf);*/ | |
4429 | pr_err("AVS: the %s fw loading failed, err: %x\n", | |
4430 | tee_enabled() ? "TEE" : "local", ret); | |
4431 | } | |
4432 | pr_info("%s, %d\n", __func__, __LINE__); | |
4433 | ||
4434 | /*vfree(buf);*/ | |
4435 | ||
4436 | hw->stat |= STAT_MC_LOAD; | |
4437 | ||
4438 | /* enable AMRISC side protocol */ | |
4439 | ret = vavs_prot_init2(hw, 0); | |
4440 | if (ret < 0) | |
4441 | return; | |
4442 | pr_info("%s, %d\n", __func__, __LINE__); | |
4443 | ||
4444 | } | |
4445 | ||
4446 | ||
4447 | static unsigned long run_ready2(struct vdec_s *vdec, unsigned long mask) | |
4448 | { | |
4449 | return 1; | |
4450 | } | |
4451 | ||
4452 | static void run2(struct vdec_s *vdec, unsigned long mask, | |
4453 | void (*callback)(struct vdec_s *, void *), | |
4454 | void *arg) | |
4455 | { | |
4456 | struct vdec_avs_hw_s *hw = | |
4457 | (struct vdec_avs_hw_s *)vdec->private; | |
4458 | pr_info("%s, %d\n", __func__, __LINE__); | |
4459 | ||
4460 | vavs_prot_init2(hw, 1); | |
4461 | ||
4462 | vdec_source_changed(VFORMAT_AVS, | |
4463 | 1920, 1080, 30); | |
4464 | ||
4465 | amvdec_start(); | |
4466 | ||
4467 | hw->stat |= STAT_VDEC_RUN; | |
4468 | pr_info("%s %d\n", __func__, __LINE__); | |
4469 | ||
4470 | } | |
4471 | ||
4472 | static int ammvdec_avs_probe2(struct platform_device *pdev) | |
4473 | { | |
4474 | struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; | |
4475 | struct vdec_avs_hw_s *hw = NULL; | |
4476 | ||
4477 | pr_info("ammvdec_avs probe start.\n"); | |
4478 | ||
4479 | if (pdata == NULL) { | |
4480 | pr_info("ammvdec_avs platform data undefined.\n"); | |
4481 | return -EFAULT; | |
4482 | } | |
4483 | pr_info("%s %d\n", __func__, __LINE__); | |
4484 | ||
4485 | hw = (struct vdec_avs_hw_s *)devm_kzalloc(&pdev->dev, | |
4486 | sizeof(struct vdec_avs_hw_s), GFP_KERNEL); | |
4487 | if (hw == NULL) { | |
4488 | pr_info("\nammvdec_avs decoder driver alloc failed\n"); | |
4489 | return -ENOMEM; | |
4490 | } | |
4491 | pr_info("%s %d\n", __func__, __LINE__); | |
4492 | /*atomic_set(&hw->error_handler_run, 0);*/ | |
4493 | hw->m_ins_flag = 1; | |
4494 | pr_info("%s %d\n", __func__, __LINE__); | |
4495 | ||
4496 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans) | |
4497 | firmware_sel = 1; | |
4498 | pr_info("%s %d\n", __func__, __LINE__); | |
4499 | ||
4500 | if (firmware_sel == 1) { | |
4501 | #ifndef USE_DYNAMIC_BUF_NUM | |
4502 | vf_buf_num = 4; | |
4503 | #endif | |
4504 | canvas_base = 0; | |
4505 | canvas_num = 3; | |
4506 | } else { | |
4507 | pr_info("Error, do not support longcabac work around!!!"); | |
4508 | return -ENOMEM; | |
4509 | } | |
4510 | pr_info("%s %d\n", __func__, __LINE__); | |
4511 | ||
4512 | if (pdata->sys_info) | |
4513 | hw->vavs_amstream_dec_info = *pdata->sys_info; | |
4514 | pr_info("%s %d\n", __func__, __LINE__); | |
4515 | ||
4516 | hw->is_reset = 0; | |
4517 | pdata->user_data_read = NULL; | |
4518 | pdata->reset_userdata_fifo = NULL; | |
4519 | ||
4520 | pr_info("%s %d\n", __func__, __LINE__); | |
4521 | ||
4522 | pdata->private = hw; | |
4523 | pdata->dec_status = vavs_dec_status; | |
4524 | pdata->set_isreset = vavs_set_isreset; | |
4525 | pdata->run_ready = run_ready2; | |
4526 | pdata->run = run2; | |
4527 | pdata->reset = reset; | |
4528 | pdata->irq_handler = vmavs_isr; | |
4529 | pdata->threaded_irq_handler = vmavs_isr_thread_fn; | |
4530 | pdata->dump_state = vmavs_dump_state; | |
4531 | ||
4532 | pr_info("%s %d\n", __func__, __LINE__); | |
4533 | ||
4534 | vavs_vdec_info_init(hw); | |
4535 | ||
4536 | pr_info("%s %d\n", __func__, __LINE__); | |
4537 | ||
4538 | #ifdef ENABLE_USER_DATA | |
4539 | if (NULL == hw->user_data_buffer) { | |
4540 | hw->user_data_buffer = | |
4541 | dma_alloc_coherent(amports_get_dma_device(), | |
4542 | USER_DATA_SIZE, | |
4543 | &hw->user_data_buffer_phys, GFP_KERNEL); | |
4544 | if (!hw->user_data_buffer) { | |
4545 | pr_info("%s: Can not allocate hw->user_data_buffer\n", | |
4546 | __func__); | |
4547 | return -ENOMEM; | |
4548 | } | |
4549 | pr_debug("hw->user_data_buffer = 0x%p, hw->user_data_buffer_phys = 0x%x\n", | |
4550 | hw->user_data_buffer, (u32)hw->user_data_buffer_phys); | |
4551 | } | |
4552 | #endif | |
4553 | hw->lmem_addr = kmalloc(LMEM_BUF_SIZE, GFP_KERNEL); | |
4554 | if (hw->lmem_addr == NULL) { | |
4555 | pr_err("%s: failed to alloc lmem buffer\n", __func__); | |
4556 | return -1; | |
4557 | } | |
4558 | hw->lmem_phy_addr = dma_map_single(amports_get_dma_device(), | |
4559 | hw->lmem_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE); | |
4560 | if (dma_mapping_error(amports_get_dma_device(), | |
4561 | hw->lmem_phy_addr)) { | |
4562 | pr_err("%s: failed to map lmem buffer\n", __func__); | |
4563 | kfree(hw->lmem_addr); | |
4564 | hw->lmem_addr = NULL; | |
4565 | return -1; | |
4566 | } | |
4567 | ||
4568 | pr_info("%s %d\n", __func__, __LINE__); | |
4569 | ||
4570 | /*INIT_WORK(&hw->set_clk_work, avs_set_clk);*/ | |
4571 | ||
4572 | pr_info("%s %d\n", __func__, __LINE__); | |
4573 | ||
4574 | if (vavs_init2(hw) < 0) { | |
4575 | pr_info("amvdec_avs init failed.\n"); | |
4576 | kfree(hw->gvs); | |
4577 | hw->gvs = NULL; | |
4578 | pdata->dec_status = NULL; | |
4579 | return -ENODEV; | |
4580 | } | |
4581 | /*vdec = pdata;*/ | |
4582 | pr_info("%s, %d\n", __func__, __LINE__); | |
4583 | ||
4584 | if (hw->m_ins_flag) { | |
4585 | INIT_WORK(&hw->notify_work, vavs_notify_work); | |
4586 | #if 1 | |
4587 | if (pdata->use_vfm_path) { | |
4588 | snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, | |
4589 | VFM_DEC_PROVIDER_NAME); | |
4590 | hw->frameinfo_enable = 1; | |
4591 | } | |
4592 | else | |
4593 | snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE, | |
4594 | MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff); | |
4595 | if (pdata->parallel_dec == 1) { | |
4596 | int i; | |
4597 | for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) | |
4598 | hw->canvas_spec[i] = 0xffffff; | |
4599 | } | |
4600 | vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name, | |
4601 | &vavs_vf_provider, hw); | |
4602 | ||
4603 | platform_set_drvdata(pdev, pdata); | |
4604 | ||
4605 | hw->platform_dev = pdev; | |
4606 | ||
4607 | vdec_set_prepare_level(pdata, start_decode_buf_level); | |
4608 | ||
4609 | if (pdata->parallel_dec == 1) | |
4610 | vdec_core_request(pdata, CORE_MASK_VDEC_1); | |
4611 | else { | |
4612 | vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC | |
4613 | | CORE_MASK_COMBINE); | |
4614 | } | |
4615 | pr_info("%s, %d\n", __func__, __LINE__); | |
4616 | #endif | |
4617 | }else{ | |
4618 | /*INIT_WORK(&hw->fatal_error_wd_work, vavs_fatal_error_handler); | |
4619 | atomic_set(&hw->error_handler_run, 0);*/ | |
4620 | #ifdef ENABLE_USER_DATA | |
4621 | INIT_WORK(&hw->userdata_push_work, userdata_push_do_work); | |
4622 | #endif | |
4623 | INIT_WORK(&hw->notify_work, vavs_notify_work); | |
4624 | } | |
4625 | ||
4626 | init_hw(pdata); | |
4627 | return 0; | |
4628 | } | |
4629 | ||
4630 | static int ammvdec_avs_remove2(struct platform_device *pdev) | |
4631 | { | |
4632 | struct vdec_avs_hw_s *hw = ghw; | |
4633 | ||
4634 | cancel_work_sync(&hw->fatal_error_wd_work); | |
4635 | atomic_set(&hw->error_handler_run, 0); | |
4636 | #ifdef ENABLE_USER_DATA | |
4637 | cancel_work_sync(&hw->userdata_push_work); | |
4638 | #endif | |
4639 | cancel_work_sync(&hw->notify_work); | |
4640 | cancel_work_sync(&hw->set_clk_work); | |
4641 | if (hw->stat & STAT_VDEC_RUN) { | |
4642 | amvdec_stop(); | |
4643 | hw->stat &= ~STAT_VDEC_RUN; | |
4644 | } | |
4645 | ||
4646 | if (hw->stat & STAT_ISR_REG) { | |
4647 | vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id); | |
4648 | hw->stat &= ~STAT_ISR_REG; | |
4649 | } | |
4650 | ||
4651 | if (hw->stat & STAT_TIMER_ARM) { | |
4652 | del_timer_sync(&hw->recycle_timer); | |
4653 | hw->stat &= ~STAT_TIMER_ARM; | |
4654 | } | |
4655 | #ifdef AVSP_LONG_CABAC | |
4656 | if (firmware_sel == 0) { | |
4657 | mutex_lock(&vavs_mutex); | |
4658 | cancel_work_sync(&long_cabac_wd_work); | |
4659 | mutex_unlock(&vavs_mutex); | |
4660 | ||
4661 | if (es_write_addr_virt) { | |
4662 | #if 0 | |
4663 | codec_mm_free_for_dma("vavs", es_write_addr_phy); | |
4664 | #else | |
4665 | dma_unmap_single(amports_get_dma_device(), | |
4666 | es_write_addr_phy, | |
4667 | MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE); | |
4668 | /*kfree(es_write_addr_virt);*/ | |
4669 | es_write_addr_virt = NULL; | |
4670 | #endif | |
4671 | } | |
4672 | ||
4673 | #ifdef BITSTREAM_READ_TMP_NO_CACHE | |
4674 | if (bitstream_read_tmp) { | |
4675 | dma_free_coherent(amports_get_dma_device(), | |
4676 | SVA_STREAM_BUF_SIZE, bitstream_read_tmp, | |
4677 | bitstream_read_tmp_phy); | |
4678 | bitstream_read_tmp = NULL; | |
4679 | } | |
4680 | #else | |
4681 | if (bitstream_read_tmp) { | |
4682 | dma_unmap_single(amports_get_dma_device(), | |
4683 | bitstream_read_tmp_phy, | |
4684 | SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE); | |
4685 | kfree(bitstream_read_tmp); | |
4686 | bitstream_read_tmp = NULL; | |
4687 | } | |
4688 | #endif | |
4689 | } | |
4690 | #endif | |
4691 | if (hw->stat & STAT_VF_HOOK) { | |
4692 | if (hw->fr_hint_status == VDEC_HINTED && !hw->is_reset) | |
4693 | avs_vf_notify_receiver(hw, PROVIDER_NAME, | |
4694 | VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); | |
4695 | hw->fr_hint_status = VDEC_NO_NEED_HINT; | |
4696 | vf_unreg_provider(&vavs_vf_prov); | |
4697 | hw->stat &= ~STAT_VF_HOOK; | |
4698 | } | |
4699 | ||
4700 | #ifdef ENABLE_USER_DATA | |
4701 | if (hw->user_data_buffer != NULL) { | |
4702 | dma_free_coherent( | |
4703 | amports_get_dma_device(), | |
4704 | USER_DATA_SIZE, | |
4705 | hw->user_data_buffer, | |
4706 | hw->user_data_buffer_phys); | |
4707 | hw->user_data_buffer = NULL; | |
4708 | hw->user_data_buffer_phys = 0; | |
4709 | } | |
4710 | #endif | |
4711 | ||
4712 | if (hw->fw) { | |
4713 | vfree(hw->fw); | |
4714 | hw->fw = NULL; | |
4715 | } | |
4716 | ||
4717 | amvdec_disable(); | |
4718 | /*vdec_disable_DMC(NULL);*/ | |
4719 | ||
4720 | hw->pic_type = 0; | |
4721 | if (hw->mm_blk_handle) { | |
4722 | decoder_bmmu_box_free(hw->mm_blk_handle); | |
4723 | hw->mm_blk_handle = NULL; | |
4724 | } | |
4725 | #ifdef DEBUG_PTS | |
4726 | pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit, | |
4727 | hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed); | |
4728 | pr_debug("total frame %d, hw->avi_flag %d, rate %d\n", hw->total_frame, hw->avi_flag, | |
4729 | hw->vavs_amstream_dec_info.rate); | |
4730 | #endif | |
4731 | kfree(hw->gvs); | |
4732 | hw->gvs = NULL; | |
4733 | ||
4734 | return 0; | |
4735 | } | |
4736 | #endif | |
4737 | ||
4738 | static struct platform_driver ammvdec_avs_driver = { | |
4739 | #ifdef DEBUG_MULTI_WITH_AUTOMODE | |
4740 | .probe = ammvdec_avs_probe2, | |
4741 | .remove = ammvdec_avs_remove2, | |
4742 | #else | |
4743 | .probe = ammvdec_avs_probe, | |
4744 | .remove = ammvdec_avs_remove, | |
4745 | #endif | |
4746 | #ifdef CONFIG_PM | |
4747 | .suspend = amvdec_suspend, | |
4748 | .resume = amvdec_resume, | |
4749 | #endif | |
4750 | .driver = { | |
4751 | .name = MULTI_DRIVER_NAME, | |
4752 | } | |
4753 | }; | |
4754 | ||
4755 | static struct codec_profile_t ammvdec_avs_profile = { | |
4756 | .name = "mavs", | |
4757 | .profile = "" | |
4758 | }; | |
4759 | ||
4760 | static struct mconfig mavs_configs[] = { | |
4761 | /*MC_PU32("stat", &stat), | |
4762 | MC_PU32("debug_flag", &debug_flag), | |
4763 | MC_PU32("error_recovery_mode", &error_recovery_mode), | |
4764 | MC_PU32("hw->pic_type", &hw->pic_type), | |
4765 | MC_PU32("radr", &radr), | |
4766 | MC_PU32("vf_buf_num", &vf_buf_num), | |
4767 | MC_PU32("vf_buf_num_used", &vf_buf_num_used), | |
4768 | MC_PU32("canvas_base", &canvas_base), | |
4769 | MC_PU32("firmware_sel", &firmware_sel), | |
4770 | */ | |
4771 | }; | |
4772 | static struct mconfig_node mavs_node; | |
4773 | ||
4774 | ||
4775 | static int __init ammvdec_avs_driver_init_module(void) | |
4776 | { | |
4777 | pr_debug("ammvdec_avs module init\n"); | |
4778 | ||
4779 | if (platform_driver_register(&ammvdec_avs_driver)) | |
4780 | pr_err("failed to register ammvdec_avs driver\n"); | |
4781 | #ifdef DEBUG_WITH_SINGLE_MODE | |
4782 | if (platform_driver_register(&amvdec_avs_driver)) { | |
4783 | pr_info("failed to register amvdec_avs driver\n"); | |
4784 | return -ENODEV; | |
4785 | } | |
4786 | #else | |
4787 | amvdec_avs_driver = amvdec_avs_driver; | |
4788 | #endif | |
4789 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) | |
4790 | ammvdec_avs_profile.profile = "avs+"; | |
4791 | ||
4792 | //vcodec_profile_register(&ammvdec_avs_profile); | |
4793 | INIT_REG_NODE_CONFIGS("media.decoder", &mavs_node, | |
4794 | "mavs", mavs_configs, CONFIG_FOR_RW); | |
4795 | return 0; | |
4796 | } | |
4797 | ||
4798 | ||
4799 | ||
4800 | static void __exit ammvdec_avs_driver_remove_module(void) | |
4801 | { | |
4802 | pr_debug("ammvdec_avs module remove.\n"); | |
4803 | ||
4804 | platform_driver_unregister(&ammvdec_avs_driver); | |
4805 | #ifdef DEBUG_WITH_SINGLE_MODE | |
4806 | platform_driver_unregister(&amvdec_avs_driver); | |
4807 | #endif | |
4808 | } | |
4809 | ||
4810 | /****************************************/ | |
4811 | /* | |
4812 | module_param(stat, uint, 0664); | |
4813 | MODULE_PARM_DESC(stat, "\n amvdec_avs stat\n"); | |
4814 | */ | |
4815 | /****************************************** | |
4816 | *module_param(run_flag, uint, 0664); | |
4817 | *MODULE_PARM_DESC(run_flag, "\n run_flag\n"); | |
4818 | * | |
4819 | *module_param(step_flag, uint, 0664); | |
4820 | *MODULE_PARM_DESC(step_flag, "\n step_flag\n"); | |
4821 | ******************************************* | |
4822 | */ | |
4823 | module_param(step, uint, 0664); | |
4824 | MODULE_PARM_DESC(step, "\n step\n"); | |
4825 | ||
4826 | module_param(debug, uint, 0664); | |
4827 | MODULE_PARM_DESC(debug, "\n debug\n"); | |
4828 | ||
4829 | module_param(debug_mask, uint, 0664); | |
4830 | MODULE_PARM_DESC(debug_mask, "\n debug_mask\n"); | |
4831 | ||
4832 | module_param(error_recovery_mode, uint, 0664); | |
4833 | MODULE_PARM_DESC(error_recovery_mode, "\n error_recovery_mode\n"); | |
4834 | ||
4835 | /****************************************** | |
4836 | *module_param(error_watchdog_threshold, uint, 0664); | |
4837 | *MODULE_PARM_DESC(error_watchdog_threshold, "\n error_watchdog_threshold\n"); | |
4838 | * | |
4839 | *module_param(error_watchdog_buf_threshold, uint, 0664); | |
4840 | *MODULE_PARM_DESC(error_watchdog_buf_threshold, | |
4841 | * "\n error_watchdog_buf_threshold\n"); | |
4842 | ******************************************* | |
4843 | */ | |
4844 | /* | |
4845 | module_param(pic_type, uint, 0444); | |
4846 | MODULE_PARM_DESC(pic_type, "\n amdec_vas picture type\n"); | |
4847 | */ | |
4848 | module_param(radr, uint, 0664); | |
4849 | MODULE_PARM_DESC(radr, "\nradr\n"); | |
4850 | ||
4851 | module_param(rval, uint, 0664); | |
107c76a4 PY |
4852 | MODULE_PARM_DESC(rval, "\nrval\n"); |
4853 | ||
4854 | module_param(dbg_cmd, uint, 0664); | |
4855 | MODULE_PARM_DESC(dbg_cmd, "\n dbg_cmd\n"); | |
4856 | ||
4857 | module_param(vf_buf_num, uint, 0664); | |
4858 | MODULE_PARM_DESC(vf_buf_num, "\nvf_buf_num\n"); | |
4859 | ||
4860 | /* | |
4861 | module_param(vf_buf_num_used, uint, 0664); | |
4862 | MODULE_PARM_DESC(vf_buf_num_used, "\nvf_buf_num_used\n"); | |
4863 | */ | |
4864 | module_param(canvas_base, uint, 0664); | |
4865 | MODULE_PARM_DESC(canvas_base, "\ncanvas_base\n"); | |
4866 | ||
4867 | ||
4868 | module_param(firmware_sel, uint, 0664); | |
4869 | MODULE_PARM_DESC(firmware_sel, "\n firmware_sel\n"); | |
4870 | ||
4871 | module_param(disable_longcabac_trans, uint, 0664); | |
4872 | MODULE_PARM_DESC(disable_longcabac_trans, "\n disable_longcabac_trans\n"); | |
4873 | ||
4874 | module_param(dec_control, uint, 0664); | |
4875 | MODULE_PARM_DESC(dec_control, "\n amvdec_vavs decoder control\n"); | |
4876 | ||
4877 | module_param(start_decode_buf_level, int, 0664); | |
4878 | MODULE_PARM_DESC(start_decode_buf_level, | |
4879 | "\n avs start_decode_buf_level\n"); | |
4880 | ||
4881 | module_param(decode_timeout_val, uint, 0664); | |
4882 | MODULE_PARM_DESC(decode_timeout_val, | |
4883 | "\n avs decode_timeout_val\n"); | |
4884 | ||
17a06af5 RZ |
4885 | module_param(error_handle_policy, uint, 0664); |
4886 | MODULE_PARM_DESC(error_handle_policy, | |
4887 | "\n avs error_handle_policy\n"); | |
4888 | ||
4889 | module_param(again_threshold, uint, 0664); | |
4890 | MODULE_PARM_DESC(again_threshold, "\n again_threshold\n"); | |
4891 | ||
107c76a4 PY |
4892 | module_param(udebug_flag, uint, 0664); |
4893 | MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n"); | |
4894 | ||
4895 | module_param(udebug_pause_pos, uint, 0664); | |
4896 | MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n"); | |
4897 | ||
4898 | module_param(udebug_pause_val, uint, 0664); | |
4899 | MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n"); | |
4900 | ||
4901 | module_param(udebug_pause_decode_idx, uint, 0664); | |
4902 | MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n"); | |
4903 | ||
17a06af5 RZ |
4904 | module_param(udebug_pause_ins_id, uint, 0664); |
4905 | MODULE_PARM_DESC(udebug_pause_ins_id, "\n udebug_pause_ins_id\n"); | |
4906 | ||
b06eadf9 | 4907 | |
17a06af5 RZ |
4908 | module_param(start_decoding_delay, uint, 0664); |
4909 | MODULE_PARM_DESC(start_decoding_delay, "\n start_decoding_delay\n"); | |
4910 | ||
46448536 PY |
4911 | module_param(pre_decode_buf_level, int, 0664); |
4912 | MODULE_PARM_DESC(pre_decode_buf_level, | |
4913 | "\n ammvdec_mavs pre_decode_buf_level\n"); | |
4914 | ||
4915 | ||
17a06af5 RZ |
4916 | #ifdef DEBUG_MULTI_WITH_AUTOMODE |
4917 | module_param(debug_flag2, uint, 0664); | |
4918 | MODULE_PARM_DESC(debug_flag2, "\n debug_flag2\n"); | |
4919 | #endif | |
107c76a4 PY |
4920 | module_param(force_fps, uint, 0664); |
4921 | MODULE_PARM_DESC(force_fps, "\n force_fps\n"); | |
4922 | ||
17a06af5 RZ |
4923 | #ifdef DEBUG_MULTI_FRAME_INS |
4924 | module_param(delay, uint, 0664); | |
4925 | MODULE_PARM_DESC(delay, "\n delay\n"); | |
4926 | ||
4927 | module_param_array(max_run_count, uint, &max_decode_instance_num, 0664); | |
4928 | ||
4929 | #endif | |
4930 | ||
4931 | module_param_array(ins_udebug_flag, uint, &max_decode_instance_num, 0664); | |
4932 | ||
107c76a4 PY |
4933 | module_param_array(max_process_time, uint, &max_decode_instance_num, 0664); |
4934 | ||
17a06af5 RZ |
4935 | module_param_array(run_count, uint, &max_decode_instance_num, 0664); |
4936 | ||
107c76a4 PY |
4937 | module_param_array(max_get_frame_interval, uint, |
4938 | &max_decode_instance_num, 0664); | |
4939 | ||
4940 | ||
4941 | module_init(ammvdec_avs_driver_init_module); | |
4942 | module_exit(ammvdec_avs_driver_remove_module); | |
4943 | ||
4944 | MODULE_DESCRIPTION("AMLOGIC AVS Video Decoder Driver"); | |
4945 | MODULE_LICENSE("GPL"); | |
4946 | MODULE_AUTHOR("Qi Wang <qi.wang@amlogic.com>"); |