vdec: change to support vc1 decoder [1/1]
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_media.git] / drivers / frame_provider / decoder / utils / vdec.c
CommitLineData
b9164398
NQ
1/*
2 * drivers/amlogic/media/frame_provider/decoder/utils/vdec.c
3 *
4 * Copyright (C) 2016 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 *
e0614bf7 16 */
5b851ff9 17#define DEBUG
b9164398
NQ
18#include <linux/kernel.h>
19#include <linux/spinlock.h>
20#include <linux/types.h>
21#include <linux/errno.h>
22#include <linux/delay.h>
23#include <linux/kthread.h>
24#include <linux/platform_device.h>
25#include <linux/uaccess.h>
26#include <linux/semaphore.h>
27#include <linux/sched/rt.h>
28#include <linux/interrupt.h>
29#include <linux/amlogic/media/utils/vformat.h>
30#include <linux/amlogic/iomap.h>
31#include <linux/amlogic/media/canvas/canvas.h>
32#include <linux/amlogic/media/vfm/vframe.h>
33#include <linux/amlogic/media/vfm/vframe_provider.h>
34#include <linux/amlogic/media/vfm/vframe_receiver.h>
35#include <linux/amlogic/media/video_sink/ionvideo_ext.h>
febdc420 36#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
e8335f32 37#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
febdc420 38#endif
b9164398 39#include <linux/amlogic/media/vfm/vfm_ext.h>
a6c89e96
NQ
40/*for VDEC_DEBUG_SUPPORT*/
41#include <linux/time.h>
b9164398
NQ
42
43#include <linux/amlogic/media/utils/vdec_reg.h>
d631e9c2 44#include "../../../stream_input/amports/streambuf.h"
b9164398 45#include "vdec.h"
fe96802b
NQ
46#include "vdec_trace.h"
47#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
48#include "vdec_profile.h"
49#endif
50#include <linux/of.h>
51#include <linux/of_fdt.h>
52#include <linux/libfdt_env.h>
53#include <linux/of_reserved_mem.h>
54#include <linux/dma-contiguous.h>
55#include <linux/cma.h>
56#include <linux/module.h>
57#include <linux/slab.h>
58#include <linux/dma-mapping.h>
59#include <linux/dma-contiguous.h>
60#include "../../../stream_input/amports/amports_priv.h"
61
62#include <linux/amlogic/media/utils/amports_config.h>
63#include "../utils/amvdec.h"
64#include "vdec_input.h"
65
66#include "../../../common/media_clock/clk/clk.h"
67#include <linux/reset.h>
fe96802b 68#include <linux/amlogic/cpu_version.h>
b9164398
NQ
69#include <linux/amlogic/media/codec_mm/codec_mm.h>
70#include <linux/amlogic/media/video_sink/video_keeper.h>
fe96802b
NQ
71#include <linux/amlogic/media/codec_mm/configs.h>
72#include <linux/amlogic/media/frame_sync/ptsserv.h>
73#include "secprot.h"
63e810c0 74#include "../../../common/chips/decoder_cpu_ver_info.h"
8458676f 75#include "frame_check.h"
b9164398 76
fb394ef8
NQ
77#ifdef CONFIG_AMLOGIC_POWER
78#include <linux/amlogic/power_ctrl.h>
79#endif
80
1418c7d8 81#include <dt-bindings/power/sc2-pd.h>
82#include <linux/amlogic/pwr_ctrl.h>
5166ea72
NQ
83#include <linux/of_device.h>
84#include "vdec_power_ctrl.h"
1418c7d8 85
b9164398
NQ
86static DEFINE_MUTEX(vdec_mutex);
87
88#define MC_SIZE (4096 * 4)
89#define CMA_ALLOC_SIZE SZ_64M
90#define MEM_NAME "vdec_prealloc"
91static int inited_vcodec_num;
976f3376 92#define jiffies_ms div64_u64(get_jiffies_64() * 1000, HZ)
b9164398 93static int poweron_clock_level;
b39d60ee 94static int debug_vdetect = 0;
b9164398
NQ
95static int keep_vdec_mem;
96static unsigned int debug_trace_num = 16 * 20;
97static int step_mode;
98static unsigned int clk_config;
bba22b6d 99#ifdef VDEC_FCC_SUPPORT
100static int fcc_debug;
101static void vdec_fcc_jump_back(struct vdec_s *vdec);
102#endif
158de7c4 103/*
677ab50d
NQ
104 * 0x1 : sched_priority to MAX_RT_PRIO -1.
105 * 0x2 : always reload firmware.
106 * 0x4 : vdec canvas debug enable
107 * 0x100: enable vdec fence.
108 */
109#define VDEC_DBG_SCHED_PRIO (0x1)
110#define VDEC_DBG_ALWAYS_LOAD_FW (0x2)
111#define VDEC_DBG_CANVAS_STATUS (0x4)
112#define VDEC_DBG_ENABLE_FENCE (0x100)
113
40831ab7 114u32 debug = VDEC_DBG_ALWAYS_LOAD_FW;
677ab50d 115EXPORT_SYMBOL(debug);
8247f369 116
5166ea72
NQ
117int hevc_max_reset_count;
118EXPORT_SYMBOL(hevc_max_reset_count);
119
120int no_powerdown;
121EXPORT_SYMBOL(no_powerdown);
fe96802b 122
05afa03d 123static int parallel_decode = 1;
97fe3d16
PY
124static int fps_detection;
125static int fps_clear;
42173624 126
127
128static int force_nosecure_even_drm;
9457f9af 129static int disable_switch_single_to_mult;
42173624 130
b9164398
NQ
131static DEFINE_SPINLOCK(vdec_spin_lock);
132
133#define HEVC_TEST_LIMIT 100
134#define GXBB_REV_A_MINOR 0xA
135
a8f62ee0
RZ
136#define PRINT_FRAME_INFO 1
137#define DISABLE_FRAME_INFO 2
138
d3b4fbc5 139#define RESET7_REGISTER_LEVEL 0x1127
140#define P_RESETCTRL_RESET5_LEVEL 0x15
141
a8f62ee0 142static int frameinfo_flag = 0;
e8335f32 143static int v4lvideo_add_di = 1;
6f50ab2c 144static int max_di_instance = 2;
e8335f32 145
a8f62ee0
RZ
146//static int path_debug = 0;
147
cc41710a 148static int enable_mvdec_info = 1;
149
a8f62ee0
RZ
150int decode_underflow = 0;
151
1418c7d8 152static int enable_stream_mode_multi_dec;
d631e9c2 153
05afa03d
PY
154#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
155
833bb93d 156extern void vframe_rate_uevent(int duration);
157
b9164398
NQ
158struct am_reg {
159 char *name;
160 int offset;
161};
162
163struct vdec_isr_context_s {
164 int index;
165 int irq;
166 irq_handler_t dev_isr;
167 irq_handler_t dev_threaded_isr;
168 void *dev_id;
a6c89e96 169 struct vdec_s *vdec;
b9164398
NQ
170};
171
97fe3d16
PY
172struct decode_fps_s {
173 u32 frame_count;
174 u64 start_timestamp;
175 u64 last_timestamp;
176 u32 fps;
177};
178
b9164398
NQ
179struct vdec_core_s {
180 struct list_head connected_vdec_list;
181 spinlock_t lock;
05afa03d 182 spinlock_t canvas_lock;
97fe3d16 183 spinlock_t fps_lock;
0ed0f572 184 spinlock_t input_lock;
fe96802b 185 struct ida ida;
b9164398
NQ
186 atomic_t vdec_nr;
187 struct vdec_s *vfm_vdec;
188 struct vdec_s *active_vdec;
05afa03d 189 struct vdec_s *active_hevc;
fe96802b 190 struct vdec_s *hint_fr_vdec;
b9164398
NQ
191 struct platform_device *vdec_core_platform_device;
192 struct device *cma_dev;
b9164398
NQ
193 struct semaphore sem;
194 struct task_struct *thread;
fe96802b 195 struct workqueue_struct *vdec_core_wq;
b9164398 196
a6c89e96 197 unsigned long sched_mask;
b9164398
NQ
198 struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX];
199 int power_ref_count[VDEC_MAX];
05afa03d
PY
200 struct vdec_s *last_vdec;
201 int parallel_dec;
202 unsigned long power_ref_mask;
203 int vdec_combine_flag;
97fe3d16 204 struct decode_fps_s decode_fps[MAX_INSTANCE_MUN];
0ed0f572
PY
205 unsigned long buff_flag;
206 unsigned long stream_buff_flag;
5166ea72 207 struct power_manager_s *pm;
558b13f3 208 u32 vdec_resouce_status;
05afa03d
PY
209};
210
211struct canvas_status_s {
212 int type;
213 int canvas_used_flag;
214 int id;
b9164398
NQ
215};
216
05afa03d 217
b9164398
NQ
218static struct vdec_core_s *vdec_core;
219
fe96802b
NQ
220static const char * const vdec_status_string[] = {
221 "VDEC_STATUS_UNINITIALIZED",
222 "VDEC_STATUS_DISCONNECTED",
223 "VDEC_STATUS_CONNECTED",
224 "VDEC_STATUS_ACTIVE"
225};
17a06af5
RZ
226/*
227bit [28] enable print
228bit [23:16] etc
229bit [15:12]
230 none 0 and not 0x1: force single
231 none 0 and 0x1: force multi
232bit [8]
233 1: force dual
234bit [3]
235 1: use mavs for single mode
236bit [2]
237 1: force vfm path for frame mode
238bit [1]
239 1: force esparser auto mode
240bit [0]
241 1: disable audo manual mode ??
242*/
fe96802b
NQ
243
244static int debugflags;
245
4373e91a 246static char vfm_path[VDEC_MAP_NAME_SIZE] = {"disable"};
247static const char vfm_path_node[][VDEC_MAP_NAME_SIZE] =
248{
249 "video_render.0",
250 "video_render.1",
251 "amvideo",
252 "videopip",
253 "deinterlace",
254 "dimulti.1",
255 "amlvideo",
256 "aml_video.1",
257 "amlvideo2.0",
258 "amlvideo2.1",
259 "ppmgr",
260 "ionvideo",
261 "ionvideo.1",
262 "ionvideo.2",
263 "ionvideo.3",
264 "ionvideo.4",
265 "ionvideo.5",
266 "ionvideo.6",
267 "ionvideo.7",
268 "ionvideo.8",
269 "videosync.0",
270 "v4lvideo.0",
271 "v4lvideo.1",
272 "v4lvideo.2",
273 "v4lvideo.3",
274 "v4lvideo.4",
275 "v4lvideo.5",
276 "v4lvideo.6",
277 "v4lvideo.7",
278 "v4lvideo.8",
677ab50d 279 "fake-amvideo",
4373e91a 280 "disable",
281 "reserved",
282};
283
05afa03d
PY
284static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1];
285
286
fe96802b
NQ
287int vdec_get_debug_flags(void)
288{
289 return debugflags;
290}
291EXPORT_SYMBOL(vdec_get_debug_flags);
292
17a06af5
RZ
293void VDEC_PRINT_FUN_LINENO(const char *fun, int line)
294{
295 if (debugflags & 0x10000000)
296 pr_info("%s, %d\n", fun, line);
297}
298EXPORT_SYMBOL(VDEC_PRINT_FUN_LINENO);
299
1418c7d8 300bool is_support_no_parser(void)
301{
302 if ((enable_stream_mode_multi_dec) ||
303 (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2))
304 return true;
305 return false;
306}
307EXPORT_SYMBOL(is_support_no_parser);
308
fe96802b
NQ
309unsigned char is_mult_inc(unsigned int type)
310{
311 unsigned char ret = 0;
312 if (vdec_get_debug_flags() & 0xf000)
313 ret = (vdec_get_debug_flags() & 0x1000)
314 ? 1 : 0;
315 else if (type & PORT_TYPE_DECODER_SCHED)
316 ret = 1;
317 return ret;
318}
319EXPORT_SYMBOL(is_mult_inc);
320
a6c89e96
NQ
321static const bool cores_with_input[VDEC_MAX] = {
322 true, /* VDEC_1 */
323 false, /* VDEC_HCODEC */
324 false, /* VDEC_2 */
325 true, /* VDEC_HEVC / VDEC_HEVC_FRONT */
326 false, /* VDEC_HEVC_BACK */
327};
328
329static const int cores_int[VDEC_MAX] = {
330 VDEC_IRQ_1,
331 VDEC_IRQ_2,
332 VDEC_IRQ_0,
333 VDEC_IRQ_0,
334 VDEC_IRQ_HEVC_BACK
335};
336
05afa03d
PY
337unsigned long vdec_canvas_lock(struct vdec_core_s *core)
338{
339 unsigned long flags;
340 spin_lock_irqsave(&core->canvas_lock, flags);
341
342 return flags;
343}
344
345void vdec_canvas_unlock(struct vdec_core_s *core, unsigned long flags)
346{
347 spin_unlock_irqrestore(&core->canvas_lock, flags);
348}
349
97fe3d16
PY
350unsigned long vdec_fps_lock(struct vdec_core_s *core)
351{
352 unsigned long flags;
353 spin_lock_irqsave(&core->fps_lock, flags);
354
355 return flags;
356}
357
358void vdec_fps_unlock(struct vdec_core_s *core, unsigned long flags)
359{
360 spin_unlock_irqrestore(&core->fps_lock, flags);
361}
05afa03d 362
b9164398
NQ
363unsigned long vdec_core_lock(struct vdec_core_s *core)
364{
365 unsigned long flags;
366
367 spin_lock_irqsave(&core->lock, flags);
368
369 return flags;
370}
371
372void vdec_core_unlock(struct vdec_core_s *core, unsigned long flags)
373{
374 spin_unlock_irqrestore(&core->lock, flags);
375}
376
0ed0f572
PY
377unsigned long vdec_inputbuff_lock(struct vdec_core_s *core)
378{
379 unsigned long flags;
380
381 spin_lock_irqsave(&core->input_lock, flags);
382
383 return flags;
384}
385
386void vdec_inputbuff_unlock(struct vdec_core_s *core, unsigned long flags)
387{
388 spin_unlock_irqrestore(&core->input_lock, flags);
389}
390
391
392static bool vdec_is_input_frame_empty(struct vdec_s *vdec) {
393 struct vdec_core_s *core = vdec_core;
394 bool ret;
395 unsigned long flags;
396
397 flags = vdec_inputbuff_lock(core);
e77bbe41 398 ret = !(vdec->core_mask & core->buff_flag);
0ed0f572
PY
399 vdec_inputbuff_unlock(core, flags);
400
401 return ret;
402}
403
404static void vdec_up(struct vdec_s *vdec)
405{
406 struct vdec_core_s *core = vdec_core;
407
408 if (debug & 8)
409 pr_info("vdec_up, id:%d\n", vdec->id);
410 up(&core->sem);
411}
412
413
97fe3d16
PY
414static u64 vdec_get_us_time_system(void)
415{
416 struct timeval tv;
417
418 do_gettimeofday(&tv);
419
420 return div64_u64(timeval_to_ns(&tv), 1000);
421}
422
423static void vdec_fps_clear(int id)
424{
425 if (id >= MAX_INSTANCE_MUN)
426 return;
427
428 vdec_core->decode_fps[id].frame_count = 0;
429 vdec_core->decode_fps[id].start_timestamp = 0;
430 vdec_core->decode_fps[id].last_timestamp = 0;
431 vdec_core->decode_fps[id].fps = 0;
432}
433
434static void vdec_fps_clearall(void)
435{
436 int i;
437
438 for (i = 0; i < MAX_INSTANCE_MUN; i++) {
439 vdec_core->decode_fps[i].frame_count = 0;
440 vdec_core->decode_fps[i].start_timestamp = 0;
441 vdec_core->decode_fps[i].last_timestamp = 0;
442 vdec_core->decode_fps[i].fps = 0;
443 }
444}
445
446static void vdec_fps_detec(int id)
447{
448 unsigned long flags;
449
450 if (fps_detection == 0)
451 return;
452
453 if (id >= MAX_INSTANCE_MUN)
454 return;
455
456 flags = vdec_fps_lock(vdec_core);
457
458 if (fps_clear == 1) {
459 vdec_fps_clearall();
460 fps_clear = 0;
461 }
462
463 vdec_core->decode_fps[id].frame_count++;
464 if (vdec_core->decode_fps[id].frame_count == 1) {
465 vdec_core->decode_fps[id].start_timestamp =
466 vdec_get_us_time_system();
467 vdec_core->decode_fps[id].last_timestamp =
468 vdec_core->decode_fps[id].start_timestamp;
469 } else {
470 vdec_core->decode_fps[id].last_timestamp =
471 vdec_get_us_time_system();
472 vdec_core->decode_fps[id].fps =
473 (u32)div_u64(((u64)(vdec_core->decode_fps[id].frame_count) *
474 10000000000),
475 (vdec_core->decode_fps[id].last_timestamp -
476 vdec_core->decode_fps[id].start_timestamp));
477 }
478 vdec_fps_unlock(vdec_core, flags);
479}
480
481
482
b9164398
NQ
483static int get_canvas(unsigned int index, unsigned int base)
484{
485 int start;
486 int canvas_index = index * base;
a35da9f0 487 int ret;
b9164398
NQ
488
489 if ((base > 4) || (base == 0))
490 return -1;
491
492 if ((AMVDEC_CANVAS_START_INDEX + canvas_index + base - 1)
493 <= AMVDEC_CANVAS_MAX1) {
494 start = AMVDEC_CANVAS_START_INDEX + base * index;
495 } else {
496 canvas_index -= (AMVDEC_CANVAS_MAX1 -
497 AMVDEC_CANVAS_START_INDEX + 1) / base * base;
498 if (canvas_index <= AMVDEC_CANVAS_MAX2)
499 start = canvas_index / base;
500 else
501 return -1;
502 }
503
504 if (base == 1) {
a35da9f0 505 ret = start;
b9164398 506 } else if (base == 2) {
a35da9f0 507 ret = ((start + 1) << 16) | ((start + 1) << 8) | start;
b9164398 508 } else if (base == 3) {
a35da9f0 509 ret = ((start + 2) << 16) | ((start + 1) << 8) | start;
b9164398 510 } else if (base == 4) {
a35da9f0 511 ret = (((start + 3) << 24) | (start + 2) << 16) |
b9164398
NQ
512 ((start + 1) << 8) | start;
513 }
514
a35da9f0 515 return ret;
b9164398
NQ
516}
517
05afa03d
PY
518static int get_canvas_ex(int type, int id)
519{
520 int i;
521 unsigned long flags;
522
523 flags = vdec_canvas_lock(vdec_core);
524
525 for (i = 0; i < CANVAS_MAX_SIZE; i++) {
05afa03d
PY
526 if ((canvas_stat[i].type == type) &&
527 (canvas_stat[i].id & (1 << id)) == 0) {
528 canvas_stat[i].canvas_used_flag++;
529 canvas_stat[i].id |= (1 << id);
be862a73
HZ
530 if (debug & 4)
531 pr_debug("get used canvas %d\n", i);
05afa03d
PY
532 vdec_canvas_unlock(vdec_core, flags);
533 if (i < AMVDEC_CANVAS_MAX2 + 1)
534 return i;
535 else
536 return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
537 }
538 }
539
540 for (i = 0; i < CANVAS_MAX_SIZE; i++) {
05afa03d
PY
541 if (canvas_stat[i].type == 0) {
542 canvas_stat[i].type = type;
543 canvas_stat[i].canvas_used_flag = 1;
544 canvas_stat[i].id = (1 << id);
be862a73
HZ
545 if (debug & 4) {
546 pr_debug("get canvas %d\n", i);
547 pr_debug("canvas_used_flag %d\n",
548 canvas_stat[i].canvas_used_flag);
549 pr_debug("canvas_stat[i].id %d\n",
550 canvas_stat[i].id);
551 }
05afa03d
PY
552 vdec_canvas_unlock(vdec_core, flags);
553 if (i < AMVDEC_CANVAS_MAX2 + 1)
554 return i;
555 else
556 return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
557 }
558 }
559 vdec_canvas_unlock(vdec_core, flags);
560
561 pr_info("cannot get canvas\n");
562
563 return -1;
564}
565
566static void free_canvas_ex(int index, int id)
567{
568 unsigned long flags;
569 int offset;
570
571 flags = vdec_canvas_lock(vdec_core);
572 if (index >= 0 &&
573 index < AMVDEC_CANVAS_MAX2 + 1)
574 offset = index;
575 else if ((index >= AMVDEC_CANVAS_START_INDEX) &&
576 (index <= AMVDEC_CANVAS_MAX1))
577 offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX;
578 else {
579 vdec_canvas_unlock(vdec_core, flags);
580 return;
581 }
582
583 if ((canvas_stat[offset].canvas_used_flag > 0) &&
584 (canvas_stat[offset].id & (1 << id))) {
585 canvas_stat[offset].canvas_used_flag--;
586 canvas_stat[offset].id &= ~(1 << id);
587 if (canvas_stat[offset].canvas_used_flag == 0) {
588 canvas_stat[offset].type = 0;
589 canvas_stat[offset].id = 0;
590 }
be862a73
HZ
591 if (debug & 4) {
592 pr_debug("free index %d used_flag %d, type = %d, id = %d\n",
593 offset,
594 canvas_stat[offset].canvas_used_flag,
595 canvas_stat[offset].type,
596 canvas_stat[offset].id);
597 }
05afa03d
PY
598 }
599 vdec_canvas_unlock(vdec_core, flags);
600
601 return;
602
603}
604
db9339b3
NQ
605static void vdec_dmc_pipeline_reset(void)
606{
607 /*
608 * bit15: vdec_piple
609 * bit14: hevc_dmc_piple
610 * bit13: hevcf_dmc_pipl
611 * bit12: wave420_dmc_pipl
612 * bit11: hcodec_dmc_pipl
613 */
614
615 WRITE_RESET_REG(RESET7_REGISTER,
616 (1 << 15) | (1 << 14) | (1 << 13) |
617 (1 << 12) | (1 << 11));
618}
619
620static void vdec_stop_armrisc(int hw)
621{
622 ulong timeout = jiffies + HZ;
623
624 if (hw == VDEC_INPUT_TARGET_VLD) {
625 WRITE_VREG(MPSR, 0);
626 WRITE_VREG(CPSR, 0);
627
628 while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
629 if (time_after(jiffies, timeout))
630 break;
631 }
632
633 timeout = jiffies + HZ;
634 while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) {
635 if (time_after(jiffies, timeout))
636 break;
637 }
638 } else if (hw == VDEC_INPUT_TARGET_HEVC) {
639 WRITE_VREG(HEVC_MPSR, 0);
640 WRITE_VREG(HEVC_CPSR, 0);
641
642 while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
643 if (time_after(jiffies, timeout))
644 break;
645 }
646
647 timeout = jiffies + HZ/10;
648 while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) {
649 if (time_after(jiffies, timeout))
650 break;
651 }
652 }
653}
654
144f5ee8
HZ
655static void vdec_disable_DMC(struct vdec_s *vdec)
656{
657 /*close first,then wait pedding end,timing suggestion from vlsi*/
658 struct vdec_input_s *input = &vdec->input;
659 unsigned long flags;
660 unsigned int mask = 0;
661
662 if (input->target == VDEC_INPUT_TARGET_VLD) {
663 mask = (1 << 13);
664 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
665 mask = (1 << 21);
666 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
667 mask = (1 << 4); /*hevc*/
668 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
669 mask |= (1 << 8); /*hevcb */
670 }
db9339b3
NQ
671
672 /* need to stop armrisc. */
673 if (!IS_ERR_OR_NULL(vdec->dev))
674 vdec_stop_armrisc(input->target);
675
144f5ee8
HZ
676 spin_lock_irqsave(&vdec_spin_lock, flags);
677 codec_dmcbus_write(DMC_REQ_CTRL,
db9339b3 678 codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
144f5ee8
HZ
679 spin_unlock_irqrestore(&vdec_spin_lock, flags);
680
1418c7d8 681 if (is_cpu_tm2_revb() ||
682 (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
97256936 683 while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
144f5ee8
HZ
684 & mask))
685 ;
97256936 686 } else {
687 while (!(codec_dmcbus_read(DMC_CHAN_STS)
688 & mask))
689 ;
690 }
144f5ee8
HZ
691
692 pr_debug("%s input->target= 0x%x\n", __func__, input->target);
693}
694
695static void vdec_enable_DMC(struct vdec_s *vdec)
696{
697 struct vdec_input_s *input = &vdec->input;
698 unsigned long flags;
699 unsigned int mask = 0;
700
701 if (input->target == VDEC_INPUT_TARGET_VLD) {
702 mask = (1 << 13);
703 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
704 mask = (1 << 21);
705 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
706 mask = (1 << 4); /*hevc*/
707 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
708 mask |= (1 << 8); /*hevcb */
709 }
db9339b3
NQ
710
711 /*must to be reset the dmc pipeline if it's g12b.*/
712 if (get_cpu_type() == AM_MESON_CPU_MAJOR_ID_G12B)
713 vdec_dmc_pipeline_reset();
714
144f5ee8
HZ
715 spin_lock_irqsave(&vdec_spin_lock, flags);
716 codec_dmcbus_write(DMC_REQ_CTRL,
db9339b3 717 codec_dmcbus_read(DMC_REQ_CTRL) | mask);
144f5ee8
HZ
718 spin_unlock_irqrestore(&vdec_spin_lock, flags);
719 pr_debug("%s input->target= 0x%x\n", __func__, input->target);
720}
05afa03d
PY
721
722
723
724static int vdec_get_hw_type(int value)
725{
726 int type;
727 switch (value) {
728 case VFORMAT_HEVC:
729 case VFORMAT_VP9:
730 case VFORMAT_AVS2:
97256936 731 case VFORMAT_AV1:
05afa03d
PY
732 type = CORE_MASK_HEVC;
733 break;
734
735 case VFORMAT_MPEG12:
736 case VFORMAT_MPEG4:
737 case VFORMAT_H264:
738 case VFORMAT_MJPEG:
739 case VFORMAT_REAL:
740 case VFORMAT_JPEG:
741 case VFORMAT_VC1:
742 case VFORMAT_AVS:
743 case VFORMAT_YUV:
744 case VFORMAT_H264MVC:
745 case VFORMAT_H264_4K2K:
746 case VFORMAT_H264_ENC:
747 case VFORMAT_JPEG_ENC:
748 type = CORE_MASK_VDEC_1;
749 break;
750
751 default:
752 type = -1;
753 }
754
755 return type;
756}
757
758
759static void vdec_save_active_hw(struct vdec_s *vdec)
760{
761 int type;
762
763 type = vdec_get_hw_type(vdec->port->vformat);
764
765 if (type == CORE_MASK_HEVC) {
766 vdec_core->active_hevc = vdec;
767 } else if (type == CORE_MASK_VDEC_1) {
768 vdec_core->active_vdec = vdec;
769 } else {
770 pr_info("save_active_fw wrong\n");
771 }
772}
773
0ed0f572
PY
774static void vdec_update_buff_status(void)
775{
776 struct vdec_core_s *core = vdec_core;
777 unsigned long flags;
778 struct vdec_s *vdec;
779
780 flags = vdec_inputbuff_lock(core);
781 core->buff_flag = 0;
782 core->stream_buff_flag = 0;
783 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
784 struct vdec_input_s *input = &vdec->input;
785 if (input_frame_based(input)) {
9d6acddf 786 if (input->have_frame_num || input->eos)
0ed0f572
PY
787 core->buff_flag |= vdec->core_mask;
788 } else if (input_stream_based(input)) {
e77bbe41 789 core->stream_buff_flag |= vdec->core_mask;
0ed0f572 790 }
fc199e88 791 /* slave el pre_decode_level wp update */
792 if ((is_support_no_parser()) && (vdec->slave)) {
793 STBUF_WRITE(&vdec->slave->vbuf, set_wp,
794 STBUF_READ(&vdec->vbuf, get_wp));
795 }
0ed0f572
PY
796 }
797 vdec_inputbuff_unlock(core, flags);
798}
799
e77bbe41 800#if 0
0ed0f572
PY
801void vdec_update_streambuff_status(void)
802{
803 struct vdec_core_s *core = vdec_core;
804 struct vdec_s *vdec;
805
806 /* check streaming prepare level threshold if not EOS */
807 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
808 struct vdec_input_s *input = &vdec->input;
809 if (input && input_stream_based(input) && !input->eos &&
810 (vdec->need_more_data & VDEC_NEED_MORE_DATA)) {
811 u32 rp, wp, level;
812
d631e9c2
HZ
813 rp = STBUF_READ(&vdec->vbuf, get_rp);
814 wp = STBUF_READ(&vdec->vbuf, get_wp);
0ed0f572
PY
815 if (wp < rp)
816 level = input->size + wp - rp;
817 else
818 level = wp - rp;
819 if ((level < input->prepare_level) &&
820 (pts_get_rec_num(PTS_TYPE_VIDEO,
821 vdec->input.total_rd_count) < 2)) {
822 break;
823 } else if (level > input->prepare_level) {
824 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
825 if (debug & 8)
826 pr_info("vdec_flush_streambuff_status up\n");
827 vdec_up(vdec);
828 }
829 break;
830 }
831 }
832}
833EXPORT_SYMBOL(vdec_update_streambuff_status);
e77bbe41 834#endif
b9164398 835
fe96802b 836int vdec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
b9164398 837{
9b670a2d 838 if (vdec && vdec->dec_status &&
839 ((vdec->status == VDEC_STATUS_CONNECTED ||
840 vdec->status == VDEC_STATUS_ACTIVE)))
b9164398
NQ
841 return vdec->dec_status(vdec, vstatus);
842
9b670a2d 843 return 0;
b9164398
NQ
844}
845EXPORT_SYMBOL(vdec_status);
846
847int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
848{
849 int r;
b9164398
NQ
850 if (vdec->set_trickmode) {
851 r = vdec->set_trickmode(vdec, trickmode);
852
853 if ((r == 0) && (vdec->slave) && (vdec->slave->set_trickmode))
854 r = vdec->slave->set_trickmode(vdec->slave,
855 trickmode);
976f3376 856 return r;
b9164398 857 }
b9164398
NQ
858 return -1;
859}
860EXPORT_SYMBOL(vdec_set_trickmode);
861
d481db31
NQ
862int vdec_set_isreset(struct vdec_s *vdec, int isreset)
863{
864 vdec->is_reset = isreset;
865 pr_info("is_reset=%d\n", isreset);
866 if (vdec->set_isreset)
867 return vdec->set_isreset(vdec, isreset);
868 return 0;
869}
870EXPORT_SYMBOL(vdec_set_isreset);
871
28e318df
NQ
872int vdec_set_dv_metawithel(struct vdec_s *vdec, int isdvmetawithel)
873{
874 vdec->dolby_meta_with_el = isdvmetawithel;
875 pr_info("isdvmetawithel=%d\n", isdvmetawithel);
876 return 0;
877}
c23e8aee 878EXPORT_SYMBOL(vdec_set_dv_metawithel);
28e318df
NQ
879
880void vdec_set_no_powerdown(int flag)
881{
882 no_powerdown = flag;
883 pr_info("no_powerdown=%d\n", no_powerdown);
884 return;
885}
c23e8aee 886EXPORT_SYMBOL(vdec_set_no_powerdown);
28e318df 887
fe96802b
NQ
888void vdec_count_info(struct vdec_info *vs, unsigned int err,
889 unsigned int offset)
890{
891 if (err)
892 vs->error_frame_count++;
893 if (offset) {
894 if (0 == vs->frame_count) {
895 vs->offset = 0;
896 vs->samp_cnt = 0;
897 }
898 vs->frame_data = offset > vs->total_data ?
899 offset - vs->total_data : vs->total_data - offset;
900 vs->total_data = offset;
901 if (vs->samp_cnt < 96000 * 2) { /* 2s */
902 if (0 == vs->samp_cnt)
903 vs->offset = offset;
904 vs->samp_cnt += vs->frame_dur;
905 } else {
906 vs->bit_rate = (offset - vs->offset) / 2;
907 /*pr_info("bitrate : %u\n",vs->bit_rate);*/
908 vs->samp_cnt = 0;
909 }
910 vs->frame_count++;
911 }
912 /*pr_info("size : %u, offset : %u, dur : %u, cnt : %u\n",
913 vs->offset,offset,vs->frame_dur,vs->samp_cnt);*/
914 return;
915}
916EXPORT_SYMBOL(vdec_count_info);
c23e8aee
HZ
917int vdec_is_support_4k(void)
918{
a8d5afab 919 return !is_meson_gxl_package_805X();
c23e8aee
HZ
920}
921EXPORT_SYMBOL(vdec_is_support_4k);
fe96802b 922
b9164398 923/*
e0614bf7 924 * clk_config:
b9164398
NQ
925 *0:default
926 *1:no gp0_pll;
927 *2:always used gp0_pll;
928 *>=10:fixed n M clk;
929 *== 100 , 100M clks;
e0614bf7 930 */
b9164398
NQ
931unsigned int get_vdec_clk_config_settings(void)
932{
933 return clk_config;
934}
935void update_vdec_clk_config_settings(unsigned int config)
936{
937 clk_config = config;
938}
939EXPORT_SYMBOL(update_vdec_clk_config_settings);
940
b9164398
NQ
941struct device *get_codec_cma_device(void)
942{
943 return vdec_core->cma_dev;
944}
945
fe96802b 946#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
947static const char * const vdec_device_name[] = {
948 "amvdec_mpeg12", "ammvdec_mpeg12",
949 "amvdec_mpeg4", "ammvdec_mpeg4",
950 "amvdec_h264", "ammvdec_h264",
951 "amvdec_mjpeg", "ammvdec_mjpeg",
952 "amvdec_real", "ammvdec_real",
953 "amjpegdec", "ammjpegdec",
954 "amvdec_vc1", "ammvdec_vc1",
955 "amvdec_avs", "ammvdec_avs",
956 "amvdec_yuv", "ammvdec_yuv",
957 "amvdec_h264mvc", "ammvdec_h264mvc",
958 "amvdec_h264_4k2k", "ammvdec_h264_4k2k",
959 "amvdec_h265", "ammvdec_h265",
960 "amvenc_avc", "amvenc_avc",
961 "jpegenc", "jpegenc",
a6c89e96 962 "amvdec_vp9", "ammvdec_vp9",
97256936 963 "amvdec_avs2", "ammvdec_avs2",
964 "amvdec_av1", "ammvdec_av1",
b9164398
NQ
965};
966
b9164398
NQ
967
968#else
969
970static const char * const vdec_device_name[] = {
971 "amvdec_mpeg12",
972 "amvdec_mpeg4",
973 "amvdec_h264",
974 "amvdec_mjpeg",
975 "amvdec_real",
976 "amjpegdec",
977 "amvdec_vc1",
978 "amvdec_avs",
979 "amvdec_yuv",
980 "amvdec_h264mvc",
981 "amvdec_h264_4k2k",
982 "amvdec_h265",
983 "amvenc_avc",
984 "jpegenc",
a6c89e96 985 "amvdec_vp9",
5fe5830f 986 "amvdec_avs2",
987 "amvdec_av1"
b9164398
NQ
988};
989
b9164398
NQ
990#endif
991
9457f9af
NQ
992/*
993 * Only support time sliced decoding for frame based input,
994 * so legacy decoder can exist with time sliced decoder.
995 */
996static const char *get_dev_name(bool use_legacy_vdec, int format)
997{
998#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
17a06af5 999 if (use_legacy_vdec && (debugflags & 0x8) == 0)
9457f9af
NQ
1000 return vdec_device_name[format * 2];
1001 else
1002 return vdec_device_name[format * 2 + 1];
1003#else
1004 return vdec_device_name[format];
1005#endif
1006}
1007
a6c89e96
NQ
1008#ifdef VDEC_DEBUG_SUPPORT
1009static u64 get_current_clk(void)
1010{
1011 /*struct timespec xtime = current_kernel_time();
1012 u64 usec = xtime.tv_sec * 1000000;
1013 usec += xtime.tv_nsec / 1000;
1014 */
1015 u64 usec = sched_clock();
1016 return usec;
1017}
1018
1019static void inc_profi_count(unsigned long mask, u32 *count)
1020{
1021 enum vdec_type_e type;
1022
1023 for (type = VDEC_1; type < VDEC_MAX; type++) {
1024 if (mask & (1 << type))
1025 count[type]++;
1026 }
1027}
1028
1029static void update_profi_clk_run(struct vdec_s *vdec,
1030 unsigned long mask, u64 clk)
1031{
1032 enum vdec_type_e type;
1033
1034 for (type = VDEC_1; type < VDEC_MAX; type++) {
1035 if (mask & (1 << type)) {
1036 vdec->start_run_clk[type] = clk;
1037 if (vdec->profile_start_clk[type] == 0)
1038 vdec->profile_start_clk[type] = clk;
1039 vdec->total_clk[type] = clk
1040 - vdec->profile_start_clk[type];
1041 /*pr_info("set start_run_clk %ld\n",
1042 vdec->start_run_clk);*/
1043
1044 }
1045 }
1046}
1047
1048static void update_profi_clk_stop(struct vdec_s *vdec,
1049 unsigned long mask, u64 clk)
1050{
1051 enum vdec_type_e type;
1052
1053 for (type = VDEC_1; type < VDEC_MAX; type++) {
1054 if (mask & (1 << type)) {
1055 if (vdec->start_run_clk[type] == 0)
1056 pr_info("error, start_run_clk[%d] not set\n", type);
1057
1058 /*pr_info("update run_clk type %d, %ld, %ld, %ld\n",
1059 type,
1060 clk,
1061 vdec->start_run_clk[type],
1062 vdec->run_clk[type]);*/
1063 vdec->run_clk[type] +=
1064 (clk - vdec->start_run_clk[type]);
1065 }
1066 }
1067}
1068
1069#endif
1070
b9164398
NQ
1071int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p)
1072{
1073 if (copy_from_user((void *)&vdec->sys_info_store, (void *)p,
1074 sizeof(struct dec_sysinfo)))
1075 return -EFAULT;
1076
52a31dc3
NQ
1077 /* force switch to mult instance if supports this profile. */
1078 if ((vdec->type == VDEC_TYPE_SINGLE) &&
1079 !disable_switch_single_to_mult) {
1080 const char *str = NULL;
1081 char fmt[16] = {0};
1082
1083 str = strchr(get_dev_name(false, vdec->format), '_');
1084 if (!str)
1085 return -1;
1086
1087 sprintf(fmt, "m%s", ++str);
1088 if (is_support_profile(fmt) &&
97256936 1089 vdec->sys_info->format != VIDEO_DEC_FORMAT_H263 &&
1090 vdec->format != VFORMAT_AV1)
52a31dc3
NQ
1091 vdec->type = VDEC_TYPE_STREAM_PARSER;
1092 }
1093
b9164398
NQ
1094 return 0;
1095}
1096EXPORT_SYMBOL(vdec_set_decinfo);
1097
1098/* construct vdec strcture */
1099struct vdec_s *vdec_create(struct stream_port_s *port,
1100 struct vdec_s *master)
1101{
1102 struct vdec_s *vdec;
1103 int type = VDEC_TYPE_SINGLE;
fe96802b 1104 int id;
9457f9af 1105
fe96802b 1106 if (is_mult_inc(port->type))
b9164398
NQ
1107 type = (port->type & PORT_TYPE_FRAME) ?
1108 VDEC_TYPE_FRAME_BLOCK :
1109 VDEC_TYPE_STREAM_PARSER;
1110
fe96802b
NQ
1111 id = ida_simple_get(&vdec_core->ida,
1112 0, MAX_INSTANCE_MUN, GFP_KERNEL);
1113 if (id < 0) {
1114 pr_info("vdec_create request id failed!ret =%d\n", id);
1115 return NULL;
1116 }
b9164398
NQ
1117 vdec = vzalloc(sizeof(struct vdec_s));
1118
1119 /* TBD */
1120 if (vdec) {
1121 vdec->magic = 0x43454456;
fe96802b 1122 vdec->id = -1;
b9164398
NQ
1123 vdec->type = type;
1124 vdec->port = port;
1125 vdec->sys_info = &vdec->sys_info_store;
1126
1127 INIT_LIST_HEAD(&vdec->list);
1128
b9164398 1129 atomic_inc(&vdec_core->vdec_nr);
6e5153ec 1130#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
1131 v4lvideo_dec_count_increase();
1132#endif
fe96802b
NQ
1133 vdec->id = id;
1134 vdec_input_init(&vdec->input, vdec);
0ed0f572
PY
1135 vdec->input.vdec_is_input_frame_empty = vdec_is_input_frame_empty;
1136 vdec->input.vdec_up = vdec_up;
b9164398
NQ
1137 if (master) {
1138 vdec->master = master;
1139 master->slave = vdec;
1140 master->sched = 1;
1141 }
cc41710a 1142 if (enable_mvdec_info) {
1143 vdec->mvfrm = (struct vdec_frames_s *)
1144 vzalloc(sizeof(struct vdec_frames_s));
1145 if (!vdec->mvfrm)
1146 pr_err("vzalloc: vdec_frames_s failed\n");
1147 }
b9164398
NQ
1148 }
1149
5166ea72
NQ
1150 pr_debug("vdec_create instance %p, total %d, PM: %s\n", vdec,
1151 atomic_read(&vdec_core->vdec_nr),
1152 get_pm_name(vdec_core->pm->pm_type));
b9164398 1153
fe96802b
NQ
1154 //trace_vdec_create(vdec); /*DEBUG_TMP*/
1155
b9164398
NQ
1156 return vdec;
1157}
1158EXPORT_SYMBOL(vdec_create);
1159
1160int vdec_set_format(struct vdec_s *vdec, int format)
1161{
1162 vdec->format = format;
fe96802b 1163 vdec->port_flag |= PORT_FLAG_VFORMAT;
b9164398 1164
fe96802b 1165 if (vdec->slave) {
b9164398 1166 vdec->slave->format = format;
fe96802b
NQ
1167 vdec->slave->port_flag |= PORT_FLAG_VFORMAT;
1168 }
fe96802b 1169 //trace_vdec_set_format(vdec, format);/*DEBUG_TMP*/
b9164398
NQ
1170
1171 return 0;
1172}
1173EXPORT_SYMBOL(vdec_set_format);
1174
1175int vdec_set_pts(struct vdec_s *vdec, u32 pts)
1176{
1177 vdec->pts = pts;
fe96802b 1178 vdec->pts64 = div64_u64((u64)pts * 100, 9);
b9164398 1179 vdec->pts_valid = true;
fe96802b 1180 //trace_vdec_set_pts(vdec, (u64)pts);/*DEBUG_TMP*/
b9164398
NQ
1181 return 0;
1182}
1183EXPORT_SYMBOL(vdec_set_pts);
1184
6b7ee58f
NQ
1185void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp)
1186{
1187 vdec->timestamp = timestamp;
1188 vdec->timestamp_valid = true;
1189}
1190EXPORT_SYMBOL(vdec_set_timestamp);
1191
b9164398
NQ
1192int vdec_set_pts64(struct vdec_s *vdec, u64 pts64)
1193{
1194 vdec->pts64 = pts64;
fe96802b 1195 vdec->pts = (u32)div64_u64(pts64 * 9, 100);
b9164398 1196 vdec->pts_valid = true;
fe96802b
NQ
1197
1198 //trace_vdec_set_pts64(vdec, pts64);/*DEBUG_TMP*/
b9164398
NQ
1199 return 0;
1200}
1201EXPORT_SYMBOL(vdec_set_pts64);
1202
6b7ee58f
NQ
1203int vdec_get_status(struct vdec_s *vdec)
1204{
1205 return vdec->status;
1206}
1207EXPORT_SYMBOL(vdec_get_status);
1208
2cd6815e
NQ
1209int vdec_get_frame_num(struct vdec_s *vdec)
1210{
1211 return vdec->input.have_frame_num;
1212}
1213EXPORT_SYMBOL(vdec_get_frame_num);
1214
b9164398
NQ
1215void vdec_set_status(struct vdec_s *vdec, int status)
1216{
fe96802b 1217 //trace_vdec_set_status(vdec, status);/*DEBUG_TMP*/
b9164398
NQ
1218 vdec->status = status;
1219}
1220EXPORT_SYMBOL(vdec_set_status);
1221
1222void vdec_set_next_status(struct vdec_s *vdec, int status)
1223{
fe96802b 1224 //trace_vdec_set_next_status(vdec, status);/*DEBUG_TMP*/
b9164398
NQ
1225 vdec->next_status = status;
1226}
1227EXPORT_SYMBOL(vdec_set_next_status);
1228
1229int vdec_set_video_path(struct vdec_s *vdec, int video_path)
1230{
1231 vdec->frame_base_video_path = video_path;
1232 return 0;
1233}
1234EXPORT_SYMBOL(vdec_set_video_path);
1235
fe96802b
NQ
1236int vdec_set_receive_id(struct vdec_s *vdec, int receive_id)
1237{
1238 vdec->vf_receiver_inst = receive_id;
1239 return 0;
1240}
1241EXPORT_SYMBOL(vdec_set_receive_id);
1242
b9164398
NQ
1243/* add frame data to input chain */
1244int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count)
1245{
1246 return vdec_input_add_frame(&vdec->input, buf, count);
1247}
1248EXPORT_SYMBOL(vdec_write_vframe);
1249
17310557 1250int vdec_write_vframe_with_dma(struct vdec_s *vdec,
d04e649b 1251 ulong addr, size_t count, u32 handle, chunk_free free, void* priv)
17310557 1252{
d04e649b
SZ
1253 return vdec_input_add_frame_with_dma(&vdec->input,
1254 addr, count, handle, free, priv);
17310557
NQ
1255}
1256EXPORT_SYMBOL(vdec_write_vframe_with_dma);
1257
fe96802b
NQ
1258/* add a work queue thread for vdec*/
1259void vdec_schedule_work(struct work_struct *work)
1260{
1261 if (vdec_core->vdec_core_wq)
1262 queue_work(vdec_core->vdec_core_wq, work);
1263 else
1264 schedule_work(work);
1265}
1266EXPORT_SYMBOL(vdec_schedule_work);
1267
1268static struct vdec_s *vdec_get_associate(struct vdec_s *vdec)
1269{
1270 if (vdec->master)
1271 return vdec->master;
1272 else if (vdec->slave)
1273 return vdec->slave;
1274 return NULL;
1275}
1276
1277static void vdec_sync_input_read(struct vdec_s *vdec)
1278{
1279 if (!vdec_stream_based(vdec))
1280 return;
1281
1282 if (vdec_dual(vdec)) {
1283 u32 me, other;
1284 if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
1285 me = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
1286 other =
1287 vdec_get_associate(vdec)->input.stream_cookie;
1288 if (me > other)
1289 return;
1290 else if (me == other) {
1291 me = READ_VREG(VLD_MEM_VIFIFO_RP);
1292 other =
1293 vdec_get_associate(vdec)->input.swap_rp;
1294 if (me > other) {
d631e9c2
HZ
1295 STBUF_WRITE(&vdec->vbuf, set_rp,
1296 vdec_get_associate(vdec)->input.swap_rp);
fe96802b
NQ
1297 return;
1298 }
1299 }
d631e9c2
HZ
1300
1301 STBUF_WRITE(&vdec->vbuf, set_rp,
fe96802b
NQ
1302 READ_VREG(VLD_MEM_VIFIFO_RP));
1303 } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
1304 me = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
1305 if (((me & 0x80000000) == 0) &&
1306 (vdec->input.streaming_rp & 0x80000000))
1307 me += 1ULL << 32;
1308 other = vdec_get_associate(vdec)->input.streaming_rp;
1309 if (me > other) {
d631e9c2
HZ
1310 STBUF_WRITE(&vdec->vbuf, set_rp,
1311 vdec_get_associate(vdec)->input.swap_rp);
fe96802b
NQ
1312 return;
1313 }
1314
d631e9c2 1315 STBUF_WRITE(&vdec->vbuf, set_rp,
fe96802b
NQ
1316 READ_VREG(HEVC_STREAM_RD_PTR));
1317 }
1318 } else if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
d631e9c2 1319 STBUF_WRITE(&vdec->vbuf, set_rp,
fe96802b
NQ
1320 READ_VREG(VLD_MEM_VIFIFO_RP));
1321 } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
d631e9c2 1322 STBUF_WRITE(&vdec->vbuf, set_rp,
fe96802b
NQ
1323 READ_VREG(HEVC_STREAM_RD_PTR));
1324 }
1325}
1326
1327static void vdec_sync_input_write(struct vdec_s *vdec)
1328{
1329 if (!vdec_stream_based(vdec))
1330 return;
1331
1332 if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
1418c7d8 1333 if (is_support_no_parser()) {
527e712a
NQ
1334 if (!vdec->master) {
1335 WRITE_VREG(VLD_MEM_VIFIFO_WP,
1336 STBUF_READ(&vdec->vbuf, get_wp));
1337 } else {
1338 STBUF_WRITE(&vdec->vbuf, set_wp,
1339 STBUF_READ(&vdec->master->vbuf, get_wp));
1340 }
1341 } else {
1342 WRITE_VREG(VLD_MEM_VIFIFO_WP,
1343 STBUF_READ(&vdec->vbuf, get_wp));
1344 }
fe96802b 1345 } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
1418c7d8 1346 if (is_support_no_parser()) {
527e712a
NQ
1347 if (!vdec->master) {
1348 WRITE_VREG(HEVC_STREAM_WR_PTR,
1349 STBUF_READ(&vdec->vbuf, get_wp));
1350 } else {
1351 STBUF_WRITE(&vdec->vbuf, set_wp,
1352 STBUF_READ(&vdec->master->vbuf, get_wp));
1353 }
1354 } else {
1355 WRITE_VREG(HEVC_STREAM_WR_PTR,
1356 STBUF_READ(&vdec->vbuf, get_wp));
1357 }
fe96802b
NQ
1358 }
1359}
1360
6bdc30f9
PY
1361void vdec_stream_skip_data(struct vdec_s *vdec, int skip_size)
1362{
1363 u32 rp_set;
1364 struct vdec_input_s *input = &vdec->input;
1365 u32 rp = 0, wp = 0, level;
1366
1367 rp = STBUF_READ(&vdec->vbuf, get_rp);
1368 wp = STBUF_READ(&vdec->vbuf, get_wp);
6bdc30f9
PY
1369
1370 if (wp > rp)
1371 level = wp - rp;
1372 else
1373 level = wp + vdec->input.size - rp ;
1374
1375 if (level <= skip_size) {
1376 pr_err("skip size is error, buffer level = 0x%x, skip size = 0x%x\n", level, skip_size);
1377 return;
1378 }
1379
1380 if (wp >= rp) {
6bdc30f9
PY
1381 rp_set = rp + skip_size;
1382 }
1383 else if ((rp + skip_size) < (input->start + input->size)) {
6bdc30f9
PY
1384 rp_set = rp + skip_size;
1385 } else {
6bdc30f9
PY
1386 rp_set = rp + skip_size - input->size;
1387 input->stream_cookie++;
1388 }
1389
1390 if (vdec->format == VFORMAT_H264)
1391 SET_VREG_MASK(POWER_CTL_VLD,
1392 (1 << 9));
1393
1394 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1395
1396 /* restore read side */
1397 WRITE_VREG(VLD_MEM_SWAP_ADDR,
1398 input->swap_page_phys);
1399 WRITE_VREG(VLD_MEM_SWAP_CTL, 1);
1400
1401 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
1402 ;
1403 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
1404
1405 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
1406 rp_set);
1407 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
1408 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1409 STBUF_WRITE(&vdec->vbuf, set_rp,
1410 rp_set);
1411 WRITE_VREG(VLD_MEM_SWAP_ADDR,
1412 input->swap_page_phys);
1413 WRITE_VREG(VLD_MEM_SWAP_CTL, 3);
1414 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
1415 ;
1416 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
6bdc30f9
PY
1417}
1418EXPORT_SYMBOL(vdec_stream_skip_data);
1419
b9164398 1420/*
e0614bf7
ZZ
1421 *get next frame from input chain
1422 */
b9164398 1423/*
e0614bf7 1424 *THE VLD_FIFO is 512 bytes and Video buffer level
b9164398
NQ
1425 * empty interrupt is set to 0x80 bytes threshold
1426 */
1427#define VLD_PADDING_SIZE 1024
1428#define HEVC_PADDING_SIZE (1024*16)
b9164398
NQ
1429int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
1430{
fe96802b 1431 struct vdec_input_s *input = &vdec->input;
b9164398
NQ
1432 struct vframe_chunk_s *chunk = NULL;
1433 struct vframe_block_list_s *block = NULL;
1434 int dummy;
1435
1436 /* full reset to HW input */
1437 if (input->target == VDEC_INPUT_TARGET_VLD) {
1438 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1439
1440 /* reset VLD fifo for all vdec */
1441 WRITE_VREG(DOS_SW_RESET0, (1<<5) | (1<<4) | (1<<3));
1442 WRITE_VREG(DOS_SW_RESET0, 0);
1418c7d8 1443 if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2)
1444 dummy = READ_RESET_REG(RESET0_REGISTER);
b9164398
NQ
1445 WRITE_VREG(POWER_CTL_VLD, 1 << 4);
1446 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1447#if 0
1448 /*move to driver*/
1449 if (input_frame_based(input))
1450 WRITE_VREG(HEVC_STREAM_CONTROL, 0);
1451
1452 /*
1453 * 2: assist
1454 * 3: parser
1455 * 4: parser_state
1456 * 8: dblk
1457 * 11:mcpu
1458 * 12:ccpu
1459 * 13:ddr
1460 * 14:iqit
1461 * 15:ipp
1462 * 17:qdct
1463 * 18:mpred
1464 * 19:sao
1465 * 24:hevc_afifo
1466 */
1467 WRITE_VREG(DOS_SW_RESET3,
1468 (1<<3)|(1<<4)|(1<<8)|(1<<11)|(1<<12)|(1<<14)|(1<<15)|
1469 (1<<17)|(1<<18)|(1<<19));
1470 WRITE_VREG(DOS_SW_RESET3, 0);
1471#endif
1472 }
1473
1474 /*
e0614bf7 1475 *setup HW decoder input buffer (VLD context)
b9164398
NQ
1476 * based on input->type and input->target
1477 */
1478 if (input_frame_based(input)) {
1479 chunk = vdec_input_next_chunk(&vdec->input);
1480
1481 if (chunk == NULL) {
1482 *p = NULL;
1483 return -1;
1484 }
1485
1486 block = chunk->block;
1487
1488 if (input->target == VDEC_INPUT_TARGET_VLD) {
1489 WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, block->start);
1490 WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, block->start +
1491 block->size - 8);
1492 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
1493 round_down(block->start + chunk->offset,
fe96802b 1494 VDEC_FIFO_ALIGN));
b9164398
NQ
1495
1496 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
1497 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1498
1499 /* set to manual mode */
1500 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
1501 WRITE_VREG(VLD_MEM_VIFIFO_RP,
1502 round_down(block->start + chunk->offset,
fe96802b 1503 VDEC_FIFO_ALIGN));
b9164398
NQ
1504 dummy = chunk->offset + chunk->size +
1505 VLD_PADDING_SIZE;
1506 if (dummy >= block->size)
1507 dummy -= block->size;
1508 WRITE_VREG(VLD_MEM_VIFIFO_WP,
fe96802b
NQ
1509 round_down(block->start + dummy,
1510 VDEC_FIFO_ALIGN));
b9164398
NQ
1511
1512 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3);
1513 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
1514
1515 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
1516 (0x11 << 16) | (1<<10) | (7<<3));
1517
1518 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1519 WRITE_VREG(HEVC_STREAM_START_ADDR, block->start);
1520 WRITE_VREG(HEVC_STREAM_END_ADDR, block->start +
1521 block->size);
1522 WRITE_VREG(HEVC_STREAM_RD_PTR, block->start +
1523 chunk->offset);
1524 dummy = chunk->offset + chunk->size +
1525 HEVC_PADDING_SIZE;
1526 if (dummy >= block->size)
1527 dummy -= block->size;
1528 WRITE_VREG(HEVC_STREAM_WR_PTR,
fe96802b
NQ
1529 round_down(block->start + dummy,
1530 VDEC_FIFO_ALIGN));
b9164398
NQ
1531
1532 /* set endian */
1533 SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
1534 }
1535
1536 *p = chunk;
1537 return chunk->size;
1538
1539 } else {
fe96802b 1540 /* stream based */
4c48dede 1541 u32 rp = 0, wp = 0, fifo_len = 0, first_set_rp = 0;
b9164398 1542 int size;
fe96802b
NQ
1543 bool swap_valid = input->swap_valid;
1544 unsigned long swap_page_phys = input->swap_page_phys;
1545
1546 if (vdec_dual(vdec) &&
1547 ((vdec->flag & VDEC_FLAG_SELF_INPUT_CONTEXT) == 0)) {
1548 /* keep using previous input context */
1549 struct vdec_s *master = (vdec->slave) ?
1550 vdec : vdec->master;
1551 if (master->input.last_swap_slave) {
1552 swap_valid = master->slave->input.swap_valid;
1553 swap_page_phys =
1554 master->slave->input.swap_page_phys;
1555 } else {
1556 swap_valid = master->input.swap_valid;
1557 swap_page_phys = master->input.swap_page_phys;
1558 }
1559 }
1560
1561 if (swap_valid) {
b9164398 1562 if (input->target == VDEC_INPUT_TARGET_VLD) {
fe96802b
NQ
1563 if (vdec->format == VFORMAT_H264)
1564 SET_VREG_MASK(POWER_CTL_VLD,
1565 (1 << 9));
1566
b9164398
NQ
1567 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1568
1569 /* restore read side */
1570 WRITE_VREG(VLD_MEM_SWAP_ADDR,
fe96802b 1571 swap_page_phys);
b9164398
NQ
1572 WRITE_VREG(VLD_MEM_SWAP_CTL, 1);
1573
1574 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
1575 ;
1576 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
bba22b6d 1577#ifdef VDEC_FCC_SUPPORT
1578 vdec_fcc_jump_back(vdec);
1579#endif
b9164398
NQ
1580
1581 /* restore wrap count */
1582 WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT,
1583 input->stream_cookie);
1584
1585 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1586 fifo_len = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
1587
1588 /* enable */
1589 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
1590 (0x11 << 16) | (1<<10));
1591
d631e9c2
HZ
1592 if (vdec->vbuf.no_parser)
1593 SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
1594 7 << 3);
1595
fe96802b
NQ
1596 /* sync with front end */
1597 vdec_sync_input_read(vdec);
1598 vdec_sync_input_write(vdec);
b9164398
NQ
1599
1600 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1601 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1602 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
1603
1604 /* restore read side */
1605 WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
fe96802b 1606 swap_page_phys);
b9164398
NQ
1607 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1);
1608
1609 while (READ_VREG(HEVC_STREAM_SWAP_CTRL)
1610 & (1<<7))
1611 ;
1612 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
bba22b6d 1613#ifdef VDEC_FCC_SUPPORT
1614 vdec_fcc_jump_back(vdec);
1615#endif
b9164398
NQ
1616 /* restore stream offset */
1617 WRITE_VREG(HEVC_SHIFT_BYTE_COUNT,
1618 input->stream_cookie);
1619
1620 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1621 fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
1622 >> 16) & 0x7f;
1623
1624
1625 /* enable */
1626
fe96802b
NQ
1627 /* sync with front end */
1628 vdec_sync_input_read(vdec);
1629 vdec_sync_input_write(vdec);
b9164398
NQ
1630
1631 wp = READ_VREG(HEVC_STREAM_WR_PTR);
fe96802b 1632
d631e9c2
HZ
1633 if (vdec->vbuf.no_parser)
1634 SET_VREG_MASK(HEVC_STREAM_CONTROL,
1635 7 << 4);
fe96802b 1636 /*pr_info("vdec: restore context\r\n");*/
b9164398
NQ
1637 }
1638
1639 } else {
e75f3183 1640 if (vdec->vbuf.ext_buf_addr)
1641 first_set_rp = STBUF_READ(&vdec->vbuf, get_rp);
1642 else
4c48dede 1643 first_set_rp = input->start;
1644
b9164398
NQ
1645 if (input->target == VDEC_INPUT_TARGET_VLD) {
1646 WRITE_VREG(VLD_MEM_VIFIFO_START_PTR,
1647 input->start);
1648 WRITE_VREG(VLD_MEM_VIFIFO_END_PTR,
1649 input->start + input->size - 8);
1650 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
4c48dede 1651 first_set_rp);
b9164398
NQ
1652
1653 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
1654 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1655
1656 /* set to manual mode */
1657 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
4c48dede 1658 WRITE_VREG(VLD_MEM_VIFIFO_RP, first_set_rp);
b9164398 1659 WRITE_VREG(VLD_MEM_VIFIFO_WP,
d631e9c2 1660 STBUF_READ(&vdec->vbuf, get_wp));
b9164398
NQ
1661 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1662
1663 /* enable */
1664 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
1665 (0x11 << 16) | (1<<10));
d631e9c2
HZ
1666 if (vdec->vbuf.no_parser)
1667 SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
1668 7 << 3);
b9164398
NQ
1669
1670 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1671
1672 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1673 WRITE_VREG(HEVC_STREAM_START_ADDR,
1674 input->start);
1675 WRITE_VREG(HEVC_STREAM_END_ADDR,
1676 input->start + input->size);
1677 WRITE_VREG(HEVC_STREAM_RD_PTR,
4c48dede 1678 first_set_rp);
b9164398 1679 WRITE_VREG(HEVC_STREAM_WR_PTR,
d631e9c2 1680 STBUF_READ(&vdec->vbuf, get_wp));
b9164398
NQ
1681 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1682 wp = READ_VREG(HEVC_STREAM_WR_PTR);
1683 fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
1684 >> 16) & 0x7f;
d631e9c2
HZ
1685 if (vdec->vbuf.no_parser)
1686 SET_VREG_MASK(HEVC_STREAM_CONTROL,
1687 7 << 4);
b9164398
NQ
1688 /* enable */
1689 }
1690 }
1691 *p = NULL;
1692 if (wp >= rp)
1693 size = wp - rp + fifo_len;
1694 else
1695 size = wp + input->size - rp + fifo_len;
1696 if (size < 0) {
1697 pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n",
1698 __func__, input->size, wp, rp, fifo_len, size);
1699 size = 0;
1700 }
1701 return size;
1702 }
1703}
1704EXPORT_SYMBOL(vdec_prepare_input);
1705
1706void vdec_enable_input(struct vdec_s *vdec)
1707{
1708 struct vdec_input_s *input = &vdec->input;
1709
1710 if (vdec->status != VDEC_STATUS_ACTIVE)
1711 return;
1712
1713 if (input->target == VDEC_INPUT_TARGET_VLD)
1714 SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1<<2) | (1<<1));
1715 else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1716 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
d631e9c2
HZ
1717 if (vdec_stream_based(vdec)) {
1718 if (vdec->vbuf.no_parser)
1719 /*set endian for non-parser mode. */
1720 SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
1721 else
1722 CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
1723 } else
b9164398 1724 SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
d631e9c2 1725
b9164398
NQ
1726 SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29));
1727 }
1728}
1729EXPORT_SYMBOL(vdec_enable_input);
1730
fe96802b
NQ
1731int vdec_set_input_buffer(struct vdec_s *vdec, u32 start, u32 size)
1732{
1733 int r = vdec_input_set_buffer(&vdec->input, start, size);
1734
1735 if (r)
1736 return r;
1737
1738 if (vdec->slave)
1739 r = vdec_input_set_buffer(&vdec->slave->input, start, size);
1740
1741 return r;
1742}
1743EXPORT_SYMBOL(vdec_set_input_buffer);
1744
1745/*
1746 * vdec_eos returns the possibility that there are
1747 * more input can be used by decoder through vdec_prepare_input
1748 * Note: this function should be called prior to vdec_vframe_dirty
1749 * by decoder driver to determine if EOS happens for stream based
1750 * decoding when there is no sufficient data for a frame
1751 */
1752bool vdec_has_more_input(struct vdec_s *vdec)
1753{
1754 struct vdec_input_s *input = &vdec->input;
1755
1756 if (!input->eos)
1757 return true;
1758
1759 if (input_frame_based(input))
1760 return vdec_input_next_input_chunk(input) != NULL;
1761 else {
1762 if (input->target == VDEC_INPUT_TARGET_VLD)
1763 return READ_VREG(VLD_MEM_VIFIFO_WP) !=
d631e9c2 1764 STBUF_READ(&vdec->vbuf, get_wp);
fe96802b
NQ
1765 else {
1766 return (READ_VREG(HEVC_STREAM_WR_PTR) & ~0x3) !=
d631e9c2 1767 (STBUF_READ(&vdec->vbuf, get_wp) & ~0x3);
fe96802b
NQ
1768 }
1769 }
1770}
1771EXPORT_SYMBOL(vdec_has_more_input);
1772
1773void vdec_set_prepare_level(struct vdec_s *vdec, int level)
1774{
1775 vdec->input.prepare_level = level;
1776}
1777EXPORT_SYMBOL(vdec_set_prepare_level);
1778
b9164398
NQ
1779void vdec_set_flag(struct vdec_s *vdec, u32 flag)
1780{
1781 vdec->flag = flag;
1782}
fe96802b
NQ
1783EXPORT_SYMBOL(vdec_set_flag);
1784
1785void vdec_set_eos(struct vdec_s *vdec, bool eos)
1786{
9d6acddf 1787 struct vdec_core_s *core = vdec_core;
6cfc5cce 1788
fe96802b
NQ
1789 vdec->input.eos = eos;
1790
1791 if (vdec->slave)
1792 vdec->slave->input.eos = eos;
9d6acddf 1793 up(&core->sem);
fe96802b
NQ
1794}
1795EXPORT_SYMBOL(vdec_set_eos);
b9164398 1796
a6c89e96
NQ
1797#ifdef VDEC_DEBUG_SUPPORT
1798void vdec_set_step_mode(void)
1799{
1800 step_mode = 0x1ff;
1801}
1802EXPORT_SYMBOL(vdec_set_step_mode);
1803#endif
1804
b9164398
NQ
1805void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec)
1806{
1807 if (vdec && next_vdec) {
1808 vdec->sched = 0;
1809 next_vdec->sched = 1;
1810 }
1811}
fe96802b
NQ
1812EXPORT_SYMBOL(vdec_set_next_sched);
1813
1814/*
1815 * Swap Context: S0 S1 S2 S3 S4
1816 * Sample sequence: M S M M S
1817 * Master Context: S0 S0 S2 S3 S3
1818 * Slave context: NA S1 S1 S2 S4
1819 * ^
1820 * ^
1821 * ^
1822 * the tricky part
1823 * If there are back to back decoding of master or slave
1824 * then the context of the counter part should be updated
1825 * with current decoder. In this example, S1 should be
1826 * updated to S2.
1827 * This is done by swap the swap_page and related info
1828 * between two layers.
1829 */
1830static void vdec_borrow_input_context(struct vdec_s *vdec)
1831{
1832 struct page *swap_page;
1833 unsigned long swap_page_phys;
1834 struct vdec_input_s *me;
1835 struct vdec_input_s *other;
1836
1837 if (!vdec_dual(vdec))
1838 return;
1839
1840 me = &vdec->input;
1841 other = &vdec_get_associate(vdec)->input;
1842
1843 /* swap the swap_context, borrow counter part's
1844 * swap context storage and update all related info.
1845 * After vdec_vframe_dirty, vdec_save_input_context
1846 * will be called to update current vdec's
1847 * swap context
1848 */
1849 swap_page = other->swap_page;
1850 other->swap_page = me->swap_page;
1851 me->swap_page = swap_page;
1852
1853 swap_page_phys = other->swap_page_phys;
1854 other->swap_page_phys = me->swap_page_phys;
1855 me->swap_page_phys = swap_page_phys;
1856
1857 other->swap_rp = me->swap_rp;
1858 other->streaming_rp = me->streaming_rp;
1859 other->stream_cookie = me->stream_cookie;
1860 other->swap_valid = me->swap_valid;
1861}
1862
b9164398
NQ
1863void vdec_vframe_dirty(struct vdec_s *vdec, struct vframe_chunk_s *chunk)
1864{
1865 if (chunk)
1866 chunk->flag |= VFRAME_CHUNK_FLAG_CONSUMED;
1867
1868 if (vdec_stream_based(vdec)) {
fe96802b
NQ
1869 vdec->input.swap_needed = true;
1870
1871 if (vdec_dual(vdec)) {
1872 vdec_get_associate(vdec)->input.dirty_count = 0;
1873 vdec->input.dirty_count++;
1874 if (vdec->input.dirty_count > 1) {
1875 vdec->input.dirty_count = 1;
1876 vdec_borrow_input_context(vdec);
1877 }
b9164398 1878 }
fe96802b
NQ
1879
1880 /* for stream based mode, we update read and write pointer
1881 * also in case decoder wants to keep working on decoding
1882 * for more frames while input front end has more data
1883 */
1884 vdec_sync_input_read(vdec);
1885 vdec_sync_input_write(vdec);
1886
1887 vdec->need_more_data |= VDEC_NEED_MORE_DATA_DIRTY;
1888 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
b9164398
NQ
1889 }
1890}
1891EXPORT_SYMBOL(vdec_vframe_dirty);
1892
fe96802b
NQ
1893bool vdec_need_more_data(struct vdec_s *vdec)
1894{
1895 if (vdec_stream_based(vdec))
1896 return vdec->need_more_data & VDEC_NEED_MORE_DATA;
1897
1898 return false;
1899}
1900EXPORT_SYMBOL(vdec_need_more_data);
1901
976f3376
HZ
1902
1903void hevc_wait_ddr(void)
1904{
1905 unsigned long flags;
144f5ee8
HZ
1906 unsigned int mask = 0;
1907
1908 mask = 1 << 4; /* hevc */
1909 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
1910 mask |= (1 << 8); /* hevcb */
1911
976f3376
HZ
1912 spin_lock_irqsave(&vdec_spin_lock, flags);
1913 codec_dmcbus_write(DMC_REQ_CTRL,
144f5ee8 1914 codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
976f3376
HZ
1915 spin_unlock_irqrestore(&vdec_spin_lock, flags);
1916
1418c7d8 1917 if (is_cpu_tm2_revb() ||
1918 (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
97256936 1919 while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
1920 & mask))
1921 ;
1922 } else {
1923 while (!(codec_dmcbus_read(DMC_CHAN_STS)
1924 & mask))
1925 ;
1926 }
976f3376
HZ
1927}
1928
b9164398
NQ
1929void vdec_save_input_context(struct vdec_s *vdec)
1930{
fe96802b 1931 struct vdec_input_s *input = &vdec->input;
b9164398 1932
fe96802b 1933#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
1934 vdec_profile(vdec, VDEC_PROFILE_EVENT_SAVE_INPUT);
1935#endif
1936
1937 if (input->target == VDEC_INPUT_TARGET_VLD)
1938 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1<<15);
1939
1940 if (input_stream_based(input) && (input->swap_needed)) {
1941 if (input->target == VDEC_INPUT_TARGET_VLD) {
1942 WRITE_VREG(VLD_MEM_SWAP_ADDR,
fe96802b 1943 input->swap_page_phys);
b9164398
NQ
1944 WRITE_VREG(VLD_MEM_SWAP_CTL, 3);
1945 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
1946 ;
1947 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
1948 vdec->input.stream_cookie =
1949 READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
fe96802b
NQ
1950 vdec->input.swap_rp =
1951 READ_VREG(VLD_MEM_VIFIFO_RP);
1952 vdec->input.total_rd_count =
1953 (u64)vdec->input.stream_cookie *
1954 vdec->input.size + vdec->input.swap_rp -
1955 READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL);
b9164398
NQ
1956 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1957 WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
fe96802b 1958 input->swap_page_phys);
b9164398
NQ
1959 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 3);
1960
1961 while (READ_VREG(HEVC_STREAM_SWAP_CTRL) & (1<<7))
1962 ;
1963 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
1964
1965 vdec->input.stream_cookie =
1966 READ_VREG(HEVC_SHIFT_BYTE_COUNT);
fe96802b
NQ
1967 vdec->input.swap_rp =
1968 READ_VREG(HEVC_STREAM_RD_PTR);
1969 if (((vdec->input.stream_cookie & 0x80000000) == 0) &&
1970 (vdec->input.streaming_rp & 0x80000000))
1971 vdec->input.streaming_rp += 1ULL << 32;
1972 vdec->input.streaming_rp &= 0xffffffffULL << 32;
1973 vdec->input.streaming_rp |= vdec->input.stream_cookie;
1974 vdec->input.total_rd_count = vdec->input.streaming_rp;
432add18 1975 hevc_wait_ddr();
b9164398
NQ
1976 }
1977
1978 input->swap_valid = true;
fe96802b
NQ
1979 input->swap_needed = false;
1980 /*pr_info("vdec: save context\r\n");*/
b9164398 1981
fe96802b
NQ
1982 vdec_sync_input_read(vdec);
1983
1984 if (vdec_dual(vdec)) {
1985 struct vdec_s *master = (vdec->slave) ?
1986 vdec : vdec->master;
1987 master->input.last_swap_slave = (master->slave == vdec);
1988 /* pr_info("master->input.last_swap_slave = %d\n",
1989 master->input.last_swap_slave); */
1990 }
b9164398
NQ
1991 }
1992}
1993EXPORT_SYMBOL(vdec_save_input_context);
1994
1995void vdec_clean_input(struct vdec_s *vdec)
1996{
1997 struct vdec_input_s *input = &vdec->input;
1998
1999 while (!list_empty(&input->vframe_chunk_list)) {
2000 struct vframe_chunk_s *chunk =
2001 vdec_input_next_chunk(input);
87046a60 2002 if (chunk && (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED))
b9164398
NQ
2003 vdec_input_release_chunk(input, chunk);
2004 else
2005 break;
2006 }
2007 vdec_save_input_context(vdec);
2008}
2009EXPORT_SYMBOL(vdec_clean_input);
2010
0b6a7fae 2011
2012static int vdec_input_read_restore(struct vdec_s *vdec)
2013{
2014 struct vdec_input_s *input = &vdec->input;
2015
2016 if (!vdec_stream_based(vdec))
2017 return 0;
2018
2019 if (!input->swap_valid) {
2020 if (input->target == VDEC_INPUT_TARGET_VLD) {
2021 WRITE_VREG(VLD_MEM_VIFIFO_START_PTR,
2022 input->start);
2023 WRITE_VREG(VLD_MEM_VIFIFO_END_PTR,
2024 input->start + input->size - 8);
2025 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
2026 input->start);
2027 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
2028 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
2029
2030 /* set to manual mode */
2031 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
2032 WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start);
2033 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
2034 WRITE_VREG(HEVC_STREAM_START_ADDR,
2035 input->start);
2036 WRITE_VREG(HEVC_STREAM_END_ADDR,
2037 input->start + input->size);
2038 WRITE_VREG(HEVC_STREAM_RD_PTR,
2039 input->start);
2040 }
2041 return 0;
2042 }
2043 if (input->target == VDEC_INPUT_TARGET_VLD) {
2044 /* restore read side */
2045 WRITE_VREG(VLD_MEM_SWAP_ADDR,
2046 input->swap_page_phys);
2047
2048 /*swap active*/
2049 WRITE_VREG(VLD_MEM_SWAP_CTL, 1);
2050
2051 /*wait swap busy*/
2052 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
2053 ;
2054
2055 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
2056 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
2057 /* restore read side */
2058 WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
2059 input->swap_page_phys);
2060 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1);
2061
2062 while (READ_VREG(HEVC_STREAM_SWAP_CTRL)
2063 & (1<<7))
2064 ;
2065 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
2066 }
2067
2068 return 0;
2069}
2070
2071
fe96802b 2072int vdec_sync_input(struct vdec_s *vdec)
b9164398 2073{
fe96802b
NQ
2074 struct vdec_input_s *input = &vdec->input;
2075 u32 rp = 0, wp = 0, fifo_len = 0;
2076 int size;
2077
0b6a7fae 2078 vdec_input_read_restore(vdec);
fe96802b
NQ
2079 vdec_sync_input_read(vdec);
2080 vdec_sync_input_write(vdec);
2081 if (input->target == VDEC_INPUT_TARGET_VLD) {
2082 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
2083 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
2084
2085 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
2086 rp = READ_VREG(HEVC_STREAM_RD_PTR);
2087 wp = READ_VREG(HEVC_STREAM_WR_PTR);
2088 fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
2089 >> 16) & 0x7f;
2090 }
2091 if (wp >= rp)
2092 size = wp - rp + fifo_len;
2093 else
2094 size = wp + input->size - rp + fifo_len;
2095 if (size < 0) {
2096 pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n",
2097 __func__, input->size, wp, rp, fifo_len, size);
2098 size = 0;
b9164398 2099 }
fe96802b
NQ
2100 return size;
2101
2102}
2103EXPORT_SYMBOL(vdec_sync_input);
2104
2105const char *vdec_status_str(struct vdec_s *vdec)
2106{
a03ea6d2 2107 if (vdec->status < 0)
2108 return "INVALID";
fe96802b
NQ
2109 return vdec->status < ARRAY_SIZE(vdec_status_string) ?
2110 vdec_status_string[vdec->status] : "INVALID";
b9164398
NQ
2111}
2112
2113const char *vdec_type_str(struct vdec_s *vdec)
2114{
2115 switch (vdec->type) {
2116 case VDEC_TYPE_SINGLE:
2117 return "VDEC_TYPE_SINGLE";
2118 case VDEC_TYPE_STREAM_PARSER:
2119 return "VDEC_TYPE_STREAM_PARSER";
2120 case VDEC_TYPE_FRAME_BLOCK:
2121 return "VDEC_TYPE_FRAME_BLOCK";
2122 case VDEC_TYPE_FRAME_CIRCULAR:
2123 return "VDEC_TYPE_FRAME_CIRCULAR";
2124 default:
2125 return "VDEC_TYPE_INVALID";
2126 }
2127}
2128
2129const char *vdec_device_name_str(struct vdec_s *vdec)
2130{
2131 return vdec_device_name[vdec->format * 2 + 1];
2132}
fe96802b 2133EXPORT_SYMBOL(vdec_device_name_str);
b9164398
NQ
2134
2135void walk_vdec_core_list(char *s)
2136{
2137 struct vdec_s *vdec;
2138 struct vdec_core_s *core = vdec_core;
2139 unsigned long flags;
2140
2141 pr_info("%s --->\n", s);
2142
2143 flags = vdec_core_lock(vdec_core);
2144
2145 if (list_empty(&core->connected_vdec_list)) {
2146 pr_info("connected vdec list empty\n");
2147 } else {
2148 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
2149 pr_info("\tvdec (%p), status = %s\n", vdec,
2150 vdec_status_str(vdec));
2151 }
2152 }
2153
2154 vdec_core_unlock(vdec_core, flags);
2155}
2156EXPORT_SYMBOL(walk_vdec_core_list);
2157
fe96802b
NQ
2158/* insert vdec to vdec_core for scheduling,
2159 * for dual running decoders, connect/disconnect always runs in pairs
2160 */
b9164398
NQ
2161int vdec_connect(struct vdec_s *vdec)
2162{
2163 unsigned long flags;
2164
fe96802b
NQ
2165 //trace_vdec_connect(vdec);/*DEBUG_TMP*/
2166
b9164398
NQ
2167 if (vdec->status != VDEC_STATUS_DISCONNECTED)
2168 return 0;
2169
2170 vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
2171 vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED);
2172
2173 init_completion(&vdec->inactive_done);
2174
2175 if (vdec->slave) {
2176 vdec_set_status(vdec->slave, VDEC_STATUS_CONNECTED);
2177 vdec_set_next_status(vdec->slave, VDEC_STATUS_CONNECTED);
2178
2179 init_completion(&vdec->slave->inactive_done);
2180 }
2181
2182 flags = vdec_core_lock(vdec_core);
2183
2184 list_add_tail(&vdec->list, &vdec_core->connected_vdec_list);
2185
2186 if (vdec->slave) {
2187 list_add_tail(&vdec->slave->list,
2188 &vdec_core->connected_vdec_list);
2189 }
2190
2191 vdec_core_unlock(vdec_core, flags);
2192
2193 up(&vdec_core->sem);
2194
2195 return 0;
2196}
2197EXPORT_SYMBOL(vdec_connect);
2198
2199/* remove vdec from vdec_core scheduling */
2200int vdec_disconnect(struct vdec_s *vdec)
2201{
fe96802b 2202#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
2203 vdec_profile(vdec, VDEC_PROFILE_EVENT_DISCONNECT);
2204#endif
fe96802b 2205 //trace_vdec_disconnect(vdec);/*DEBUG_TMP*/
b9164398
NQ
2206
2207 if ((vdec->status != VDEC_STATUS_CONNECTED) &&
2208 (vdec->status != VDEC_STATUS_ACTIVE)) {
2209 return 0;
2210 }
6da7a8e8 2211 mutex_lock(&vdec_mutex);
b9164398 2212 /*
e0614bf7 2213 *when a vdec is under the management of scheduler
b9164398
NQ
2214 * the status change will only be from vdec_core_thread
2215 */
2216 vdec_set_next_status(vdec, VDEC_STATUS_DISCONNECTED);
2217
2218 if (vdec->slave)
2219 vdec_set_next_status(vdec->slave, VDEC_STATUS_DISCONNECTED);
2220 else if (vdec->master)
2221 vdec_set_next_status(vdec->master, VDEC_STATUS_DISCONNECTED);
6da7a8e8 2222 mutex_unlock(&vdec_mutex);
b9164398
NQ
2223 up(&vdec_core->sem);
2224
87046a60 2225 if(!wait_for_completion_timeout(&vdec->inactive_done,
2226 msecs_to_jiffies(2000)))
2227 goto discon_timeout;
b9164398 2228
87046a60 2229 if (vdec->slave) {
2230 if(!wait_for_completion_timeout(&vdec->slave->inactive_done,
2231 msecs_to_jiffies(2000)))
2232 goto discon_timeout;
2233 } else if (vdec->master) {
2234 if(!wait_for_completion_timeout(&vdec->master->inactive_done,
2235 msecs_to_jiffies(2000)))
2236 goto discon_timeout;
2237 }
b9164398 2238
87046a60 2239 return 0;
2240discon_timeout:
fc1c16dd 2241 pr_err("%s timeout!!! status: 0x%x force it to 2\n", __func__, vdec->status);
2242 vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
b9164398
NQ
2243 return 0;
2244}
2245EXPORT_SYMBOL(vdec_disconnect);
2246
2247/* release vdec structure */
2248int vdec_destroy(struct vdec_s *vdec)
2249{
fe96802b
NQ
2250 //trace_vdec_destroy(vdec);/*DEBUG_TMP*/
2251
2252 vdec_input_release(&vdec->input);
b9164398 2253
fe96802b 2254#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
2255 vdec_profile_flush(vdec);
2256#endif
fe96802b 2257 ida_simple_remove(&vdec_core->ida, vdec->id);
cc41710a 2258 if (vdec->mvfrm)
2259 vfree(vdec->mvfrm);
b9164398
NQ
2260 vfree(vdec);
2261
6e5153ec 2262#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
2263 v4lvideo_dec_count_decrease();
2264#endif
b9164398
NQ
2265 atomic_dec(&vdec_core->vdec_nr);
2266
2267 return 0;
2268}
2269EXPORT_SYMBOL(vdec_destroy);
2270
558b13f3 2271static bool is_tunnel_pipeline(u32 pl)
2272{
2273 return ((pl & BIT(FRAME_BASE_PATH_DTV_TUNNEL_MODE)) ||
2274 (pl & BIT(FRAME_BASE_PATH_AMLVIDEO_AMVIDEO))) ?
2275 true : false;
2276}
2277
2278static bool is_res_locked(u32 pre, u32 cur)
2279{
2280 return is_tunnel_pipeline(pre) ?
2281 (is_tunnel_pipeline(cur) ? true : false) : false;
2282}
2283
2284int vdec_resource_checking(struct vdec_s *vdec)
2285{
2286 /*
2287 * If it is the single instance that the pipeline of DTV used,
2288 * then have to check that the resources which is belong tunnel
2289 * pipeline these are being released.
2290 */
2291 ulong expires = jiffies + msecs_to_jiffies(2000);
2292
2293 while (is_res_locked(vdec_core->vdec_resouce_status,
2294 BIT(vdec->frame_base_video_path))) {
2295 if (time_after(jiffies, expires)) {
2296 pr_err("wait vdec resource timeout.\n");
2297 return -EBUSY;
2298 }
2299 schedule();
2300 }
2301
2302 return 0;
2303}
2304EXPORT_SYMBOL(vdec_resource_checking);
2305
b9164398 2306/*
e0614bf7 2307 *register vdec_device
b9164398
NQ
2308 * create output, vfm or create ionvideo output
2309 */
2310s32 vdec_init(struct vdec_s *vdec, int is_4k)
2311{
2312 int r = 0;
2313 struct vdec_s *p = vdec;
b9164398 2314 const char *dev_name;
fe96802b 2315 int id = PLATFORM_DEVID_AUTO;/*if have used my self*/
b9164398 2316
558b13f3 2317 if (is_res_locked(vdec_core->vdec_resouce_status,
2318 BIT(vdec->frame_base_video_path)))
2319 return -EBUSY;
2320
cc41710a 2321 //pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
b9164398
NQ
2322 dev_name = get_dev_name(vdec_single(vdec), vdec->format);
2323
2324 if (dev_name == NULL)
2325 return -ENODEV;
2326
bba22b6d 2327 pr_info("vdec_init, dev_name:%s, vdec_type=%s id = %d\n",
2328 dev_name, vdec_type_str(vdec), vdec->id);
b9164398
NQ
2329
2330 /*
e0614bf7 2331 *todo: VFM patch control should be configurable,
b9164398
NQ
2332 * for now all stream based input uses default VFM path.
2333 */
1418c7d8 2334 if (!is_support_no_parser()) {
d631e9c2
HZ
2335 if (vdec_stream_based(vdec) && !vdec_dual(vdec)) {
2336 if (vdec_core->vfm_vdec == NULL) {
2337 pr_debug("vdec_init set vfm decoder %p\n", vdec);
2338 vdec_core->vfm_vdec = vdec;
2339 } else {
2340 pr_info("vdec_init vfm path busy.\n");
2341 return -EBUSY;
2342 }
b9164398
NQ
2343 }
2344 }
2345
b9164398
NQ
2346 mutex_lock(&vdec_mutex);
2347 inited_vcodec_num++;
2348 mutex_unlock(&vdec_mutex);
2349
2350 vdec_input_set_type(&vdec->input, vdec->type,
2351 (vdec->format == VFORMAT_HEVC ||
a6c89e96 2352 vdec->format == VFORMAT_AVS2 ||
97256936 2353 vdec->format == VFORMAT_VP9 ||
2354 vdec->format == VFORMAT_AV1
2355 ) ?
b9164398
NQ
2356 VDEC_INPUT_TARGET_HEVC :
2357 VDEC_INPUT_TARGET_VLD);
17a06af5 2358 if (vdec_single(vdec) || (vdec_get_debug_flags() & 0x2))
144f5ee8 2359 vdec_enable_DMC(vdec);
b9164398
NQ
2360 p->cma_dev = vdec_core->cma_dev;
2361 p->get_canvas = get_canvas;
05afa03d
PY
2362 p->get_canvas_ex = get_canvas_ex;
2363 p->free_canvas_ex = free_canvas_ex;
97fe3d16 2364 p->vdec_fps_detec = vdec_fps_detec;
b9164398 2365 /* todo */
d631e9c2
HZ
2366 if (!vdec_dual(vdec)) {
2367 p->use_vfm_path =
1418c7d8 2368 (is_support_no_parser()) ?
d631e9c2
HZ
2369 vdec_single(vdec) :
2370 vdec_stream_based(vdec);
2371 }
2372
17a06af5
RZ
2373 if (debugflags & 0x4)
2374 p->use_vfm_path = 1;
b9164398 2375 /* vdec_dev_reg.flag = 0; */
fe96802b
NQ
2376 if (vdec->id >= 0)
2377 id = vdec->id;
05afa03d
PY
2378 p->parallel_dec = parallel_decode;
2379 vdec_core->parallel_dec = parallel_decode;
8458676f 2380 vdec->canvas_mode = CANVAS_BLKMODE_32X32;
2381#ifdef FRAME_CHECK
8458676f 2382 vdec_frame_check_init(vdec);
2383#endif
d631e9c2 2384 /* stream buffer init. */
527e712a 2385 if (vdec->vbuf.ops && !vdec->master) {
d631e9c2
HZ
2386 r = vdec->vbuf.ops->init(&vdec->vbuf, vdec);
2387 if (r) {
2388 pr_err("%s stream buffer init err (%d)\n", dev_name, r);
2389
2390 mutex_lock(&vdec_mutex);
2391 inited_vcodec_num--;
2392 mutex_unlock(&vdec_mutex);
2393
2394 goto error;
2395 }
527e712a
NQ
2396
2397 if (vdec->slave) {
2398 memcpy(&vdec->slave->vbuf, &vdec->vbuf,
2399 sizeof(vdec->vbuf));
2400 }
d631e9c2
HZ
2401 }
2402
fe96802b 2403 p->dev = platform_device_register_data(
b9164398
NQ
2404 &vdec_core->vdec_core_platform_device->dev,
2405 dev_name,
fe96802b 2406 id,
b9164398
NQ
2407 &p, sizeof(struct vdec_s *));
2408
2409 if (IS_ERR(p->dev)) {
2410 r = PTR_ERR(p->dev);
2411 pr_err("vdec: Decoder device %s register failed (%d)\n",
2412 dev_name, r);
2413
2414 mutex_lock(&vdec_mutex);
2415 inited_vcodec_num--;
2416 mutex_unlock(&vdec_mutex);
2417
fe96802b
NQ
2418 goto error;
2419 } else if (!p->dev->dev.driver) {
2420 pr_info("vdec: Decoder device %s driver probe failed.\n",
2421 dev_name);
2422 r = -ENODEV;
2423
b9164398
NQ
2424 goto error;
2425 }
2426
2427 if ((p->type == VDEC_TYPE_FRAME_BLOCK) && (p->run == NULL)) {
2428 r = -ENODEV;
2429 pr_err("vdec: Decoder device not handled (%s)\n", dev_name);
2430
2431 mutex_lock(&vdec_mutex);
2432 inited_vcodec_num--;
2433 mutex_unlock(&vdec_mutex);
2434
2435 goto error;
2436 }
2437
2438 if (p->use_vfm_path) {
2439 vdec->vf_receiver_inst = -1;
fe96802b 2440 vdec->vfm_map_id[0] = 0;
b9164398
NQ
2441 } else if (!vdec_dual(vdec)) {
2442 /* create IONVIDEO instance and connect decoder's
2443 * vf_provider interface to it
2444 */
1418c7d8 2445 if (!is_support_no_parser()) {
d631e9c2
HZ
2446 if (p->type != VDEC_TYPE_FRAME_BLOCK) {
2447 r = -ENODEV;
2448 pr_err("vdec: Incorrect decoder type\n");
b9164398 2449
d631e9c2
HZ
2450 mutex_lock(&vdec_mutex);
2451 inited_vcodec_num--;
2452 mutex_unlock(&vdec_mutex);
b9164398 2453
d631e9c2
HZ
2454 goto error;
2455 }
b9164398 2456 }
4373e91a 2457
2458 if (strncmp("disable", vfm_path, strlen("disable"))) {
2459 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2460 "%s %s", vdec->vf_provider_name, vfm_path);
2461 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2462 "vdec-map-%d", vdec->id);
2463 } else if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) {
b9164398 2464#if 1
ff4c2158
NQ
2465 r = ionvideo_assign_map(&vdec->vf_receiver_name,
2466 &vdec->vf_receiver_inst);
b9164398 2467#else
2b796d78
ZZ
2468 /*
2469 * temporarily just use decoder instance ID as iondriver ID
2470 * to solve OMX iondriver instance number check time sequence
2471 * only the limitation is we can NOT mix different video
2472 * decoders since same ID will be used for different decoder
2473 * formats.
2474 */
2475 vdec->vf_receiver_inst = p->dev->id;
2476 r = ionvideo_assign_map(&vdec->vf_receiver_name,
2477 &vdec->vf_receiver_inst);
b9164398 2478#endif
2b796d78
ZZ
2479 if (r < 0) {
2480 pr_err("IonVideo frame receiver allocation failed.\n");
b9164398 2481
2b796d78
ZZ
2482 mutex_lock(&vdec_mutex);
2483 inited_vcodec_num--;
2484 mutex_unlock(&vdec_mutex);
b9164398 2485
2b796d78
ZZ
2486 goto error;
2487 }
b9164398 2488
fe96802b
NQ
2489 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2490 "%s %s", vdec->vf_provider_name,
2491 vdec->vf_receiver_name);
2492 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2493 "vdec-map-%d", vdec->id);
b9164398
NQ
2494 } else if (p->frame_base_video_path ==
2495 FRAME_BASE_PATH_AMLVIDEO_AMVIDEO) {
2b796d78
ZZ
2496 if (vdec_secure(vdec)) {
2497 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2498 "%s %s", vdec->vf_provider_name,
2499 "amlvideo amvideo");
2500 } else {
b39d60ee 2501 if (debug_vdetect)
2502 snprintf(vdec->vfm_map_chain,
2503 VDEC_MAP_NAME_SIZE,
2504 "%s vdetect.0 %s",
2505 vdec->vf_provider_name,
2506 "amlvideo ppmgr deinterlace amvideo");
2507 else
2508 snprintf(vdec->vfm_map_chain,
2509 VDEC_MAP_NAME_SIZE, "%s %s",
2510 vdec->vf_provider_name,
2511 "amlvideo ppmgr deinterlace amvideo");
2b796d78 2512 }
b9164398 2513 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
fe96802b 2514 "vdec-map-%d", vdec->id);
b9164398
NQ
2515 } else if (p->frame_base_video_path ==
2516 FRAME_BASE_PATH_AMLVIDEO1_AMVIDEO2) {
2517 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2518 "%s %s", vdec->vf_provider_name,
dbba62e2 2519 "aml_video.1 videosync.0 videopip");
b9164398 2520 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
fe96802b 2521 "vdec-map-%d", vdec->id);
2cd6815e 2522 } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_OSD) {
6b7ee58f 2523 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
65a98643
NQ
2524 "%s %s", vdec->vf_provider_name,
2525 vdec->vf_receiver_name);
6b7ee58f
NQ
2526 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2527 "vdec-map-%d", vdec->id);
2b796d78
ZZ
2528 } else if (p->frame_base_video_path == FRAME_BASE_PATH_TUNNEL_MODE) {
2529 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2530 "%s %s", vdec->vf_provider_name,
2531 "amvideo");
e8335f32 2532 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2533 "vdec-map-%d", vdec->id);
8875ed5d 2534 } else if (p->frame_base_video_path == FRAME_BASE_PATH_PIP_TUNNEL_MODE) {
2535 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2536 "%s %s", vdec->vf_provider_name,
2537 "videosync.0 videopip");
2538 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2539 "vdec-map-%d", vdec->id);
2cd6815e
NQ
2540 } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) {
2541 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2542 "%s %s %s", vdec->vf_provider_name,
2543 vdec->vf_receiver_name, "amvideo");
8ee39d2d 2544 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2545 "vdec-map-%d", vdec->id);
e8335f32 2546 } else if (p->frame_base_video_path ==
2547 FRAME_BASE_PATH_DI_V4LVIDEO) {
febdc420 2548#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
e8335f32 2549 r = v4lvideo_assign_map(&vdec->vf_receiver_name,
2550 &vdec->vf_receiver_inst);
febdc420
NQ
2551#else
2552 r = -1;
2553#endif
2554 if (r < 0) {
e8335f32 2555 pr_err("V4lVideo frame receiver allocation failed.\n");
2556 mutex_lock(&vdec_mutex);
2557 inited_vcodec_num--;
2558 mutex_unlock(&vdec_mutex);
2559 goto error;
2560 }
0ba13da1 2561 if (!v4lvideo_add_di)
e8335f32 2562 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2563 "%s %s", vdec->vf_provider_name,
2564 vdec->vf_receiver_name);
2565 else {
e8abb93b 2566 if ((vdec->vf_receiver_inst == 0)
2567 && (max_di_instance > 0))
2568 if (max_di_instance == 1)
2569 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2570 "%s %s %s", vdec->vf_provider_name,
2571 "deinterlace",
2572 vdec->vf_receiver_name);
2573 else
2574 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2575 "%s %s %s", vdec->vf_provider_name,
2576 "dimulti.1",
2577 vdec->vf_receiver_name);
0c40b29f 2578 else if ((vdec->vf_receiver_inst <
2579 max_di_instance) &&
2580 (vdec->vf_receiver_inst == 1))
2581 snprintf(vdec->vfm_map_chain,
2582 VDEC_MAP_NAME_SIZE,
2583 "%s %s %s",
2584 vdec->vf_provider_name,
2585 "deinterlace",
2586 vdec->vf_receiver_name);
2587 else if (vdec->vf_receiver_inst <
2588 max_di_instance)
2589 snprintf(vdec->vfm_map_chain,
2590 VDEC_MAP_NAME_SIZE,
2591 "%s %s%d %s",
2592 vdec->vf_provider_name,
2593 "dimulti.",
2594 vdec->vf_receiver_inst,
2595 vdec->vf_receiver_name);
e8335f32 2596 else
2597 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2598 "%s %s", vdec->vf_provider_name,
2599 vdec->vf_receiver_name);
2600 }
2601 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2602 "vdec-map-%d", vdec->id);
475e80ac 2603 } else if (p->frame_base_video_path ==
2604 FRAME_BASE_PATH_V4LVIDEO) {
2605#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
2606 r = v4lvideo_assign_map(&vdec->vf_receiver_name,
2607 &vdec->vf_receiver_inst);
2608#else
2609 r = -1;
2610#endif
2611 if (r < 0) {
2612 pr_err("V4lVideo frame receiver allocation failed.\n");
2613 mutex_lock(&vdec_mutex);
2614 inited_vcodec_num--;
2615 mutex_unlock(&vdec_mutex);
2616 goto error;
2617 }
2618 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2619 "%s %s", vdec->vf_provider_name,
2620 vdec->vf_receiver_name);
2621 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2622 "vdec-map-%d", vdec->id);
558b13f3 2623 } else if (p->frame_base_video_path ==
2624 FRAME_BASE_PATH_DTV_TUNNEL_MODE) {
36114cbd 2625 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2626 "%s deinterlace %s", vdec->vf_provider_name,
2627 "amvideo");
2628 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2629 "vdec-map-%d", vdec->id);
51c859b2
NQ
2630 } else if (p->frame_base_video_path ==
2631 FRAME_BASE_PATH_AMLVIDEO_FENCE) {
2632 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
2633 "%s %s", vdec->vf_provider_name,
2634 "amlvideo amvideo");
2635 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
2636 "vdec-map-%d", vdec->id);
b9164398
NQ
2637 }
2638
2639 if (vfm_map_add(vdec->vfm_map_id,
2640 vdec->vfm_map_chain) < 0) {
2641 r = -ENOMEM;
2642 pr_err("Decoder pipeline map creation failed %s.\n",
2643 vdec->vfm_map_id);
2644 vdec->vfm_map_id[0] = 0;
2645
2646 mutex_lock(&vdec_mutex);
2647 inited_vcodec_num--;
2648 mutex_unlock(&vdec_mutex);
2649
2650 goto error;
2651 }
2652
5b851ff9 2653 pr_debug("vfm map %s created\n", vdec->vfm_map_id);
b9164398
NQ
2654
2655 /*
e0614bf7 2656 *assume IONVIDEO driver already have a few vframe_receiver
b9164398
NQ
2657 * registered.
2658 * 1. Call iondriver function to allocate a IONVIDEO path and
2659 * provide receiver's name and receiver op.
2660 * 2. Get decoder driver's provider name from driver instance
2661 * 3. vfm_map_add(name, "<decoder provider name>
2662 * <iondriver receiver name>"), e.g.
2663 * vfm_map_add("vdec_ion_map_0", "mpeg4_0 iondriver_1");
2664 * 4. vf_reg_provider and vf_reg_receiver
2665 * Note: the decoder provider's op uses vdec as op_arg
2666 * the iondriver receiver's op uses iondev device as
2667 * op_arg
2668 */
2669
2670 }
2671
2672 if (!vdec_single(vdec)) {
2673 vf_reg_provider(&p->vframe_provider);
2674
2675 vf_notify_receiver(p->vf_provider_name,
2676 VFRAME_EVENT_PROVIDER_START,
2677 vdec);
fe96802b
NQ
2678
2679 if (vdec_core->hint_fr_vdec == NULL)
2680 vdec_core->hint_fr_vdec = vdec;
2681
2682 if (vdec_core->hint_fr_vdec == vdec) {
2683 if (p->sys_info->rate != 0) {
6d2907a6 2684 if (!vdec->is_reset) {
d481db31
NQ
2685 vf_notify_receiver(p->vf_provider_name,
2686 VFRAME_EVENT_PROVIDER_FR_HINT,
2687 (void *)
2688 ((unsigned long)
2689 p->sys_info->rate));
6d2907a6
LC
2690 vdec->fr_hint_state = VDEC_HINTED;
2691 }
fe96802b
NQ
2692 } else {
2693 vdec->fr_hint_state = VDEC_NEED_HINT;
2694 }
2695 }
b9164398
NQ
2696 }
2697
28e318df 2698 p->dolby_meta_with_el = 0;
97256936 2699 pr_debug("vdec_init, vf_provider_name = %s, b %d\n",
2700 p->vf_provider_name, is_cpu_tm2_revb());
558b13f3 2701
2702 mutex_lock(&vdec_mutex);
2703 vdec_core->vdec_resouce_status |= BIT(p->frame_base_video_path);
2704 mutex_unlock(&vdec_mutex);
2705
fe96802b
NQ
2706 vdec_input_prepare_bufs(/*prepared buffer for fast playing.*/
2707 &vdec->input,
2708 vdec->sys_info->width,
2709 vdec->sys_info->height);
b9164398
NQ
2710 /* vdec is now ready to be active */
2711 vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
bba22b6d 2712
2713#ifdef VDEC_FCC_SUPPORT
2714 init_waitqueue_head(&vdec->jump_back_wq);
2715 mutex_init(&vdec->jump_back_mutex);
2716 vdec->fcc_mode = FCC_BUTT;
2717 vdec->fcc_status = STATUS_BUTT;
2718#endif
b9164398
NQ
2719 return 0;
2720
2721error:
2722 return r;
2723}
2724EXPORT_SYMBOL(vdec_init);
2725
e0364dc0 2726/*
2727 *Remove the vdec after timeout happens both in vdec_disconnect
2728 *and platform_device_unregister. Then after, we can release the vdec.
2729 */
2730static void vdec_connect_list_force_clear(struct vdec_core_s *core, struct vdec_s *v_ref)
2731{
2732 struct vdec_s *vdec, *tmp;
2733 unsigned long flags;
2734
2735 flags = vdec_core_lock(core);
2736
2737 list_for_each_entry_safe(vdec, tmp,
2738 &core->connected_vdec_list, list) {
2739 if ((vdec->status == VDEC_STATUS_DISCONNECTED) &&
2740 (vdec == v_ref)) {
2741 pr_err("%s, vdec = %p, active vdec = %p\n",
2742 __func__, vdec, core->active_vdec);
386310a4
PY
2743 if (v_ref->active_mask)
2744 core->sched_mask &= ~v_ref->active_mask;
e0364dc0 2745 if (core->active_vdec == v_ref)
2746 core->active_vdec = NULL;
386310a4
PY
2747 if (core->active_hevc == v_ref)
2748 core->active_hevc = NULL;
e0364dc0 2749 if (core->last_vdec == v_ref)
2750 core->last_vdec = NULL;
2751 list_del(&vdec->list);
2752 }
2753 }
2754
2755 vdec_core_unlock(core, flags);
2756}
2757
fe96802b
NQ
2758/* vdec_create/init/release/destroy are applied to both dual running decoders
2759 */
b9164398
NQ
2760void vdec_release(struct vdec_s *vdec)
2761{
721cd261 2762 u32 wcount = 0;
2763
fe96802b 2764 //trace_vdec_release(vdec);/*DEBUG_TMP*/
a6c89e96
NQ
2765#ifdef VDEC_DEBUG_SUPPORT
2766 if (step_mode) {
2767 pr_info("VDEC_DEBUG: in step_mode, wait release\n");
2768 while (step_mode)
2769 udelay(10);
2770 pr_info("VDEC_DEBUG: step_mode is clear\n");
2771 }
2772#endif
833bb93d 2773 /* When release, userspace systemctl need this duration 0 event */
2774 vframe_rate_uevent(0);
b9164398
NQ
2775 vdec_disconnect(vdec);
2776
fe96802b
NQ
2777 if (vdec->vframe_provider.name) {
2778 if (!vdec_single(vdec)) {
2779 if (vdec_core->hint_fr_vdec == vdec
6d2907a6 2780 && vdec->fr_hint_state == VDEC_HINTED)
fe96802b
NQ
2781 vf_notify_receiver(
2782 vdec->vf_provider_name,
2783 VFRAME_EVENT_PROVIDER_FR_END_HINT,
2784 NULL);
2785 vdec->fr_hint_state = VDEC_NO_NEED_HINT;
2786 }
b9164398 2787 vf_unreg_provider(&vdec->vframe_provider);
fe96802b 2788 }
b9164398
NQ
2789
2790 if (vdec_core->vfm_vdec == vdec)
2791 vdec_core->vfm_vdec = NULL;
2792
fe96802b
NQ
2793 if (vdec_core->hint_fr_vdec == vdec)
2794 vdec_core->hint_fr_vdec = NULL;
2795
b9164398
NQ
2796 if (vdec->vf_receiver_inst >= 0) {
2797 if (vdec->vfm_map_id[0]) {
2798 vfm_map_remove(vdec->vfm_map_id);
2799 vdec->vfm_map_id[0] = 0;
2800 }
b9164398
NQ
2801 }
2802
721cd261 2803 while (vdec->irq_cnt > vdec->irq_thread_cnt) {
2804 if ((wcount & 0x1f) == 0)
2805 pr_debug("%s vdec[%lx]: %lld > %lld, loop %u times\n",__func__, (unsigned long)vdec,
2806 vdec->irq_cnt,vdec->irq_thread_cnt, wcount);
2807 /*
2808 * Wait at most 2000 ms.
2809 * In suspend scenario, the system may disable thread_fn,
2810 * thus can NOT always waiting the thread_fn happen
2811 */
2812 if (++wcount > 1000)
2813 break;
2814 usleep_range(1000, 2000);
2815 }
5f3fbfb7 2816
8458676f 2817#ifdef FRAME_CHECK
2818 vdec_frame_check_exit(vdec);
8458676f 2819#endif
97fe3d16 2820 vdec_fps_clear(vdec->id);
144f5ee8
HZ
2821 if (atomic_read(&vdec_core->vdec_nr) == 1)
2822 vdec_disable_DMC(vdec);
b9164398 2823 platform_device_unregister(vdec->dev);
e0364dc0 2824 /*Check if the vdec still in connected list, if yes, delete it*/
2825 vdec_connect_list_force_clear(vdec_core, vdec);
d631e9c2 2826
527e712a 2827 if (vdec->vbuf.ops && !vdec->master)
d631e9c2
HZ
2828 vdec->vbuf.ops->release(&vdec->vbuf);
2829
bba22b6d 2830 pr_debug("vdec_release instance %p, total %d id = %d\n", vdec,
2831 atomic_read(&vdec_core->vdec_nr), vdec->id);
558b13f3 2832
2833 mutex_lock(&vdec_mutex);
2834 vdec_core->vdec_resouce_status &= ~BIT(vdec->frame_base_video_path);
2835 mutex_unlock(&vdec_mutex);
2836
b9164398
NQ
2837 vdec_destroy(vdec);
2838
2839 mutex_lock(&vdec_mutex);
2840 inited_vcodec_num--;
2841 mutex_unlock(&vdec_mutex);
2842}
2843EXPORT_SYMBOL(vdec_release);
2844
a6c89e96
NQ
2845/* For dual running decoders, vdec_reset is only called with master vdec.
2846 */
b9164398
NQ
2847int vdec_reset(struct vdec_s *vdec)
2848{
a6c89e96
NQ
2849 //trace_vdec_reset(vdec); /*DEBUG_TMP*/
2850
b9164398
NQ
2851 vdec_disconnect(vdec);
2852
2853 if (vdec->vframe_provider.name)
2854 vf_unreg_provider(&vdec->vframe_provider);
2855
2856 if ((vdec->slave) && (vdec->slave->vframe_provider.name))
2857 vf_unreg_provider(&vdec->slave->vframe_provider);
2858
2859 if (vdec->reset) {
2860 vdec->reset(vdec);
2861 if (vdec->slave)
2862 vdec->slave->reset(vdec->slave);
2863 }
158de7c4 2864 vdec->mc_loaded = 0;/*clear for reload firmware*/
b9164398
NQ
2865 vdec_input_release(&vdec->input);
2866
6b7ee58f
NQ
2867 vdec_input_init(&vdec->input, vdec);
2868
2869 vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width,
2870 vdec->sys_info->height);
2871
b9164398
NQ
2872 vf_reg_provider(&vdec->vframe_provider);
2873 vf_notify_receiver(vdec->vf_provider_name,
2874 VFRAME_EVENT_PROVIDER_START, vdec);
2875
2876 if (vdec->slave) {
2877 vf_reg_provider(&vdec->slave->vframe_provider);
2878 vf_notify_receiver(vdec->slave->vf_provider_name,
2879 VFRAME_EVENT_PROVIDER_START, vdec->slave);
158de7c4 2880 vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
b9164398
NQ
2881 }
2882
2883 vdec_connect(vdec);
2884
2885 return 0;
2886}
2887EXPORT_SYMBOL(vdec_reset);
2888
6cfc5cce
YP
2889int vdec_v4l2_reset(struct vdec_s *vdec, int flag)
2890{
2891 //trace_vdec_reset(vdec); /*DEBUG_TMP*/
2892 pr_debug("vdec_v4l2_reset %d\n", flag);
2893 vdec_disconnect(vdec);
2894 if (flag != 2) {
2895 if (vdec->vframe_provider.name)
2896 vf_unreg_provider(&vdec->vframe_provider);
2897
2898 if ((vdec->slave) && (vdec->slave->vframe_provider.name))
2899 vf_unreg_provider(&vdec->slave->vframe_provider);
2900
2901 if (vdec->reset) {
2902 vdec->reset(vdec);
2903 if (vdec->slave)
2904 vdec->slave->reset(vdec->slave);
2905 }
2906 vdec->mc_loaded = 0;/*clear for reload firmware*/
2907
2908 vdec_input_release(&vdec->input);
2909
2910 vdec_input_init(&vdec->input, vdec);
2911
2912 vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width,
2913 vdec->sys_info->height);
2914
2915 vf_reg_provider(&vdec->vframe_provider);
2916 vf_notify_receiver(vdec->vf_provider_name,
2917 VFRAME_EVENT_PROVIDER_START, vdec);
2918
2919 if (vdec->slave) {
2920 vf_reg_provider(&vdec->slave->vframe_provider);
2921 vf_notify_receiver(vdec->slave->vf_provider_name,
2922 VFRAME_EVENT_PROVIDER_START, vdec->slave);
2923 vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
2924 }
2925 } else {
2926 if (vdec->reset) {
2927 vdec->reset(vdec);
2928 if (vdec->slave)
2929 vdec->slave->reset(vdec->slave);
2930 }
2931 }
2932
2933 vdec_connect(vdec);
2934
b9ff7233
NQ
2935 vdec_frame_check_init(vdec);
2936
6cfc5cce
YP
2937 return 0;
2938}
2939EXPORT_SYMBOL(vdec_v4l2_reset);
2940
2941
fe96802b
NQ
2942void vdec_free_cmabuf(void)
2943{
2944 mutex_lock(&vdec_mutex);
2945
a35da9f0 2946 /*if (inited_vcodec_num > 0) {
fe96802b
NQ
2947 mutex_unlock(&vdec_mutex);
2948 return;
a35da9f0 2949 }*/
fe96802b
NQ
2950 mutex_unlock(&vdec_mutex);
2951}
2952
665a4a8e 2953void vdec_core_request(struct vdec_s *vdec, unsigned long mask)
b9164398 2954{
a6c89e96 2955 vdec->core_mask |= mask;
b9164398 2956
a6c89e96
NQ
2957 if (vdec->slave)
2958 vdec->slave->core_mask |= mask;
05afa03d
PY
2959 if (vdec_core->parallel_dec == 1) {
2960 if (mask & CORE_MASK_COMBINE)
2961 vdec_core->vdec_combine_flag++;
2962 }
a6c89e96 2963
a6c89e96
NQ
2964}
2965EXPORT_SYMBOL(vdec_core_request);
2966
2967int vdec_core_release(struct vdec_s *vdec, unsigned long mask)
2968{
2969 vdec->core_mask &= ~mask;
2970
2971 if (vdec->slave)
2972 vdec->slave->core_mask &= ~mask;
05afa03d
PY
2973 if (vdec_core->parallel_dec == 1) {
2974 if (mask & CORE_MASK_COMBINE)
2975 vdec_core->vdec_combine_flag--;
2976 }
a6c89e96
NQ
2977 return 0;
2978}
2979EXPORT_SYMBOL(vdec_core_release);
2980
a35da9f0 2981bool vdec_core_with_input(unsigned long mask)
a6c89e96
NQ
2982{
2983 enum vdec_type_e type;
2984
2985 for (type = VDEC_1; type < VDEC_MAX; type++) {
2986 if ((mask & (1 << type)) && cores_with_input[type])
2987 return true;
b9164398
NQ
2988 }
2989
a6c89e96
NQ
2990 return false;
2991}
2992
2993void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask)
2994{
2995 unsigned long i;
2996 unsigned long t = mask;
6da7a8e8 2997 mutex_lock(&vdec_mutex);
a6c89e96
NQ
2998 while (t) {
2999 i = __ffs(t);
3000 clear_bit(i, &vdec->active_mask);
3001 t &= ~(1 << i);
3002 }
3003
3004 if (vdec->active_mask == 0)
3005 vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
6da7a8e8
PY
3006
3007 mutex_unlock(&vdec_mutex);
a6c89e96
NQ
3008}
3009EXPORT_SYMBOL(vdec_core_finish_run);
3010/*
3011 * find what core resources are available for vdec
3012 */
3013static unsigned long vdec_schedule_mask(struct vdec_s *vdec,
3014 unsigned long active_mask)
3015{
3016 unsigned long mask = vdec->core_mask &
3017 ~CORE_MASK_COMBINE;
3018
3019 if (vdec->core_mask & CORE_MASK_COMBINE) {
3020 /* combined cores must be granted together */
3021 if ((mask & ~active_mask) == mask)
3022 return mask;
3023 else
3024 return 0;
3025 } else
3026 return mask & ~vdec->sched_mask & ~active_mask;
b9164398
NQ
3027}
3028
3029/*
e0614bf7 3030 *Decoder callback
b9164398
NQ
3031 * Each decoder instance uses this callback to notify status change, e.g. when
3032 * decoder finished using HW resource.
3033 * a sample callback from decoder's driver is following:
3034 *
3035 * if (hw->vdec_cb) {
3036 * vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED);
3037 * hw->vdec_cb(vdec, hw->vdec_cb_arg);
3038 * }
3039 */
3040static void vdec_callback(struct vdec_s *vdec, void *data)
3041{
3042 struct vdec_core_s *core = (struct vdec_core_s *)data;
3043
fe96802b 3044#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
3045 vdec_profile(vdec, VDEC_PROFILE_EVENT_CB);
3046#endif
3047
3048 up(&core->sem);
3049}
3050
3051static irqreturn_t vdec_isr(int irq, void *dev_id)
3052{
3053 struct vdec_isr_context_s *c =
3054 (struct vdec_isr_context_s *)dev_id;
05afa03d 3055 struct vdec_s *vdec = vdec_core->last_vdec;
5f3fbfb7 3056 irqreturn_t ret = IRQ_HANDLED;
05afa03d
PY
3057
3058 if (vdec_core->parallel_dec == 1) {
3059 if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq)
3060 vdec = vdec_core->active_hevc;
3061 else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq)
3062 vdec = vdec_core->active_vdec;
3063 else
3064 vdec = NULL;
3065 }
3066
5f3fbfb7
HZ
3067 if (c->dev_isr) {
3068 ret = c->dev_isr(irq, c->dev_id);
3069 goto isr_done;
3070 }
b9164398 3071
a6c89e96
NQ
3072 if ((c != &vdec_core->isr_context[VDEC_IRQ_0]) &&
3073 (c != &vdec_core->isr_context[VDEC_IRQ_1]) &&
3074 (c != &vdec_core->isr_context[VDEC_IRQ_HEVC_BACK])) {
b9164398
NQ
3075#if 0
3076 pr_warn("vdec interrupt w/o a valid receiver\n");
3077#endif
5f3fbfb7 3078 goto isr_done;
b9164398
NQ
3079 }
3080
3081 if (!vdec) {
3082#if 0
3083 pr_warn("vdec interrupt w/o an active instance running. core = %p\n",
3084 core);
3085#endif
5f3fbfb7 3086 goto isr_done;
b9164398
NQ
3087 }
3088
3089 if (!vdec->irq_handler) {
3090#if 0
3091 pr_warn("vdec instance has no irq handle.\n");
3092#endif
5f3fbfb7 3093 goto isr_done;
b9164398
NQ
3094 }
3095
5f3fbfb7
HZ
3096 ret = vdec->irq_handler(vdec, c->index);
3097isr_done:
51b7cb07 3098 if (vdec && ret == IRQ_WAKE_THREAD)
3099 vdec->irq_cnt++;
3100
5f3fbfb7 3101 return ret;
b9164398
NQ
3102}
3103
3104static irqreturn_t vdec_thread_isr(int irq, void *dev_id)
3105{
3106 struct vdec_isr_context_s *c =
3107 (struct vdec_isr_context_s *)dev_id;
05afa03d 3108 struct vdec_s *vdec = vdec_core->last_vdec;
5f3fbfb7 3109 irqreturn_t ret = IRQ_HANDLED;
05afa03d
PY
3110
3111 if (vdec_core->parallel_dec == 1) {
3112 if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq)
3113 vdec = vdec_core->active_hevc;
3114 else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq)
3115 vdec = vdec_core->active_vdec;
3116 else
3117 vdec = NULL;
3118 }
3119
5f3fbfb7
HZ
3120 if (c->dev_threaded_isr) {
3121 ret = c->dev_threaded_isr(irq, c->dev_id);
3122 goto thread_isr_done;
3123 }
b9164398 3124 if (!vdec)
5f3fbfb7 3125 goto thread_isr_done;
b9164398
NQ
3126
3127 if (!vdec->threaded_irq_handler)
5f3fbfb7
HZ
3128 goto thread_isr_done;
3129 ret = vdec->threaded_irq_handler(vdec, c->index);
3130thread_isr_done:
3131 if (vdec)
51b7cb07 3132 vdec->irq_thread_cnt++;
5f3fbfb7 3133 return ret;
b9164398
NQ
3134}
3135
a6c89e96 3136unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
b9164398 3137{
a6c89e96 3138 unsigned long ready_mask;
fe96802b 3139 struct vdec_input_s *input = &vdec->input;
51b7cb07 3140
3141 /* Wait the matching irq_thread finished */
721cd261 3142 if (vdec->irq_cnt > vdec->irq_thread_cnt) {
3143 pr_debug("%s vdec[%lx]: %lld > %lld\n",__func__, (unsigned long)vdec,
3144 vdec->irq_cnt,vdec->irq_thread_cnt);
51b7cb07 3145 return false;
721cd261 3146 }
51b7cb07 3147
a6c89e96
NQ
3148 if ((vdec->status != VDEC_STATUS_CONNECTED) &&
3149 (vdec->status != VDEC_STATUS_ACTIVE))
b9164398
NQ
3150 return false;
3151
3152 if (!vdec->run_ready)
3153 return false;
3154
d5c1c0ff 3155 /* when crc32 error, block at error frame */
3156 if (vdec->vfc.err_crc_block)
3157 return false;
3158
b9164398
NQ
3159 if ((vdec->slave || vdec->master) &&
3160 (vdec->sched == 0))
3161 return false;
a6c89e96
NQ
3162#ifdef VDEC_DEBUG_SUPPORT
3163 inc_profi_count(mask, vdec->check_count);
3164#endif
3165 if (vdec_core_with_input(mask)) {
6cfc5cce 3166
a6c89e96
NQ
3167 /* check frame based input underrun */
3168 if (input && !input->eos && input_frame_based(input)
3169 && (!vdec_input_next_chunk(input))) {
3170#ifdef VDEC_DEBUG_SUPPORT
3171 inc_profi_count(mask, vdec->input_underrun_count);
3172#endif
fe96802b 3173 return false;
a6c89e96
NQ
3174 }
3175 /* check streaming prepare level threshold if not EOS */
3176 if (input && input_stream_based(input) && !input->eos) {
3177 u32 rp, wp, level;
3178
d631e9c2
HZ
3179 rp = STBUF_READ(&vdec->vbuf, get_rp);
3180 wp = STBUF_READ(&vdec->vbuf, get_wp);
a6c89e96
NQ
3181 if (wp < rp)
3182 level = input->size + wp - rp;
3183 else
3184 level = wp - rp;
3185
3186 if ((level < input->prepare_level) &&
3187 (pts_get_rec_num(PTS_TYPE_VIDEO,
3188 vdec->input.total_rd_count) < 2)) {
3189 vdec->need_more_data |= VDEC_NEED_MORE_DATA;
3190#ifdef VDEC_DEBUG_SUPPORT
3191 inc_profi_count(mask, vdec->input_underrun_count);
3192 if (step_mode & 0x200) {
3193 if ((step_mode & 0xff) == vdec->id) {
3194 step_mode |= 0xff;
3195 return mask;
3196 }
3197 }
3198#endif
3199 return false;
e77bbe41
PY
3200 } else if (level > input->prepare_level)
3201 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
a6c89e96 3202 }
fe96802b
NQ
3203 }
3204
b9164398
NQ
3205 if (step_mode) {
3206 if ((step_mode & 0xff) != vdec->id)
a6c89e96
NQ
3207 return 0;
3208 step_mode |= 0xff; /*VDEC_DEBUG_SUPPORT*/
b9164398
NQ
3209 }
3210
a6c89e96 3211 /*step_mode &= ~0xff; not work for id of 0, removed*/
b9164398 3212
fe96802b 3213#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
3214 vdec_profile(vdec, VDEC_PROFILE_EVENT_CHK_RUN_READY);
3215#endif
3216
a6c89e96
NQ
3217 ready_mask = vdec->run_ready(vdec, mask) & mask;
3218#ifdef VDEC_DEBUG_SUPPORT
3219 if (ready_mask != mask)
3220 inc_profi_count(ready_mask ^ mask, vdec->not_run_ready_count);
3221#endif
fe96802b 3222#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
a6c89e96 3223 if (ready_mask)
b9164398
NQ
3224 vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN_READY);
3225#endif
3226
a6c89e96
NQ
3227 return ready_mask;
3228}
3229
3230/* bridge on/off vdec's interrupt processing to vdec core */
3231static void vdec_route_interrupt(struct vdec_s *vdec, unsigned long mask,
3232 bool enable)
3233{
3234 enum vdec_type_e type;
3235
3236 for (type = VDEC_1; type < VDEC_MAX; type++) {
3237 if (mask & (1 << type)) {
3238 struct vdec_isr_context_s *c =
3239 &vdec_core->isr_context[cores_int[type]];
3240 if (enable)
3241 c->vdec = vdec;
3242 else if (c->vdec == vdec)
3243 c->vdec = NULL;
3244 }
3245 }
b9164398
NQ
3246}
3247
fe96802b
NQ
3248/*
3249 * Set up secure protection for each decoder instance running.
3250 * Note: The operation from REE side only resets memory access
3251 * to a default policy and even a non_secure type will still be
3252 * changed to secure type automatically when secure source is
3253 * detected inside TEE.
3254 * Perform need_more_data checking and set flag is decoder
3255 * is not consuming data.
3256 */
a6c89e96 3257void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask)
fe96802b
NQ
3258{
3259 struct vdec_input_s *input = &vdec->input;
a6c89e96 3260 int secure = (vdec_secure(vdec)) ? DMC_DEV_TYPE_SECURE :
fe96802b
NQ
3261 DMC_DEV_TYPE_NON_SECURE;
3262
a6c89e96
NQ
3263 vdec_route_interrupt(vdec, mask, true);
3264
3265 if (!vdec_core_with_input(mask))
3266 return;
3267
0f7b4bb4 3268 if (vdec_stream_based(vdec) && !vdec_secure(vdec))
42173624 3269 {
0f7b4bb4 3270 tee_config_device_secure(DMC_DEV_ID_PARSER, 0);
42173624 3271 }
fe96802b 3272 if (input->target == VDEC_INPUT_TARGET_VLD)
a6c89e96 3273 tee_config_device_secure(DMC_DEV_ID_VDEC, secure);
fe96802b 3274 else if (input->target == VDEC_INPUT_TARGET_HEVC)
a6c89e96 3275 tee_config_device_secure(DMC_DEV_ID_HEVC, secure);
fe96802b
NQ
3276
3277 if (vdec_stream_based(vdec) &&
3278 ((vdec->need_more_data & VDEC_NEED_MORE_DATA_RUN) &&
3279 (vdec->need_more_data & VDEC_NEED_MORE_DATA_DIRTY) == 0)) {
3280 vdec->need_more_data |= VDEC_NEED_MORE_DATA;
3281 }
3282
3283 vdec->need_more_data |= VDEC_NEED_MORE_DATA_RUN;
3284 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA_DIRTY;
3285}
3286
0ed0f572 3287
b9164398
NQ
3288/* struct vdec_core_shread manages all decoder instance in active list. When
3289 * a vdec is added into the active list, it can onlt be in two status:
3290 * VDEC_STATUS_CONNECTED(the decoder does not own HW resource and ready to run)
3291 * VDEC_STATUS_ACTIVE(the decoder owns HW resources and is running).
3292 * Removing a decoder from active list is only performed within core thread.
3293 * Adding a decoder into active list is performed from user thread.
3294 */
3295static int vdec_core_thread(void *data)
3296{
b9164398 3297 struct vdec_core_s *core = (struct vdec_core_s *)data;
158de7c4 3298 struct sched_param param = {.sched_priority = MAX_RT_PRIO/2};
630e09ed 3299 unsigned long flags;
05afa03d 3300 int i;
b9164398
NQ
3301
3302 sched_setscheduler(current, SCHED_FIFO, &param);
3303
3304 allow_signal(SIGTERM);
05afa03d 3305
b9164398 3306 while (down_interruptible(&core->sem) == 0) {
a6c89e96
NQ
3307 struct vdec_s *vdec, *tmp, *worker;
3308 unsigned long sched_mask = 0;
b9164398
NQ
3309 LIST_HEAD(disconnecting_list);
3310
3311 if (kthread_should_stop())
3312 break;
6da7a8e8 3313 mutex_lock(&vdec_mutex);
05afa03d
PY
3314
3315 if (core->parallel_dec == 1) {
3316 for (i = VDEC_1; i < VDEC_MAX; i++) {
3317 core->power_ref_mask =
3318 core->power_ref_count[i] > 0 ?
3319 (core->power_ref_mask | (1 << i)) :
3320 (core->power_ref_mask & ~(1 << i));
3321 }
3322 }
b9164398 3323 /* clean up previous active vdec's input */
a6c89e96
NQ
3324 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
3325 unsigned long mask = vdec->sched_mask &
3326 (vdec->active_mask ^ vdec->sched_mask);
3327
3328 vdec_route_interrupt(vdec, mask, false);
3329
3330#ifdef VDEC_DEBUG_SUPPORT
3331 update_profi_clk_stop(vdec, mask, get_current_clk());
3332#endif
3333 /*
3334 * If decoder released some core resources (mask), then
3335 * check if these core resources are associated
3336 * with any input side and do input clean up accordingly
3337 */
3338 if (vdec_core_with_input(mask)) {
3339 struct vdec_input_s *input = &vdec->input;
3340 while (!list_empty(
3341 &input->vframe_chunk_list)) {
3342 struct vframe_chunk_s *chunk =
3343 vdec_input_next_chunk(input);
87046a60 3344 if (chunk && (chunk->flag &
3345 VFRAME_CHUNK_FLAG_CONSUMED))
a6c89e96
NQ
3346 vdec_input_release_chunk(input,
3347 chunk);
3348 else
3349 break;
3350 }
3351
3352 vdec_save_input_context(vdec);
b9164398
NQ
3353 }
3354
a6c89e96
NQ
3355 vdec->sched_mask &= ~mask;
3356 core->sched_mask &= ~mask;
b9164398 3357 }
0ed0f572 3358 vdec_update_buff_status();
b9164398 3359 /*
e0614bf7 3360 *todo:
b9164398
NQ
3361 * this is the case when the decoder is in active mode and
3362 * the system side wants to stop it. Currently we rely on
3363 * the decoder instance to go back to VDEC_STATUS_CONNECTED
3364 * from VDEC_STATUS_ACTIVE by its own. However, if for some
3365 * reason the decoder can not exist by itself (dead decoding
3366 * or whatever), then we may have to add another vdec API
3367 * to kill the vdec and release its HW resource and make it
3368 * become inactive again.
3369 * if ((core->active_vdec) &&
3370 * (core->active_vdec->status == VDEC_STATUS_DISCONNECTED)) {
3371 * }
3372 */
3373
b9164398 3374 /* check disconnected decoders */
630e09ed 3375 flags = vdec_core_lock(vdec_core);
b9164398
NQ
3376 list_for_each_entry_safe(vdec, tmp,
3377 &core->connected_vdec_list, list) {
3378 if ((vdec->status == VDEC_STATUS_CONNECTED) &&
3379 (vdec->next_status == VDEC_STATUS_DISCONNECTED)) {
05afa03d
PY
3380 if (core->parallel_dec == 1) {
3381 if (vdec_core->active_hevc == vdec)
3382 vdec_core->active_hevc = NULL;
3383 if (vdec_core->active_vdec == vdec)
3384 vdec_core->active_vdec = NULL;
3385 }
3386 if (core->last_vdec == vdec)
3387 core->last_vdec = NULL;
b9164398
NQ
3388 list_move(&vdec->list, &disconnecting_list);
3389 }
3390 }
630e09ed 3391 vdec_core_unlock(vdec_core, flags);
6da7a8e8 3392 mutex_unlock(&vdec_mutex);
a6c89e96 3393 /* elect next vdec to be scheduled */
05afa03d 3394 vdec = core->last_vdec;
a6c89e96
NQ
3395 if (vdec) {
3396 vdec = list_entry(vdec->list.next, struct vdec_s, list);
b9164398
NQ
3397 list_for_each_entry_from(vdec,
3398 &core->connected_vdec_list, list) {
a6c89e96
NQ
3399 sched_mask = vdec_schedule_mask(vdec,
3400 core->sched_mask);
3401 if (!sched_mask)
3402 continue;
3403 sched_mask = vdec_ready_to_run(vdec,
3404 sched_mask);
3405 if (sched_mask)
b9164398
NQ
3406 break;
3407 }
3408
a6c89e96
NQ
3409 if (&vdec->list == &core->connected_vdec_list)
3410 vdec = NULL;
3411 }
3412
3413 if (!vdec) {
3414 /* search from beginning */
3415 list_for_each_entry(vdec,
3416 &core->connected_vdec_list, list) {
3417 sched_mask = vdec_schedule_mask(vdec,
3418 core->sched_mask);
05afa03d 3419 if (vdec == core->last_vdec) {
a6c89e96
NQ
3420 if (!sched_mask) {
3421 vdec = NULL;
b9164398 3422 break;
a6c89e96
NQ
3423 }
3424
3425 sched_mask = vdec_ready_to_run(vdec,
3426 sched_mask);
b9164398 3427
a6c89e96 3428 if (!sched_mask) {
b9164398
NQ
3429 vdec = NULL;
3430 break;
3431 }
a6c89e96 3432 break;
b9164398 3433 }
a6c89e96
NQ
3434
3435 if (!sched_mask)
3436 continue;
3437
3438 sched_mask = vdec_ready_to_run(vdec,
3439 sched_mask);
3440 if (sched_mask)
3441 break;
b9164398
NQ
3442 }
3443
3444 if (&vdec->list == &core->connected_vdec_list)
3445 vdec = NULL;
b9164398
NQ
3446 }
3447
a6c89e96
NQ
3448 worker = vdec;
3449
3450 if (vdec) {
3451 unsigned long mask = sched_mask;
3452 unsigned long i;
3453
3454 /* setting active_mask should be atomic.
3455 * it can be modified by decoder driver callbacks.
3456 */
3457 while (sched_mask) {
3458 i = __ffs(sched_mask);
3459 set_bit(i, &vdec->active_mask);
3460 sched_mask &= ~(1 << i);
3461 }
3462
3463 /* vdec's sched_mask is only set from core thread */
3464 vdec->sched_mask |= mask;
05afa03d
PY
3465 if (core->last_vdec) {
3466 if ((core->last_vdec != vdec) &&
3467 (core->last_vdec->mc_type != vdec->mc_type))
158de7c4 3468 vdec->mc_loaded = 0;/*clear for reload firmware*/
b455a12f
PY
3469 } else
3470 vdec->mc_loaded = 0;
05afa03d 3471 core->last_vdec = vdec;
158de7c4
HZ
3472 if (debug & 2)
3473 vdec->mc_loaded = 0;/*alway reload firmware*/
b9164398
NQ
3474 vdec_set_status(vdec, VDEC_STATUS_ACTIVE);
3475
a6c89e96 3476 core->sched_mask |= mask;
05afa03d
PY
3477 if (core->parallel_dec == 1)
3478 vdec_save_active_hw(vdec);
fe96802b 3479#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
3480 vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN);
3481#endif
a6c89e96
NQ
3482 vdec_prepare_run(vdec, mask);
3483#ifdef VDEC_DEBUG_SUPPORT
3484 inc_profi_count(mask, vdec->run_count);
3485 update_profi_clk_run(vdec, mask, get_current_clk());
3486#endif
51b7cb07 3487
a6c89e96
NQ
3488 vdec->run(vdec, mask, vdec_callback, core);
3489
fe96802b 3490
a6c89e96
NQ
3491 /* we have some cores scheduled, keep working until
3492 * all vdecs are checked with no cores to schedule
3493 */
05afa03d
PY
3494 if (core->parallel_dec == 1) {
3495 if (vdec_core->vdec_combine_flag == 0)
3496 up(&core->sem);
3497 } else
3498 up(&core->sem);
b9164398
NQ
3499 }
3500
3501 /* remove disconnected decoder from active list */
3502 list_for_each_entry_safe(vdec, tmp, &disconnecting_list, list) {
3503 list_del(&vdec->list);
3504 vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
05afa03d 3505 /*core->last_vdec = NULL;*/
b9164398
NQ
3506 complete(&vdec->inactive_done);
3507 }
3508
a6c89e96
NQ
3509 /* if there is no new work scheduled and nothing
3510 * is running, sleep 20ms
3511 */
05afa03d
PY
3512 if (core->parallel_dec == 1) {
3513 if (vdec_core->vdec_combine_flag == 0) {
3514 if ((!worker) &&
3515 ((core->sched_mask != core->power_ref_mask)) &&
0ed0f572
PY
3516 (atomic_read(&vdec_core->vdec_nr) > 0) &&
3517 ((core->buff_flag | core->stream_buff_flag) &
3518 (core->sched_mask ^ core->power_ref_mask))) {
05afa03d
PY
3519 usleep_range(1000, 2000);
3520 up(&core->sem);
3521 }
3522 } else {
0ed0f572
PY
3523 if ((!worker) && (!core->sched_mask) &&
3524 (atomic_read(&vdec_core->vdec_nr) > 0) &&
3525 (core->buff_flag | core->stream_buff_flag)) {
05afa03d
PY
3526 usleep_range(1000, 2000);
3527 up(&core->sem);
3528 }
3529 }
3530 } else if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) {
14d1803e 3531 usleep_range(1000, 2000);
b9164398
NQ
3532 up(&core->sem);
3533 }
3f4a083c 3534
b9164398
NQ
3535 }
3536
3537 return 0;
3538}
3539
3540#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
865e748b
NQ
3541void vdec_power_reset(void)
3542{
3543 /* enable vdec1 isolation */
3544 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
3545 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc0);
3546 /* power off vdec1 memories */
3547 WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
3548 /* vdec1 power off */
3549 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
3550 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc);
3551
3552 if (has_vdec2()) {
3553 /* enable vdec2 isolation */
3554 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
3555 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x300);
3556 /* power off vdec2 memories */
3557 WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL);
3558 /* vdec2 power off */
3559 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
3560 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0x30);
3561 }
3562
3563 if (has_hdec()) {
3564 /* enable hcodec isolation */
3565 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
3566 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30);
3567 /* power off hcodec memories */
3568 WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL);
3569 /* hcodec power off */
3570 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
3571 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 3);
3572 }
3573
3574 if (has_hevc_vdec()) {
3575 /* enable hevc isolation */
3576 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
3577 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc00);
3578 /* power off hevc memories */
3579 WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
3580 /* hevc power off */
3581 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
3582 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc0);
3583 }
3584}
3585EXPORT_SYMBOL(vdec_power_reset);
3586
b9164398
NQ
3587void vdec_poweron(enum vdec_type_e core)
3588{
b9164398
NQ
3589 if (core >= VDEC_MAX)
3590 return;
3591
3592 mutex_lock(&vdec_mutex);
3593
3594 vdec_core->power_ref_count[core]++;
3595 if (vdec_core->power_ref_count[core] > 1) {
3596 mutex_unlock(&vdec_mutex);
3597 return;
3598 }
3599
3600 if (vdec_on(core)) {
3601 mutex_unlock(&vdec_mutex);
3602 return;
3603 }
3604
5166ea72 3605 vdec_core->pm->power_on(vdec_core->cma_dev, core);
b9164398
NQ
3606
3607 mutex_unlock(&vdec_mutex);
3608}
3609EXPORT_SYMBOL(vdec_poweron);
3610
3611void vdec_poweroff(enum vdec_type_e core)
3612{
3613 if (core >= VDEC_MAX)
3614 return;
3615
3616 mutex_lock(&vdec_mutex);
3617
3618 vdec_core->power_ref_count[core]--;
3619 if (vdec_core->power_ref_count[core] > 0) {
3620 mutex_unlock(&vdec_mutex);
3621 return;
3622 }
3623
5166ea72 3624 vdec_core->pm->power_off(vdec_core->cma_dev, core);
fb394ef8 3625
b9164398
NQ
3626 mutex_unlock(&vdec_mutex);
3627}
3628EXPORT_SYMBOL(vdec_poweroff);
3629
3630bool vdec_on(enum vdec_type_e core)
3631{
5166ea72 3632 return vdec_core->pm->power_state(vdec_core->cma_dev, core);
b9164398
NQ
3633}
3634EXPORT_SYMBOL(vdec_on);
3635
3636#elif 0 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
3637void vdec_poweron(enum vdec_type_e core)
3638{
3639 ulong flags;
3640
3641 spin_lock_irqsave(&lock, flags);
3642
3643 if (core == VDEC_1) {
3644 /* vdec1 soft reset */
3645 WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
3646 WRITE_VREG(DOS_SW_RESET0, 0);
3647 /* enable vdec1 clock */
3648 vdec_clock_enable();
3649 /* reset DOS top registers */
3650 WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0);
3651 } else if (core == VDEC_2) {
3652 /* vdec2 soft reset */
3653 WRITE_VREG(DOS_SW_RESET2, 0xffffffff);
3654 WRITE_VREG(DOS_SW_RESET2, 0);
3655 /* enable vdec2 clock */
3656 vdec2_clock_enable();
3657 /* reset DOS top registers */
3658 WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0);
3659 } else if (core == VDEC_HCODEC) {
3660 /* hcodec soft reset */
3661 WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
3662 WRITE_VREG(DOS_SW_RESET1, 0);
3663 /* enable hcodec clock */
3664 hcodec_clock_enable();
3665 }
3666
3667 spin_unlock_irqrestore(&lock, flags);
3668}
3669
3670void vdec_poweroff(enum vdec_type_e core)
3671{
3672 ulong flags;
3673
3674 spin_lock_irqsave(&lock, flags);
3675
3676 if (core == VDEC_1) {
3677 /* disable vdec1 clock */
3678 vdec_clock_off();
3679 } else if (core == VDEC_2) {
3680 /* disable vdec2 clock */
3681 vdec2_clock_off();
3682 } else if (core == VDEC_HCODEC) {
3683 /* disable hcodec clock */
3684 hcodec_clock_off();
3685 }
3686
3687 spin_unlock_irqrestore(&lock, flags);
3688}
3689
3690bool vdec_on(enum vdec_type_e core)
3691{
3692 bool ret = false;
3693
3694 if (core == VDEC_1) {
3695 if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100)
3696 ret = true;
3697 } else if (core == VDEC_2) {
3698 if (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100)
3699 ret = true;
3700 } else if (core == VDEC_HCODEC) {
3701 if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000)
3702 ret = true;
3703 }
3704
3705 return ret;
3706}
3707#endif
3708
3709int vdec_source_changed(int format, int width, int height, int fps)
3710{
3711 /* todo: add level routines for clock adjustment per chips */
3712 int ret = -1;
3713 static int on_setting;
3714
3715 if (on_setting > 0)
3716 return ret;/*on changing clk,ignore this change*/
3717
3718 if (vdec_source_get(VDEC_1) == width * height * fps)
3719 return ret;
3720
3721
3722 on_setting = 1;
3723 ret = vdec_source_changed_for_clk_set(format, width, height, fps);
5b851ff9 3724 pr_debug("vdec1 video changed to %d x %d %d fps clk->%dMHZ\n",
b9164398
NQ
3725 width, height, fps, vdec_clk_get(VDEC_1));
3726 on_setting = 0;
3727 return ret;
3728
3729}
3730EXPORT_SYMBOL(vdec_source_changed);
790386eb 3731
144f5ee8 3732void vdec_reset_core(struct vdec_s *vdec)
ecd31bc4 3733{
ecd31bc4 3734 unsigned long flags;
144f5ee8 3735 unsigned int mask = 0;
ecd31bc4 3736
144f5ee8
HZ
3737 mask = 1 << 13; /*bit13: DOS VDEC interface*/
3738 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
3739 mask = 1 << 21; /*bit21: DOS VDEC interface*/
ecd31bc4 3740
ecd31bc4 3741 spin_lock_irqsave(&vdec_spin_lock, flags);
3742 codec_dmcbus_write(DMC_REQ_CTRL,
144f5ee8 3743 codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
87046a60 3744 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3745
1418c7d8 3746 if (is_cpu_tm2_revb() ||
3747 (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
97256936 3748 while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
3749 & mask))
3750 ;
3751 } else {
3752 while (!(codec_dmcbus_read(DMC_CHAN_STS)
3753 & mask))
3754 ;
3755 }
87046a60 3756 /*
3757 * 2: assist
3758 * 3: vld_reset
3759 * 4: vld_part_reset
3760 * 5: vfifo reset
3761 * 6: iqidct
3762 * 7: mc
3763 * 8: dblk
3764 * 9: pic_dc
3765 * 10: psc
3766 * 11: mcpu
3767 * 12: ccpu
3768 * 13: ddr
3769 * 14: afifo
3770 */
654ebddc 3771 WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)|(1<<7)|(1<<8)|(1<<9));
87046a60 3772 WRITE_VREG(DOS_SW_RESET0, 0);
3773
3774 spin_lock_irqsave(&vdec_spin_lock, flags);
3775 codec_dmcbus_write(DMC_REQ_CTRL,
144f5ee8 3776 codec_dmcbus_read(DMC_REQ_CTRL) | mask);
87046a60 3777 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3778}
3779EXPORT_SYMBOL(vdec_reset_core);
3780
144f5ee8 3781void hevc_mmu_dma_check(struct vdec_s *vdec)
c4265ace 3782{
144f5ee8
HZ
3783 ulong timeout;
3784 u32 data;
3785 if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A)
3786 return;
3787 timeout = jiffies + HZ/100;
3788 while (1) {
3789 data = READ_VREG(HEVC_CM_CORE_STATUS);
3790 if ((data & 0x1) == 0)
3791 break;
3792 if (time_after(jiffies, timeout)) {
3793 if (debug & 0x10)
3794 pr_info(" %s sao mmu dma idle\n", __func__);
3795 break;
3796 }
3797 }
3798 /*disable sao mmu dma */
3799 CLEAR_VREG_MASK(HEVC_SAO_MMU_DMA_CTRL, 1 << 0);
3800 timeout = jiffies + HZ/100;
3801 while (1) {
3802 data = READ_VREG(HEVC_SAO_MMU_DMA_STATUS);
3803 if ((data & 0x1))
3804 break;
3805 if (time_after(jiffies, timeout)) {
3806 if (debug & 0x10)
3807 pr_err("%s sao mmu dma timeout, num_buf_used = 0x%x\n",
3808 __func__, (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16));
3809 break;
3810 }
3811 }
c4265ace 3812}
144f5ee8 3813EXPORT_SYMBOL(hevc_mmu_dma_check);
c4265ace 3814
fe96802b
NQ
3815void hevc_reset_core(struct vdec_s *vdec)
3816{
3817 unsigned long flags;
144f5ee8 3818 unsigned int mask = 0;
d3b4fbc5 3819 int cpu_type;
144f5ee8
HZ
3820
3821 mask = 1 << 4; /*bit4: hevc*/
3822 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
3823 mask |= 1 << 8; /*bit8: hevcb*/
3824
fe96802b
NQ
3825 WRITE_VREG(HEVC_STREAM_CONTROL, 0);
3826 spin_lock_irqsave(&vdec_spin_lock, flags);
3827 codec_dmcbus_write(DMC_REQ_CTRL,
144f5ee8 3828 codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
fe96802b
NQ
3829 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3830
1418c7d8 3831 if (is_cpu_tm2_revb() ||
3832 (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
97256936 3833 while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
3834 & mask))
3835 ;
3836 } else {
3837 while (!(codec_dmcbus_read(DMC_CHAN_STS)
3838 & mask))
3839 ;
3840 }
fe96802b 3841
28e318df 3842 if (vdec == NULL || input_frame_based(vdec))
fe96802b
NQ
3843 WRITE_VREG(HEVC_STREAM_CONTROL, 0);
3844
d3b4fbc5 3845
3846 WRITE_VREG(HEVC_SAO_MMU_RESET_CTRL,
3847 READ_VREG(HEVC_SAO_MMU_RESET_CTRL) | 1);
3848
fe96802b
NQ
3849 /*
3850 * 2: assist
3851 * 3: parser
3852 * 4: parser_state
3853 * 8: dblk
d3b4fbc5 3854 * 10:wrrsp lmem
fe96802b
NQ
3855 * 11:mcpu
3856 * 12:ccpu
3857 * 13:ddr
3858 * 14:iqit
3859 * 15:ipp
3860 * 17:qdct
3861 * 18:mpred
3862 * 19:sao
3863 * 24:hevc_afifo
d3b4fbc5 3864 * 26:rst_mmu_n
fe96802b 3865 */
1418c7d8 3866 if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2) &&
3867 (vdec->format == VFORMAT_AVS2)) {
3868 WRITE_VREG(DOS_SW_RESET3,
fe96802b 3869 (1<<3)|(1<<4)|(1<<8)|(1<<11)|
1418c7d8 3870 (1<<12)|(1<<14)|(1<<15)|
3871 (1<<17)|(1<<18)|(1<<19));
3872 } else {
3873 WRITE_VREG(DOS_SW_RESET3,
d3b4fbc5 3874 (1<<3)|(1<<4)|(1<<8)|(1<<10)|(1<<11)|
1418c7d8 3875 (1<<12)|(1<<13)|(1<<14)|(1<<15)|
d3b4fbc5 3876 (1<<17)|(1<<18)|(1<<19)|(1<<24)|(1<<26));
1418c7d8 3877 }
fe96802b
NQ
3878
3879 WRITE_VREG(DOS_SW_RESET3, 0);
d3b4fbc5 3880 while (READ_VREG(HEVC_WRRSP_LMEM) & 0xfff)
3881 ;
3882 WRITE_VREG(HEVC_SAO_MMU_RESET_CTRL,
3883 READ_VREG(HEVC_SAO_MMU_RESET_CTRL) & (~1));
3884 cpu_type = get_cpu_major_id();
3885 if (cpu_type == AM_MESON_CPU_MAJOR_ID_TL1 &&
3886 is_meson_rev_b())
3887 cpu_type = AM_MESON_CPU_MAJOR_ID_G12B;
3888 switch (cpu_type) {
3889 case AM_MESON_CPU_MAJOR_ID_G12B:
3890 WRITE_RESET_REG((RESET7_REGISTER_LEVEL),
3891 READ_RESET_REG(RESET7_REGISTER_LEVEL) & (~((1<<13)|(1<<14))));
3892 WRITE_RESET_REG((RESET7_REGISTER_LEVEL),
3893 READ_RESET_REG((RESET7_REGISTER_LEVEL)) | ((1<<13)|(1<<14)));
3894 break;
3895 case AM_MESON_CPU_MAJOR_ID_G12A:
3896 case AM_MESON_CPU_MAJOR_ID_SM1:
3897 case AM_MESON_CPU_MAJOR_ID_TL1:
3898 case AM_MESON_CPU_MAJOR_ID_TM2:
3899 WRITE_RESET_REG((RESET7_REGISTER_LEVEL),
3900 READ_RESET_REG(RESET7_REGISTER_LEVEL) & (~((1<<13))));
3901 WRITE_RESET_REG((RESET7_REGISTER_LEVEL),
3902 READ_RESET_REG((RESET7_REGISTER_LEVEL)) | ((1<<13)));
3903 break;
3904 case AM_MESON_CPU_MAJOR_ID_SC2:
3905 WRITE_RESET_REG(P_RESETCTRL_RESET5_LEVEL,
3906 READ_RESET_REG(P_RESETCTRL_RESET5_LEVEL) & (~((1<<1)|(1<<12)|(1<<13))));
3907 WRITE_RESET_REG(P_RESETCTRL_RESET5_LEVEL,
3908 READ_RESET_REG(P_RESETCTRL_RESET5_LEVEL) | ((1<<1)|(1<<12)|(1<<13)));
3909 break;
3910 default:
3911 break;
3912 }
fe96802b
NQ
3913
3914
3915 spin_lock_irqsave(&vdec_spin_lock, flags);
3916 codec_dmcbus_write(DMC_REQ_CTRL,
144f5ee8 3917 codec_dmcbus_read(DMC_REQ_CTRL) | mask);
fe96802b
NQ
3918 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3919
3920}
3921EXPORT_SYMBOL(hevc_reset_core);
3922
b9164398
NQ
3923int vdec2_source_changed(int format, int width, int height, int fps)
3924{
3925 int ret = -1;
3926 static int on_setting;
3927
3928 if (has_vdec2()) {
3929 /* todo: add level routines for clock adjustment per chips */
3930 if (on_setting != 0)
3931 return ret;/*on changing clk,ignore this change*/
3932
3933 if (vdec_source_get(VDEC_2) == width * height * fps)
3934 return ret;
3935
3936 on_setting = 1;
3937 ret = vdec_source_changed_for_clk_set(format,
3938 width, height, fps);
5b851ff9 3939 pr_debug("vdec2 video changed to %d x %d %d fps clk->%dMHZ\n",
b9164398
NQ
3940 width, height, fps, vdec_clk_get(VDEC_2));
3941 on_setting = 0;
3942 return ret;
3943 }
3944 return 0;
3945}
3946EXPORT_SYMBOL(vdec2_source_changed);
3947
3948int hevc_source_changed(int format, int width, int height, int fps)
3949{
3950 /* todo: add level routines for clock adjustment per chips */
3951 int ret = -1;
3952 static int on_setting;
3953
3954 if (on_setting != 0)
3955 return ret;/*on changing clk,ignore this change*/
3956
3957 if (vdec_source_get(VDEC_HEVC) == width * height * fps)
3958 return ret;
3959
3960 on_setting = 1;
3961 ret = vdec_source_changed_for_clk_set(format, width, height, fps);
5b851ff9 3962 pr_debug("hevc video changed to %d x %d %d fps clk->%dMHZ\n",
b9164398
NQ
3963 width, height, fps, vdec_clk_get(VDEC_HEVC));
3964 on_setting = 0;
3965
3966 return ret;
3967}
3968EXPORT_SYMBOL(hevc_source_changed);
3969
b9164398
NQ
3970static struct am_reg am_risc[] = {
3971 {"MSP", 0x300},
3972 {"MPSR", 0x301},
3973 {"MCPU_INT_BASE", 0x302},
3974 {"MCPU_INTR_GRP", 0x303},
3975 {"MCPU_INTR_MSK", 0x304},
3976 {"MCPU_INTR_REQ", 0x305},
3977 {"MPC-P", 0x306},
3978 {"MPC-D", 0x307},
3979 {"MPC_E", 0x308},
3980 {"MPC_W", 0x309},
3981 {"CSP", 0x320},
3982 {"CPSR", 0x321},
3983 {"CCPU_INT_BASE", 0x322},
3984 {"CCPU_INTR_GRP", 0x323},
3985 {"CCPU_INTR_MSK", 0x324},
3986 {"CCPU_INTR_REQ", 0x325},
3987 {"CPC-P", 0x326},
3988 {"CPC-D", 0x327},
3989 {"CPC_E", 0x328},
3990 {"CPC_W", 0x329},
3991 {"AV_SCRATCH_0", 0x09c0},
3992 {"AV_SCRATCH_1", 0x09c1},
3993 {"AV_SCRATCH_2", 0x09c2},
3994 {"AV_SCRATCH_3", 0x09c3},
3995 {"AV_SCRATCH_4", 0x09c4},
3996 {"AV_SCRATCH_5", 0x09c5},
3997 {"AV_SCRATCH_6", 0x09c6},
3998 {"AV_SCRATCH_7", 0x09c7},
3999 {"AV_SCRATCH_8", 0x09c8},
4000 {"AV_SCRATCH_9", 0x09c9},
4001 {"AV_SCRATCH_A", 0x09ca},
4002 {"AV_SCRATCH_B", 0x09cb},
4003 {"AV_SCRATCH_C", 0x09cc},
4004 {"AV_SCRATCH_D", 0x09cd},
4005 {"AV_SCRATCH_E", 0x09ce},
4006 {"AV_SCRATCH_F", 0x09cf},
4007 {"AV_SCRATCH_G", 0x09d0},
4008 {"AV_SCRATCH_H", 0x09d1},
4009 {"AV_SCRATCH_I", 0x09d2},
4010 {"AV_SCRATCH_J", 0x09d3},
4011 {"AV_SCRATCH_K", 0x09d4},
4012 {"AV_SCRATCH_L", 0x09d5},
4013 {"AV_SCRATCH_M", 0x09d6},
4014 {"AV_SCRATCH_N", 0x09d7},
4015};
4016
4017static ssize_t amrisc_regs_show(struct class *class,
4018 struct class_attribute *attr, char *buf)
4019{
4020 char *pbuf = buf;
4021 struct am_reg *regs = am_risc;
4022 int rsize = sizeof(am_risc) / sizeof(struct am_reg);
4023 int i;
e0614bf7 4024 unsigned int val;
b9164398
NQ
4025 ssize_t ret;
4026
63e810c0 4027 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
4028 mutex_lock(&vdec_mutex);
4029 if (!vdec_on(VDEC_1)) {
4030 mutex_unlock(&vdec_mutex);
4031 pbuf += sprintf(pbuf, "amrisc is power off\n");
4032 ret = pbuf - buf;
4033 return ret;
4034 }
63e810c0 4035 } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4036 /*TODO:M6 define */
4037 /*
4038 * switch_mod_gate_by_type(MOD_VDEC, 1);
4039 */
4040 amports_switch_gate("vdec", 1);
4041 }
4042 pbuf += sprintf(pbuf, "amrisc registers show:\n");
4043 for (i = 0; i < rsize; i++) {
4044 val = READ_VREG(regs[i].offset);
4045 pbuf += sprintf(pbuf, "%s(%#x)\t:%#x(%d)\n",
4046 regs[i].name, regs[i].offset, val, val);
4047 }
63e810c0 4048 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
b9164398 4049 mutex_unlock(&vdec_mutex);
63e810c0 4050 else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4051 /*TODO:M6 define */
4052 /*
4053 * switch_mod_gate_by_type(MOD_VDEC, 0);
4054 */
4055 amports_switch_gate("vdec", 0);
4056 }
4057 ret = pbuf - buf;
4058 return ret;
4059}
4060
4061static ssize_t dump_trace_show(struct class *class,
4062 struct class_attribute *attr, char *buf)
4063{
4064 int i;
4065 char *pbuf = buf;
4066 ssize_t ret;
beec8b33 4067 u16 *trace_buf = vzalloc(debug_trace_num * 2);
b9164398
NQ
4068
4069 if (!trace_buf) {
4070 pbuf += sprintf(pbuf, "No Memory bug\n");
4071 ret = pbuf - buf;
4072 return ret;
4073 }
63e810c0 4074 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
4075 mutex_lock(&vdec_mutex);
4076 if (!vdec_on(VDEC_1)) {
4077 mutex_unlock(&vdec_mutex);
beec8b33 4078 vfree(trace_buf);
b9164398
NQ
4079 pbuf += sprintf(pbuf, "amrisc is power off\n");
4080 ret = pbuf - buf;
4081 return ret;
4082 }
63e810c0 4083 } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4084 /*TODO:M6 define */
4085 /*
4086 * switch_mod_gate_by_type(MOD_VDEC, 1);
4087 */
4088 amports_switch_gate("vdec", 1);
4089 }
4090 pr_info("dump trace steps:%d start\n", debug_trace_num);
4091 i = 0;
4092 while (i <= debug_trace_num - 16) {
4093 trace_buf[i] = READ_VREG(MPC_E);
4094 trace_buf[i + 1] = READ_VREG(MPC_E);
4095 trace_buf[i + 2] = READ_VREG(MPC_E);
4096 trace_buf[i + 3] = READ_VREG(MPC_E);
4097 trace_buf[i + 4] = READ_VREG(MPC_E);
4098 trace_buf[i + 5] = READ_VREG(MPC_E);
4099 trace_buf[i + 6] = READ_VREG(MPC_E);
4100 trace_buf[i + 7] = READ_VREG(MPC_E);
4101 trace_buf[i + 8] = READ_VREG(MPC_E);
4102 trace_buf[i + 9] = READ_VREG(MPC_E);
4103 trace_buf[i + 10] = READ_VREG(MPC_E);
4104 trace_buf[i + 11] = READ_VREG(MPC_E);
4105 trace_buf[i + 12] = READ_VREG(MPC_E);
4106 trace_buf[i + 13] = READ_VREG(MPC_E);
4107 trace_buf[i + 14] = READ_VREG(MPC_E);
4108 trace_buf[i + 15] = READ_VREG(MPC_E);
4109 i += 16;
4110 };
4111 pr_info("dump trace steps:%d finished\n", debug_trace_num);
63e810c0 4112 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
b9164398 4113 mutex_unlock(&vdec_mutex);
63e810c0 4114 else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4115 /*TODO:M6 define */
4116 /*
4117 * switch_mod_gate_by_type(MOD_VDEC, 0);
4118 */
4119 amports_switch_gate("vdec", 0);
4120 }
4121 for (i = 0; i < debug_trace_num; i++) {
4122 if (i % 4 == 0) {
4123 if (i % 16 == 0)
4124 pbuf += sprintf(pbuf, "\n");
4125 else if (i % 8 == 0)
4126 pbuf += sprintf(pbuf, " ");
4127 else /* 4 */
4128 pbuf += sprintf(pbuf, " ");
4129 }
4130 pbuf += sprintf(pbuf, "%04x:", trace_buf[i]);
4131 }
4132 while (i < debug_trace_num)
4133 ;
beec8b33 4134 vfree(trace_buf);
b9164398
NQ
4135 pbuf += sprintf(pbuf, "\n");
4136 ret = pbuf - buf;
4137 return ret;
4138}
4139
4140static ssize_t clock_level_show(struct class *class,
4141 struct class_attribute *attr, char *buf)
4142{
4143 char *pbuf = buf;
4144 size_t ret;
4145
4146 pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_1));
4147
4148 if (has_vdec2())
4149 pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_2));
4150
4151 if (has_hevc_vdec())
4152 pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_HEVC));
4153
4154 ret = pbuf - buf;
4155 return ret;
4156}
4157
cc41710a 4158static ssize_t enable_mvdec_info_show(struct class *cla,
4159 struct class_attribute *attr, char *buf)
4160{
4161 return sprintf(buf, "%d\n", enable_mvdec_info);
4162}
4163
4164static ssize_t enable_mvdec_info_store(struct class *cla,
4165 struct class_attribute *attr,
4166 const char *buf, size_t count)
4167{
4168 int r;
4169 int val;
4170
4171 r = kstrtoint(buf, 0, &val);
4172 if (r < 0)
4173 return -EINVAL;
4174 enable_mvdec_info = val;
4175
4176 return count;
4177}
4178
b9164398
NQ
4179static ssize_t store_poweron_clock_level(struct class *class,
4180 struct class_attribute *attr,
4181 const char *buf, size_t size)
4182{
e0614bf7 4183 unsigned int val;
b9164398
NQ
4184 ssize_t ret;
4185
4186 /*ret = sscanf(buf, "%d", &val);*/
4187 ret = kstrtoint(buf, 0, &val);
4188
4189 if (ret != 0)
4190 return -EINVAL;
4191 poweron_clock_level = val;
4192 return size;
4193}
4194
4195static ssize_t show_poweron_clock_level(struct class *class,
4196 struct class_attribute *attr, char *buf)
4197{
4198 return sprintf(buf, "%d\n", poweron_clock_level);
4199}
4200
4201/*
e0614bf7
ZZ
4202 *if keep_vdec_mem == 1
4203 *always don't release
4204 *vdec 64 memory for fast play.
4205 */
b9164398
NQ
4206static ssize_t store_keep_vdec_mem(struct class *class,
4207 struct class_attribute *attr,
4208 const char *buf, size_t size)
4209{
e0614bf7 4210 unsigned int val;
b9164398
NQ
4211 ssize_t ret;
4212
4213 /*ret = sscanf(buf, "%d", &val);*/
4214 ret = kstrtoint(buf, 0, &val);
4215 if (ret != 0)
4216 return -EINVAL;
4217 keep_vdec_mem = val;
4218 return size;
4219}
4220
4221static ssize_t show_keep_vdec_mem(struct class *class,
4222 struct class_attribute *attr, char *buf)
4223{
4224 return sprintf(buf, "%d\n", keep_vdec_mem);
4225}
4226
cc41710a 4227
a6c89e96
NQ
4228#ifdef VDEC_DEBUG_SUPPORT
4229static ssize_t store_debug(struct class *class,
4230 struct class_attribute *attr,
4231 const char *buf, size_t size)
4232{
4233 struct vdec_s *vdec;
4234 struct vdec_core_s *core = vdec_core;
4235 unsigned long flags;
4236
4237 unsigned id;
4238 unsigned val;
4239 ssize_t ret;
4240 char cbuf[32];
4241
4242 cbuf[0] = 0;
4243 ret = sscanf(buf, "%s %x %x", cbuf, &id, &val);
4244 /*pr_info(
4245 "%s(%s)=>ret %ld: %s, %x, %x\n",
4246 __func__, buf, ret, cbuf, id, val);*/
4247 if (strcmp(cbuf, "schedule") == 0) {
4248 pr_info("VDEC_DEBUG: force schedule\n");
4249 up(&core->sem);
4250 } else if (strcmp(cbuf, "power_off") == 0) {
4251 pr_info("VDEC_DEBUG: power off core %d\n", id);
4252 vdec_poweroff(id);
4253 } else if (strcmp(cbuf, "power_on") == 0) {
4254 pr_info("VDEC_DEBUG: power_on core %d\n", id);
4255 vdec_poweron(id);
4256 } else if (strcmp(cbuf, "wr") == 0) {
4257 pr_info("VDEC_DEBUG: WRITE_VREG(0x%x, 0x%x)\n",
4258 id, val);
4259 WRITE_VREG(id, val);
4260 } else if (strcmp(cbuf, "rd") == 0) {
4261 pr_info("VDEC_DEBUG: READ_VREG(0x%x) = 0x%x\n",
4262 id, READ_VREG(id));
4263 } else if (strcmp(cbuf, "read_hevc_clk_reg") == 0) {
4264 pr_info(
4265 "VDEC_DEBUG: HHI_VDEC4_CLK_CNTL = 0x%x, HHI_VDEC2_CLK_CNTL = 0x%x\n",
4266 READ_HHI_REG(HHI_VDEC4_CLK_CNTL),
4267 READ_HHI_REG(HHI_VDEC2_CLK_CNTL));
4268 }
4269
4270 flags = vdec_core_lock(vdec_core);
4271
4272 list_for_each_entry(vdec,
4273 &core->connected_vdec_list, list) {
4274 pr_info("vdec: status %d, id %d\n", vdec->status, vdec->id);
4275 if (((vdec->status == VDEC_STATUS_CONNECTED
4276 || vdec->status == VDEC_STATUS_ACTIVE)) &&
4277 (vdec->id == id)) {
4278 /*to add*/
4279 break;
4280 }
4281 }
4282 vdec_core_unlock(vdec_core, flags);
4283 return size;
4284}
4285
4286static ssize_t show_debug(struct class *class,
4287 struct class_attribute *attr, char *buf)
4288{
4289 char *pbuf = buf;
4290 struct vdec_s *vdec;
4291 struct vdec_core_s *core = vdec_core;
4292 unsigned long flags = vdec_core_lock(vdec_core);
1e37ecab 4293 u64 tmp;
a6c89e96
NQ
4294
4295 pbuf += sprintf(pbuf,
4296 "============== help:\n");
4297 pbuf += sprintf(pbuf,
4298 "'echo xxx > debug' usuage:\n");
4299 pbuf += sprintf(pbuf,
4300 "schedule - trigger schedule thread to run\n");
4301 pbuf += sprintf(pbuf,
4302 "power_off core_num - call vdec_poweroff(core_num)\n");
4303 pbuf += sprintf(pbuf,
4304 "power_on core_num - call vdec_poweron(core_num)\n");
4305 pbuf += sprintf(pbuf,
4306 "wr adr val - call WRITE_VREG(adr, val)\n");
4307 pbuf += sprintf(pbuf,
4308 "rd adr - call READ_VREG(adr)\n");
4309 pbuf += sprintf(pbuf,
4310 "read_hevc_clk_reg - read HHI register for hevc clk\n");
4311 pbuf += sprintf(pbuf,
4312 "===================\n");
4313
4314 pbuf += sprintf(pbuf,
4315 "name(core)\tschedule_count\trun_count\tinput_underrun\tdecbuf_not_ready\trun_time\n");
4316 list_for_each_entry(vdec,
4317 &core->connected_vdec_list, list) {
4318 enum vdec_type_e type;
976f3376
HZ
4319 if ((vdec->status == VDEC_STATUS_CONNECTED
4320 || vdec->status == VDEC_STATUS_ACTIVE)) {
a6c89e96
NQ
4321 for (type = VDEC_1; type < VDEC_MAX; type++) {
4322 if (vdec->core_mask & (1 << type)) {
4323 pbuf += sprintf(pbuf, "%s(%d):",
4324 vdec->vf_provider_name, type);
4325 pbuf += sprintf(pbuf, "\t%d",
4326 vdec->check_count[type]);
4327 pbuf += sprintf(pbuf, "\t%d",
4328 vdec->run_count[type]);
4329 pbuf += sprintf(pbuf, "\t%d",
4330 vdec->input_underrun_count[type]);
4331 pbuf += sprintf(pbuf, "\t%d",
4332 vdec->not_run_ready_count[type]);
1e37ecab
AX
4333 tmp = vdec->run_clk[type] * 100;
4334 do_div(tmp, vdec->total_clk[type]);
a6c89e96
NQ
4335 pbuf += sprintf(pbuf,
4336 "\t%d%%\n",
4337 vdec->total_clk[type] == 0 ? 0 :
1e37ecab 4338 (u32)tmp);
a6c89e96
NQ
4339 }
4340 }
976f3376 4341 }
a6c89e96
NQ
4342 }
4343
4344 vdec_core_unlock(vdec_core, flags);
4345 return pbuf - buf;
4346
4347}
4348#endif
b9164398 4349
d631e9c2
HZ
4350int show_stream_buffer_status(char *buf,
4351 int (*callback) (struct stream_buf_s *, char *))
4352{
4353 char *pbuf = buf;
4354 struct vdec_s *vdec;
4355 struct vdec_core_s *core = vdec_core;
4356 u64 flags = vdec_core_lock(vdec_core);
4357
4358 list_for_each_entry(vdec,
4359 &core->connected_vdec_list, list) {
4360 if ((vdec->status == VDEC_STATUS_CONNECTED
4361 || vdec->status == VDEC_STATUS_ACTIVE)) {
4362 if (vdec_frame_based(vdec))
4363 continue;
4364 pbuf += callback(&vdec->vbuf, pbuf);
4365 }
4366 }
4367 vdec_core_unlock(vdec_core, flags);
4368
4369 return pbuf - buf;
4370}
4371EXPORT_SYMBOL(show_stream_buffer_status);
4372
4373e91a 4373static ssize_t store_vdec_vfm_path(struct class *class,
4374 struct class_attribute *attr,
4375 const char *buf, size_t count)
4376{
4377 char *buf_dup, *ps, *token;
4378 char str[VDEC_MAP_NAME_SIZE] = "\0";
4379 bool found = false;
4380 int i;
4381
4382 if (strlen(buf) >= VDEC_MAP_NAME_SIZE) {
4383 pr_info("parameter is overflow\n");
4384 return -1;
4385 }
4386
4387 buf_dup = kstrdup(buf, GFP_KERNEL);
4388 ps = buf_dup;
4389 while (1) {
4390 token = strsep(&ps, "\n ");
4391 if (token == NULL)
4392 break;
4393 if (*token == '\0')
4394 continue;
4395
4396 for (i = 0; strcmp("reserved", vfm_path_node[i]) != 0; i++) {
4397 if (!strncmp (vfm_path_node[i], token, strlen(vfm_path_node[i]))) {
4398 break;
4399 }
4400 }
4401
4402 if (strcmp("reserved", vfm_path_node[i]) == 0 ||
4403 strncmp("help", buf, strlen("help")) == 0) {
4404 if (strncmp("help", buf, strlen("help")) != 0) {
4405 pr_info("warnning! Input parameter is invalid. set failed!\n");
4406 }
4407 pr_info("\nusage for example: \n");
4408 pr_info("echo help > /sys/class/vdec/vfm_path \n");
4409 pr_info("echo disable > /sys/class/vdec/vfm_path \n");
4410 pr_info("echo amlvideo ppmgr amvideo > /sys/class/vdec/vfm_path \n");
4411 found = false;
4412
4413 break;
4414 } else {
4415 strcat(str, vfm_path_node[i]);
4416 strcat(str, " ");
4417 found = true;
4418 }
4419 }
4420
4421 if (found == true) {
4422 memset(vfm_path, 0, sizeof(vfm_path));
4423 strncpy(vfm_path, str, strlen(str));
4424 vfm_path[VDEC_MAP_NAME_SIZE - 1] = '\0';
4425 pr_info("cfg path success: decoder %s\n", vfm_path);
4426 }
4427 kfree(buf_dup);
4428
4429 return count;
4430}
4431
4432static ssize_t show_vdec_vfm_path(struct class *class,
4433 struct class_attribute *attr, char *buf)
4434{
4435 int len = 0;
4436 int i;
4437 len += sprintf(buf + len, "cfg vfm path: decoder %s\n", vfm_path);
4438 len += sprintf(buf + len, "\nvfm path node list: \n");
4439 for (i = 0; strcmp("reserved", vfm_path_node[i]) != 0; i++) {
4440 len += sprintf(buf + len, "\t%s \n", vfm_path_node[i]);
4441 }
4442
4443 return len;
4444}
4445
b9164398
NQ
4446/*irq num as same as .dts*/
4447/*
e0614bf7
ZZ
4448 * interrupts = <0 3 1
4449 * 0 23 1
4450 * 0 32 1
4451 * 0 43 1
4452 * 0 44 1
4453 * 0 45 1>;
4454 * interrupt-names = "vsync",
4455 * "demux",
4456 * "parser",
4457 * "mailbox_0",
4458 * "mailbox_1",
4459 * "mailbox_2";
4460 */
b9164398
NQ
4461s32 vdec_request_threaded_irq(enum vdec_irq_num num,
4462 irq_handler_t handler,
4463 irq_handler_t thread_fn,
4464 unsigned long irqflags,
4465 const char *devname, void *dev)
4466{
4467 s32 res_irq;
4468 s32 ret = 0;
4469
4470 if (num >= VDEC_IRQ_MAX) {
4471 pr_err("[%s] request irq error, irq num too big!", __func__);
4472 return -EINVAL;
4473 }
4474
4475 if (vdec_core->isr_context[num].irq < 0) {
4476 res_irq = platform_get_irq(
4477 vdec_core->vdec_core_platform_device, num);
4478 if (res_irq < 0) {
4479 pr_err("[%s] get irq error!", __func__);
4480 return -EINVAL;
4481 }
4482
4483 vdec_core->isr_context[num].irq = res_irq;
4484 vdec_core->isr_context[num].dev_isr = handler;
4485 vdec_core->isr_context[num].dev_threaded_isr = thread_fn;
4486 vdec_core->isr_context[num].dev_id = dev;
4487
4488 ret = request_threaded_irq(res_irq,
4489 vdec_isr,
4490 vdec_thread_isr,
4491 (thread_fn) ? IRQF_ONESHOT : irqflags,
4492 devname,
4493 &vdec_core->isr_context[num]);
4494
4495 if (ret) {
4496 vdec_core->isr_context[num].irq = -1;
4497 vdec_core->isr_context[num].dev_isr = NULL;
4498 vdec_core->isr_context[num].dev_threaded_isr = NULL;
4499 vdec_core->isr_context[num].dev_id = NULL;
4500
4501 pr_err("vdec irq register error for %s.\n", devname);
4502 return -EIO;
4503 }
4504 } else {
4505 vdec_core->isr_context[num].dev_isr = handler;
4506 vdec_core->isr_context[num].dev_threaded_isr = thread_fn;
4507 vdec_core->isr_context[num].dev_id = dev;
4508 }
4509
4510 return ret;
4511}
4512EXPORT_SYMBOL(vdec_request_threaded_irq);
4513
4514s32 vdec_request_irq(enum vdec_irq_num num, irq_handler_t handler,
4515 const char *devname, void *dev)
4516{
5b851ff9 4517 pr_debug("vdec_request_irq %p, %s\n", handler, devname);
b9164398
NQ
4518
4519 return vdec_request_threaded_irq(num,
4520 handler,
4521 NULL,/*no thread_fn*/
4522 IRQF_SHARED,
4523 devname,
4524 dev);
4525}
4526EXPORT_SYMBOL(vdec_request_irq);
4527
4528void vdec_free_irq(enum vdec_irq_num num, void *dev)
4529{
4530 if (num >= VDEC_IRQ_MAX) {
4531 pr_err("[%s] request irq error, irq num too big!", __func__);
4532 return;
4533 }
b9164398 4534 /*
e0614bf7 4535 *assume amrisc is stopped already and there is no mailbox interrupt
b9164398
NQ
4536 * when we reset pointers here.
4537 */
4538 vdec_core->isr_context[num].dev_isr = NULL;
4539 vdec_core->isr_context[num].dev_threaded_isr = NULL;
4540 vdec_core->isr_context[num].dev_id = NULL;
5f3fbfb7 4541 synchronize_irq(vdec_core->isr_context[num].irq);
b9164398
NQ
4542}
4543EXPORT_SYMBOL(vdec_free_irq);
4544
a6c89e96
NQ
4545struct vdec_s *vdec_get_default_vdec_for_userdata(void)
4546{
4547 struct vdec_s *vdec;
4548 struct vdec_s *ret_vdec;
4549 struct vdec_core_s *core = vdec_core;
4550 unsigned long flags;
4551 int id;
4552
4553 flags = vdec_core_lock(vdec_core);
4554
4555 id = 0x10000000;
4556 ret_vdec = NULL;
4557 if (!list_empty(&core->connected_vdec_list)) {
4558 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
4559 if (vdec->id < id) {
4560 id = vdec->id;
4561 ret_vdec = vdec;
4562 }
4563 }
4564 }
4565
4566 vdec_core_unlock(vdec_core, flags);
4567
4568 return ret_vdec;
4569}
4570EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata);
4571
9cc3c918
RZ
4572struct vdec_s *vdec_get_vdec_by_id(int vdec_id)
4573{
4574 struct vdec_s *vdec;
4575 struct vdec_s *ret_vdec;
4576 struct vdec_core_s *core = vdec_core;
4577 unsigned long flags;
4578
4579 flags = vdec_core_lock(vdec_core);
4580
4581 ret_vdec = NULL;
4582 if (!list_empty(&core->connected_vdec_list)) {
4583 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
4584 if (vdec->id == vdec_id) {
4585 ret_vdec = vdec;
4586 break;
4587 }
4588 }
4589 }
4590
4591 vdec_core_unlock(vdec_core, flags);
4592
4593 return ret_vdec;
4594}
4595EXPORT_SYMBOL(vdec_get_vdec_by_id);
4596
a6c89e96
NQ
4597int vdec_read_user_data(struct vdec_s *vdec,
4598 struct userdata_param_t *p_userdata_param)
4599{
4600 int ret = 0;
4601
4602 if (!vdec)
4603 vdec = vdec_get_default_vdec_for_userdata();
4604
4605 if (vdec) {
4606 if (vdec->user_data_read)
4607 ret = vdec->user_data_read(vdec, p_userdata_param);
4608 }
4609 return ret;
4610}
4611EXPORT_SYMBOL(vdec_read_user_data);
4612
4613int vdec_wakeup_userdata_poll(struct vdec_s *vdec)
4614{
9cc3c918 4615 if (vdec) {
b78f4cd9 4616 if (vdec->wakeup_userdata_poll)
9cc3c918 4617 vdec->wakeup_userdata_poll(vdec);
b78f4cd9 4618 }
a6c89e96
NQ
4619
4620 return 0;
4621}
4622EXPORT_SYMBOL(vdec_wakeup_userdata_poll);
4623
4624void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
4625{
4626 if (!vdec)
4627 vdec = vdec_get_default_vdec_for_userdata();
4628
4629 if (vdec) {
4630 if (vdec->reset_userdata_fifo)
4631 vdec->reset_userdata_fifo(vdec, bInit);
4632 }
4633}
4634EXPORT_SYMBOL(vdec_reset_userdata_fifo);
4635
3ac450bd 4636void vdec_set_profile_level(struct vdec_s *vdec, u32 profile_idc, u32 level_idc)
4637{
4638 if (vdec) {
4639 vdec->profile_idc = profile_idc;
4640 vdec->level_idc = level_idc;
4641 }
4642}
4643EXPORT_SYMBOL(vdec_set_profile_level);
4644
bba22b6d 4645#ifdef VDEC_FCC_SUPPORT
4646int vdec_wakeup_fcc_poll(struct vdec_s *vdec)
4647{
4648 if (vdec) {
4649 if (vdec->wakeup_fcc_poll)
4650 vdec->wakeup_fcc_poll(vdec);
4651 }
4652
4653 return 0;
4654}
4655EXPORT_SYMBOL(vdec_wakeup_fcc_poll);
4656
4657int vdec_has_get_fcc_new_msg(struct vdec_s *vdec)
4658{
4659 int ret = 1;
4660
4661 if (vdec == NULL) {
4662 pr_info("Error, invalid vdec instance!\n");
4663 return 0;
4664 }
4665
4666 if (input_stream_based(vdec)) {
4667 if (vdec->fcc_mode == FCC_DISCARD_MODE &&
4668 vdec->fcc_status == STATUS_BUTT) {
4669 ret = 1;
4670 vdec->fcc_status = AGAIN_STATUS;
4671 } else if (vdec->fcc_mode == FCC_DEC_MODE &&
4672 vdec->fcc_status != SWITCH_DONE_STATUS) {
4673 ret = 1;
4674
4675 if (wait_event_interruptible_timeout(vdec->jump_back_wq, vdec->jump_back_done | vdec->jump_back_error,
4676 HZ / 2) <= 0) {
4677 pr_info("[%d][FCC]: Error! Wait jump back wp timeout 500ms!\n",
4678 vdec->id);
4679 vdec->fcc_status = SWITCH_DONE_STATUS;
4680 } else {
4681 if (fcc_debug_enable())
4682 pr_info("[%d][FCC]: jump_back_done = %d\n",
4683 vdec->id, vdec->jump_back_done);
4684 if (vdec->jump_back_done) {
4685 vdec->fcc_status = JUMP_BACK_STATUS;
4686 vdec->jump_back_done = 0;
4687 } else {
4688 vdec->fcc_status = SWITCH_DONE_STATUS;
4689 vdec->jump_back_error = 0;
4690 }
4691 }
4692
4693 if (fcc_debug_enable())
4694 pr_info("[%d][FCC]: It is DEC mode now! fcc_status: %d\n",
4695 vdec->id, vdec->fcc_status);
4696 } else if (vdec->fcc_mode == FCC_DISCARD_MODE &&
4697 !vdec->fcc_new_msg) {
4698 if (vdec->fcc_status == WAIT_MSG_STATUS) {
4699 if (fcc_debug_enable())
4700 pr_info("[%d][FCC]: Wait msg!\n", vdec->id);
4701 ret = 0;
4702 } else {
4703 if (fcc_debug_enable())
4704 pr_info("[%d][FCC]: Continue to find header!\n", vdec->id);
4705 ret = 1;
4706 }
4707 } else if (vdec->fcc_new_msg) {
4708 if (fcc_debug_enable())
4709 pr_info("[%d][FCC]: Got discard msg!\n", vdec->id);
4710 ret = 1;
4711 vdec->fcc_new_msg = 0;
4712 if (vdec->fcc_mode == FCC_DISCARD_MODE) {
4713 vdec->fcc_status = DISCARD_STATUS;
4714 }
4715 }
4716 }
4717
4718 return ret;
4719}
4720EXPORT_SYMBOL(vdec_has_get_fcc_new_msg);
4721
4722int fcc_debug_enable(void)
4723{
4724 return fcc_debug;
4725}
4726EXPORT_SYMBOL(fcc_debug_enable);
4727
4728static void vdec_fcc_jump_back(struct vdec_s *vdec)
4729{
4730 u32 cur_rp, set_rp;
4731 struct vdec_input_s *input = &vdec->input;
4732
4733 if (fcc_debug_enable())
4734 pr_info("[%d][FCC]: fcc_mode = %d fcc_status = %d\n",
4735 vdec->id, vdec->fcc_mode, vdec->fcc_status);
4736
4737 if (input->target == VDEC_INPUT_TARGET_VLD) {
4738 if (vdec->fcc_mode == FCC_DEC_MODE &&
4739 vdec->fcc_status == JUMP_BACK_STATUS) {
4740 set_rp = vdec->jump_back_rp;
4741 cur_rp =READ_VREG(VLD_MEM_VIFIFO_RP);
4742 input->stream_cookie = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
4743 if (cur_rp < set_rp) {
4744 if (fcc_debug_enable())
4745 pr_info("[%d][FCC]: Packet is wrapped! VLD_MEM_VIFIFO_WRAP_COUNT = %d\n",
4746 vdec->id, input->stream_cookie);
4747 input->stream_cookie = (input->stream_cookie - 1) < 0 ?
4748 0 : input->stream_cookie - 1;
4749 }
4750
4751 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, set_rp);
4752 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
4753 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
4754
4755 WRITE_VREG(VLD_MEM_SWAP_ADDR,
4756 input->swap_page_phys);
4757 WRITE_VREG(VLD_MEM_SWAP_CTL, 3);
4758 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
4759 ;
4760 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
4761 vdec->fcc_status = SWITCH_DONE_STATUS;
4762 if (fcc_debug_enable()) {
4763 pr_info("[%d][FCC]:Current VLD_MEM_VIFIFO_WRAP_COUNT = %d cur_rp = %x set_rp = %x\n",
4764 vdec->id, input->stream_cookie, cur_rp, set_rp);
4765 }
4766 }
4767 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
4768 if (vdec->fcc_mode == FCC_DEC_MODE &&
4769 vdec->fcc_status == JUMP_BACK_STATUS) {
4770 set_rp = vdec->jump_back_rp;
4771 cur_rp = READ_VREG(HEVC_STREAM_RD_PTR);
4772 if (cur_rp < set_rp) {
4773 input->stream_cookie = input->stream_cookie + set_rp - cur_rp - vdec->input.size;
4774 } else {
4775 input->stream_cookie = input->stream_cookie - cur_rp + set_rp;
4776 }
4777
4778 WRITE_VREG(HEVC_STREAM_RD_PTR, set_rp);
4779 vdec->fcc_status = SWITCH_DONE_STATUS;
4780
4781 WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
4782 input->swap_page_phys);
4783 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 3);
4784
4785 while (READ_VREG(HEVC_STREAM_SWAP_CTRL)
4786 & (1<<7))
4787 ;
4788 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
4789 }
4790 }
4791
4792 return;
4793}
4794#endif
4795
b9164398
NQ
4796static int dump_mode;
4797static ssize_t dump_risc_mem_store(struct class *class,
4798 struct class_attribute *attr,
4799 const char *buf, size_t size)/*set*/
4800{
e0614bf7 4801 unsigned int val;
b9164398
NQ
4802 ssize_t ret;
4803 char dump_mode_str[4] = "PRL";
4804
4805 /*ret = sscanf(buf, "%d", &val);*/
4806 ret = kstrtoint(buf, 0, &val);
4807
4808 if (ret != 0)
4809 return -EINVAL;
4810 dump_mode = val & 0x3;
4811 pr_info("set dump mode to %d,%c_mem\n",
4812 dump_mode, dump_mode_str[dump_mode]);
4813 return size;
4814}
4815static u32 read_amrisc_reg(int reg)
4816{
4817 WRITE_VREG(0x31b, reg);
4818 return READ_VREG(0x31c);
4819}
4820
4821static void dump_pmem(void)
4822{
4823 int i;
4824
4825 WRITE_VREG(0x301, 0x8000);
4826 WRITE_VREG(0x31d, 0);
4827 pr_info("start dump amrisc pmem of risc\n");
4828 for (i = 0; i < 0xfff; i++) {
4829 /*same as .o format*/
4830 pr_info("%08x // 0x%04x:\n", read_amrisc_reg(i), i);
4831 }
4832}
4833
4834static void dump_lmem(void)
4835{
4836 int i;
4837
4838 WRITE_VREG(0x301, 0x8000);
4839 WRITE_VREG(0x31d, 2);
4840 pr_info("start dump amrisc lmem\n");
4841 for (i = 0; i < 0x3ff; i++) {
4842 /*same as */
4843 pr_info("[%04x] = 0x%08x:\n", i, read_amrisc_reg(i));
4844 }
4845}
4846
4847static ssize_t dump_risc_mem_show(struct class *class,
4848 struct class_attribute *attr, char *buf)
4849{
4850 char *pbuf = buf;
4851 int ret;
4852
63e810c0 4853 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
4854 mutex_lock(&vdec_mutex);
4855 if (!vdec_on(VDEC_1)) {
4856 mutex_unlock(&vdec_mutex);
4857 pbuf += sprintf(pbuf, "amrisc is power off\n");
4858 ret = pbuf - buf;
4859 return ret;
4860 }
63e810c0 4861 } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4862 /*TODO:M6 define */
4863 /*
4864 * switch_mod_gate_by_type(MOD_VDEC, 1);
4865 */
4866 amports_switch_gate("vdec", 1);
4867 }
4868 /*start do**/
4869 switch (dump_mode) {
4870 case 0:
4871 dump_pmem();
4872 break;
4873 case 2:
4874 dump_lmem();
4875 break;
4876 default:
4877 break;
4878 }
4879
4880 /*done*/
63e810c0 4881 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
b9164398 4882 mutex_unlock(&vdec_mutex);
63e810c0 4883 else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4884 /*TODO:M6 define */
4885 /*
4886 * switch_mod_gate_by_type(MOD_VDEC, 0);
4887 */
4888 amports_switch_gate("vdec", 0);
4889 }
4890 return sprintf(buf, "done\n");
4891}
4892
4893static ssize_t core_show(struct class *class, struct class_attribute *attr,
4894 char *buf)
4895{
4896 struct vdec_core_s *core = vdec_core;
4897 char *pbuf = buf;
2743b7c1 4898 unsigned long flags = vdec_core_lock(vdec_core);
b9164398
NQ
4899
4900 if (list_empty(&core->connected_vdec_list))
4901 pbuf += sprintf(pbuf, "connected vdec list empty\n");
4902 else {
4903 struct vdec_s *vdec;
4904
a6c89e96
NQ
4905 pbuf += sprintf(pbuf,
4906 " Core: last_sched %p, sched_mask %lx\n",
05afa03d 4907 core->last_vdec,
a6c89e96
NQ
4908 core->sched_mask);
4909
b9164398
NQ
4910 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
4911 pbuf += sprintf(pbuf,
a6c89e96 4912 "\tvdec.%d (%p (%s)), status = %s,\ttype = %s, \tactive_mask = %lx\n",
fe96802b
NQ
4913 vdec->id,
4914 vdec,
4915 vdec_device_name[vdec->format * 2],
b9164398 4916 vdec_status_str(vdec),
a6c89e96
NQ
4917 vdec_type_str(vdec),
4918 vdec->active_mask);
b9164398
NQ
4919 }
4920 }
4921
2743b7c1 4922 vdec_core_unlock(vdec_core, flags);
b9164398
NQ
4923 return pbuf - buf;
4924}
4925
fe96802b
NQ
4926static ssize_t vdec_status_show(struct class *class,
4927 struct class_attribute *attr, char *buf)
4928{
4929 char *pbuf = buf;
4930 struct vdec_s *vdec;
4931 struct vdec_info vs;
4932 unsigned char vdec_num = 0;
4933 struct vdec_core_s *core = vdec_core;
4934 unsigned long flags = vdec_core_lock(vdec_core);
4935
4936 if (list_empty(&core->connected_vdec_list)) {
4937 pbuf += sprintf(pbuf, "No vdec.\n");
4938 goto out;
4939 }
4940
4941 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
9b670a2d 4942 if ((vdec->status == VDEC_STATUS_CONNECTED
4943 || vdec->status == VDEC_STATUS_ACTIVE)) {
fe96802b
NQ
4944 memset(&vs, 0, sizeof(vs));
4945 if (vdec_status(vdec, &vs)) {
4946 pbuf += sprintf(pbuf, "err.\n");
4947 goto out;
4948 }
4949 pbuf += sprintf(pbuf,
4950 "vdec channel %u statistics:\n",
4951 vdec_num);
4952 pbuf += sprintf(pbuf,
4953 "%13s : %s\n", "device name",
4954 vs.vdec_name);
4955 pbuf += sprintf(pbuf,
4956 "%13s : %u\n", "frame width",
4957 vs.frame_width);
4958 pbuf += sprintf(pbuf,
4959 "%13s : %u\n", "frame height",
4960 vs.frame_height);
4961 pbuf += sprintf(pbuf,
4962 "%13s : %u %s\n", "frame rate",
4963 vs.frame_rate, "fps");
4964 pbuf += sprintf(pbuf,
4965 "%13s : %u %s\n", "bit rate",
4966 vs.bit_rate / 1024 * 8, "kbps");
4967 pbuf += sprintf(pbuf,
4968 "%13s : %u\n", "status",
4969 vs.status);
4970 pbuf += sprintf(pbuf,
4971 "%13s : %u\n", "frame dur",
4972 vs.frame_dur);
4973 pbuf += sprintf(pbuf,
4974 "%13s : %u %s\n", "frame data",
4975 vs.frame_data / 1024, "KB");
4976 pbuf += sprintf(pbuf,
4977 "%13s : %u\n", "frame count",
4978 vs.frame_count);
4979 pbuf += sprintf(pbuf,
4980 "%13s : %u\n", "drop count",
4981 vs.drop_frame_count);
4982 pbuf += sprintf(pbuf,
4983 "%13s : %u\n", "fra err count",
4984 vs.error_frame_count);
4985 pbuf += sprintf(pbuf,
4986 "%13s : %u\n", "hw err count",
4987 vs.error_count);
4988 pbuf += sprintf(pbuf,
500f0559 4989 "%13s : %llu %s\n", "total data",
fe96802b 4990 vs.total_data / 1024, "KB");
aa5b19d5 4991 pbuf += sprintf(pbuf,
500f0559 4992 "%13s : %x\n\n", "ratio_control",
aa5b19d5 4993 vs.ratio_control);
fe96802b
NQ
4994
4995 vdec_num++;
4996 }
4997 }
4998out:
4999 vdec_core_unlock(vdec_core, flags);
5000 return pbuf - buf;
5001}
5002
5003static ssize_t dump_vdec_blocks_show(struct class *class,
5004 struct class_attribute *attr, char *buf)
5005{
5006 struct vdec_core_s *core = vdec_core;
5007 char *pbuf = buf;
b2e59ce1 5008 unsigned long flags = vdec_core_lock(vdec_core);
fe96802b
NQ
5009
5010 if (list_empty(&core->connected_vdec_list))
5011 pbuf += sprintf(pbuf, "connected vdec list empty\n");
5012 else {
5013 struct vdec_s *vdec;
5014 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
5015 pbuf += vdec_input_dump_blocks(&vdec->input,
5016 pbuf, PAGE_SIZE - (pbuf - buf));
5017 }
5018 }
b2e59ce1 5019 vdec_core_unlock(vdec_core, flags);
fe96802b
NQ
5020
5021 return pbuf - buf;
5022}
5023static ssize_t dump_vdec_chunks_show(struct class *class,
5024 struct class_attribute *attr, char *buf)
5025{
5026 struct vdec_core_s *core = vdec_core;
5027 char *pbuf = buf;
b2e59ce1 5028 unsigned long flags = vdec_core_lock(vdec_core);
fe96802b
NQ
5029
5030 if (list_empty(&core->connected_vdec_list))
5031 pbuf += sprintf(pbuf, "connected vdec list empty\n");
5032 else {
5033 struct vdec_s *vdec;
5034 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
627825a3 5035 pbuf += vdec_input_dump_chunks(vdec->id, &vdec->input,
fe96802b
NQ
5036 pbuf, PAGE_SIZE - (pbuf - buf));
5037 }
5038 }
b2e59ce1 5039 vdec_core_unlock(vdec_core, flags);
fe96802b
NQ
5040
5041 return pbuf - buf;
5042}
5043
fe96802b
NQ
5044static ssize_t dump_decoder_state_show(struct class *class,
5045 struct class_attribute *attr, char *buf)
5046{
5047 char *pbuf = buf;
5048 struct vdec_s *vdec;
5049 struct vdec_core_s *core = vdec_core;
5050 unsigned long flags = vdec_core_lock(vdec_core);
5051
5052 if (list_empty(&core->connected_vdec_list)) {
5053 pbuf += sprintf(pbuf, "No vdec.\n");
5054 } else {
5055 list_for_each_entry(vdec,
5056 &core->connected_vdec_list, list) {
5057 if ((vdec->status == VDEC_STATUS_CONNECTED
5058 || vdec->status == VDEC_STATUS_ACTIVE)
5059 && vdec->dump_state)
5060 vdec->dump_state(vdec);
5061 }
5062 }
5063 vdec_core_unlock(vdec_core, flags);
5064
5065 return pbuf - buf;
5066}
d481db31 5067
97fe3d16
PY
5068static ssize_t dump_fps_show(struct class *class,
5069 struct class_attribute *attr, char *buf)
5070{
5071 char *pbuf = buf;
5072 struct vdec_core_s *core = vdec_core;
5073 int i;
5074
5075 unsigned long flags = vdec_fps_lock(vdec_core);
5076 for (i = 0; i < MAX_INSTANCE_MUN; i++)
5077 pbuf += sprintf(pbuf, "%d ", core->decode_fps[i].fps);
5078
5079 pbuf += sprintf(pbuf, "\n");
5080 vdec_fps_unlock(vdec_core, flags);
5081
5082 return pbuf - buf;
5083}
5084
3ac450bd 5085static char * parser_h264_profile(char *pbuf, struct vdec_s *vdec)
5086{
5087 switch (vdec->profile_idc) {
5088 case 66:
5089 pbuf += sprintf(pbuf, "%d: Baseline Profile(%u)\n",
5090 vdec->id, vdec->profile_idc);
5091 break;
5092 case 77:
5093 pbuf += sprintf(pbuf, "%d: Main Profile(%u)\n",
5094 vdec->id, vdec->profile_idc);
5095 break;
5096 case 88:
5097 pbuf += sprintf(pbuf, "%d: Extended Profile(%u)\n",
5098 vdec->id, vdec->profile_idc);
5099 break;
5100 case 100:
5101 pbuf += sprintf(pbuf, "%d: High Profile(%u)\n",
5102 vdec->id, vdec->profile_idc);
5103 break;
5104 case 110:
5105 pbuf += sprintf(pbuf, "%d: High 10 Profile(%u)\n",
5106 vdec->id, vdec->profile_idc);
5107 break;
5108 default:
5109 pbuf += sprintf(pbuf, "%d: Not Support Profile(%u)\n",
5110 vdec->id, vdec->profile_idc);
5111 break;
5112 }
5113
5114 return pbuf;
5115}
5116
5117static char * parser_mpeg2_profile(char *pbuf, struct vdec_s *vdec)
5118{
5119 switch (vdec->profile_idc) {
5120 case 5:
5121 pbuf += sprintf(pbuf, "%d: Simple Profile(%u)\n",
5122 vdec->id, vdec->profile_idc);
5123 break;
5124 case 4:
5125 pbuf += sprintf(pbuf, "%d: Main Profile(%u)\n",
5126 vdec->id, vdec->profile_idc);
5127 break;
5128 case 3:
5129 pbuf += sprintf(pbuf, "%d: SNR Scalable Profile(%u)\n",
5130 vdec->id, vdec->profile_idc);
5131 break;
5132 case 2:
5133 pbuf += sprintf(pbuf, "%d: Airspace Profile(%u)\n",
5134 vdec->id, vdec->profile_idc);
5135 break;
5136 case 1:
5137 pbuf += sprintf(pbuf, "%d: High Profile(%u)\n",
5138 vdec->id, vdec->profile_idc);
5139 break;
5140 default:
5141 pbuf += sprintf(pbuf, "%d: Not Support Profile(%u)\n",
5142 vdec->id, vdec->profile_idc);
5143 break;
5144 }
5145 return pbuf;
5146}
5147
5148static char * parser_mpeg4_profile(char *pbuf, struct vdec_s *vdec)
5149{
5150 switch (vdec->profile_idc) {
5151 case 0:
5152 pbuf += sprintf(pbuf, "%d: Simple Profile(%u)\n",
5153 vdec->id, vdec->profile_idc);
5154 break;
5155 case 1:
5156 pbuf += sprintf(pbuf, "%d: Simple Scalable Profile(%u)\n",
5157 vdec->id, vdec->profile_idc);
5158 break;
5159 case 2:
5160 pbuf += sprintf(pbuf, "%d: Core Profile(%u)\n",
5161 vdec->id, vdec->profile_idc);
5162 break;
5163 case 3:
5164 pbuf += sprintf(pbuf, "%d: Main Profile(%u)\n",
5165 vdec->id, vdec->profile_idc);
5166 break;
5167 case 4:
5168 pbuf += sprintf(pbuf, "%d: N-bit Profile(%u)\n",
5169 vdec->id, vdec->profile_idc);
5170 break;
5171 case 5:
5172 pbuf += sprintf(pbuf, "%d: Scalable Texture Profile(%u)\n",
5173 vdec->id, vdec->profile_idc);
5174 break;
5175 case 6:
5176 if (vdec->profile_idc == 1 || vdec->profile_idc == 2)
5177 pbuf += sprintf(pbuf, "%d: Simple Face Animation Profile(%u)\n",
5178 vdec->id, vdec->profile_idc);
5179 else
5180 pbuf += sprintf(pbuf, "%d: Simple FBA Profile(%u)\n",
5181 vdec->id, vdec->profile_idc);
5182 break;
5183 case 7:
5184 pbuf += sprintf(pbuf, "%d: Basic Animated Texture Profile(%u)\n",
5185 vdec->id, vdec->profile_idc);
5186 break;
5187 case 8:
5188 pbuf += sprintf(pbuf, "%d: Hybrid Profile(%u)\n",
5189 vdec->id, vdec->profile_idc);
5190 break;
5191 case 9:
5192 pbuf += sprintf(pbuf, "%d: Advanced Real Time Simple Profile(%u)\n",
5193 vdec->id, vdec->profile_idc);
5194 break;
5195 case 10:
5196 pbuf += sprintf(pbuf, "%d: Core Scalable Profile(%u)\n",
5197 vdec->id, vdec->profile_idc);
5198 break;
5199 case 11:
5200 pbuf += sprintf(pbuf, "%d: Advanced Coding Efficiency Profile(%u)\n",
5201 vdec->id, vdec->profile_idc);
5202 break;
5203 case 12:
5204 pbuf += sprintf(pbuf, "%d: Advanced Core Profile(%u)\n",
5205 vdec->id, vdec->profile_idc);
5206 break;
5207 case 13:
5208 pbuf += sprintf(pbuf, "%d: Advanced Scalable Texture Profile(%u)\n",
5209 vdec->id, vdec->profile_idc);
5210 break;
5211 case 14:
5212 case 15:
5213 pbuf += sprintf(pbuf, "%d: Advanced Simple Profile(%u)\n",
5214 vdec->id, vdec->profile_idc);
5215 break;
5216 default:
5217 pbuf += sprintf(pbuf, "%d: Not Support Profile(%u)\n",
5218 vdec->id, vdec->profile_idc);
5219 break;
5220 }
5221
5222 return pbuf;
5223}
5224
5225static ssize_t profile_idc_show(struct class *class, struct class_attribute *attr,
5226 char *buf)
5227{
5228 struct vdec_core_s *core = vdec_core;
5229 char *pbuf = buf;
5230 unsigned long flags = vdec_core_lock(vdec_core);
d481db31 5231
3ac450bd 5232 if (list_empty(&core->connected_vdec_list))
5233 pbuf += sprintf(pbuf, "connected vdec list empty\n");
5234 else {
5235 struct vdec_s *vdec;
5236 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
5237 if (vdec->format == 0) {
5238 pbuf = parser_mpeg2_profile(pbuf, vdec);
5239 } else if (vdec->format == 1) {
5240 pbuf = parser_mpeg4_profile(pbuf, vdec);
5241 } else if (vdec->format == 2) {
5242 pbuf = parser_h264_profile(pbuf, vdec);
5243 } else {
5244 pbuf += sprintf(pbuf,
5245 "%d: Not Support\n", vdec->id);
5246 }
5247 }
5248 }
5249
5250 vdec_core_unlock(vdec_core, flags);
5251 return pbuf - buf;
5252}
5253
5254static char * parser_h264_level(char *pbuf, struct vdec_s *vdec)
5255{
5256
5257 pbuf += sprintf(pbuf, "%d: Level %d.%d(%u)\n",
5258 vdec->id, vdec->level_idc/10, vdec->level_idc%10, vdec->level_idc);
5259
5260 return pbuf;
5261}
5262
5263static char * parser_mpeg2_level(char *pbuf, struct vdec_s *vdec)
5264{
5265 switch (vdec->level_idc) {
5266 case 10:
5267 pbuf += sprintf(pbuf, "%d: Low Level(%u)\n",
5268 vdec->id, vdec->level_idc);
5269 break;
5270 case 8:
5271 pbuf += sprintf(pbuf, "%d: Main Level(%u)\n",
5272 vdec->id, vdec->level_idc);
5273 break;
5274 case 6:
5275 pbuf += sprintf(pbuf, "%d: High 1440 Level(%u)\n",
5276 vdec->id, vdec->level_idc);
5277 break;
5278 case 4:
5279 pbuf += sprintf(pbuf, "%d: High Level(%u)\n",
5280 vdec->id, vdec->level_idc);
5281 break;
5282 default:
5283 pbuf += sprintf(pbuf, "%d: Not Support Level(%u)\n",
5284 vdec->id, vdec->level_idc);
5285 break;
5286 }
5287
5288 return pbuf;
5289}
5290
5291static char * parser_mpeg4_level(char *pbuf, struct vdec_s *vdec)
5292{
5293 switch (vdec->level_idc) {
5294 case 1:
5295 pbuf += sprintf(pbuf, "%d: Level 1(%u)\n",
5296 vdec->id, vdec->level_idc);
5297 break;
5298 case 2:
5299 pbuf += sprintf(pbuf, "%d: Level 2(%u)\n",
5300 vdec->id, vdec->level_idc);
5301 break;
5302 case 3:
5303 pbuf += sprintf(pbuf, "%d: Level 3(%u)\n",
5304 vdec->id, vdec->level_idc);
5305 break;
5306 case 4:
5307 pbuf += sprintf(pbuf, "%d: Level 4(%u)\n",
5308 vdec->id, vdec->level_idc);
5309 break;
5310 case 5:
5311 pbuf += sprintf(pbuf, "%d: Level 5(%u)\n",
5312 vdec->id, vdec->level_idc);
5313 break;
5314 default:
5315 pbuf += sprintf(pbuf, "%d: Not Support Level(%u)\n",
5316 vdec->id, vdec->level_idc);
5317 break;
5318 }
5319
5320 return pbuf;
5321}
5322
5323static ssize_t level_idc_show(struct class *class, struct class_attribute *attr,
5324 char *buf)
5325{
5326 struct vdec_core_s *core = vdec_core;
5327 char *pbuf = buf;
5328 unsigned long flags = vdec_core_lock(vdec_core);
5329
5330 if (list_empty(&core->connected_vdec_list))
5331 pbuf += sprintf(pbuf, "connected vdec list empty\n");
5332 else {
5333 struct vdec_s *vdec;
5334 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
5335 if (vdec->format == 0) {
5336 pbuf = parser_mpeg2_level(pbuf, vdec);
5337 } else if (vdec->format == 1) {
5338 pbuf = parser_mpeg4_level(pbuf, vdec);
5339 } else if (vdec->format == 2) {
5340 pbuf = parser_h264_level(pbuf, vdec);
5341 } else {
5342 pbuf += sprintf(pbuf,
5343 "%d: Not Support\n", vdec->id);
5344 }
5345 }
5346 }
5347
5348 vdec_core_unlock(vdec_core, flags);
5349 return pbuf - buf;
5350}
fe96802b 5351
bba22b6d 5352#ifdef VDEC_FCC_SUPPORT
5353static ssize_t store_fcc_debug(struct class *class,
5354 struct class_attribute *attr,
5355 const char *buf, size_t size)
5356{
5357 unsigned int val;
5358 ssize_t ret;
5359
5360 ret = kstrtoint(buf, 0, &val);
5361 if (ret != 0)
5362 return -EINVAL;
5363 fcc_debug = val;
5364 return size;
5365}
5366
5367static ssize_t show_fcc_debug(struct class *class,
5368 struct class_attribute *attr, char *buf)
5369{
5370 return sprintf(buf, "%d\n", fcc_debug);
5371}
5372#endif
5373
b9164398
NQ
5374static struct class_attribute vdec_class_attrs[] = {
5375 __ATTR_RO(amrisc_regs),
5376 __ATTR_RO(dump_trace),
5377 __ATTR_RO(clock_level),
cc41710a 5378 __ATTR(enable_mvdec_info, S_IRUGO | S_IWUSR | S_IWGRP,
5379 enable_mvdec_info_show, enable_mvdec_info_store),
b9164398
NQ
5380 __ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP,
5381 show_poweron_clock_level, store_poweron_clock_level),
5382 __ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP,
5383 dump_risc_mem_show, dump_risc_mem_store),
5384 __ATTR(keep_vdec_mem, S_IRUGO | S_IWUSR | S_IWGRP,
5385 show_keep_vdec_mem, store_keep_vdec_mem),
5386 __ATTR_RO(core),
fe96802b
NQ
5387 __ATTR_RO(vdec_status),
5388 __ATTR_RO(dump_vdec_blocks),
5389 __ATTR_RO(dump_vdec_chunks),
d481db31 5390 __ATTR_RO(dump_decoder_state),
a6c89e96
NQ
5391#ifdef VDEC_DEBUG_SUPPORT
5392 __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP,
5393 show_debug, store_debug),
8458676f 5394#endif
5395#ifdef FRAME_CHECK
5396 __ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP,
5397 dump_yuv_show, dump_yuv_store),
5398 __ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP,
5399 frame_check_show, frame_check_store),
a6c89e96 5400#endif
97fe3d16 5401 __ATTR_RO(dump_fps),
3ac450bd 5402 __ATTR_RO(profile_idc),
5403 __ATTR_RO(level_idc),
4373e91a 5404 __ATTR(vfm_path, S_IRUGO | S_IWUSR | S_IWGRP,
5405 show_vdec_vfm_path, store_vdec_vfm_path),
bba22b6d 5406#ifdef VDEC_FCC_SUPPORT
5407 __ATTR(fcc_debug, S_IRUGO | S_IWUSR | S_IWGRP,
5408 show_fcc_debug, store_fcc_debug),
5409#endif
b9164398
NQ
5410 __ATTR_NULL
5411};
5412
5413static struct class vdec_class = {
5414 .name = "vdec",
5415 .class_attrs = vdec_class_attrs,
5416 };
5417
b9164398
NQ
5418struct device *get_vdec_device(void)
5419{
5420 return &vdec_core->vdec_core_platform_device->dev;
5421}
5422EXPORT_SYMBOL(get_vdec_device);
5423
5424static int vdec_probe(struct platform_device *pdev)
5425{
5426 s32 i, r;
5427
5428 vdec_core = (struct vdec_core_s *)devm_kzalloc(&pdev->dev,
5429 sizeof(struct vdec_core_s), GFP_KERNEL);
5430 if (vdec_core == NULL) {
5431 pr_err("vdec core allocation failed.\n");
5432 return -ENOMEM;
5433 }
5434
5435 atomic_set(&vdec_core->vdec_nr, 0);
5436 sema_init(&vdec_core->sem, 1);
5437
5438 r = class_register(&vdec_class);
5439 if (r) {
5440 pr_info("vdec class create fail.\n");
5441 return r;
5442 }
5443
5444 vdec_core->vdec_core_platform_device = pdev;
5445
5446 platform_set_drvdata(pdev, vdec_core);
5447
5448 for (i = 0; i < VDEC_IRQ_MAX; i++) {
5449 vdec_core->isr_context[i].index = i;
5450 vdec_core->isr_context[i].irq = -1;
5451 }
5452
a6c89e96
NQ
5453 r = vdec_request_threaded_irq(VDEC_IRQ_0, NULL, NULL,
5454 IRQF_ONESHOT, "vdec-0", NULL);
5455 if (r < 0) {
5456 pr_err("vdec interrupt request failed\n");
5457 return r;
5458 }
5459
b9164398
NQ
5460 r = vdec_request_threaded_irq(VDEC_IRQ_1, NULL, NULL,
5461 IRQF_ONESHOT, "vdec-1", NULL);
5462 if (r < 0) {
5463 pr_err("vdec interrupt request failed\n");
5464 return r;
5465 }
a6c89e96 5466#if 0
df841122 5467 if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) {
a6c89e96
NQ
5468 r = vdec_request_threaded_irq(VDEC_IRQ_HEVC_BACK, NULL, NULL,
5469 IRQF_ONESHOT, "vdec-hevc_back", NULL);
5470 if (r < 0) {
5471 pr_err("vdec interrupt request failed\n");
5472 return r;
5473 }
5474 }
5475#endif
b9164398
NQ
5476 r = of_reserved_mem_device_init(&pdev->dev);
5477 if (r == 0)
5478 pr_info("vdec_probe done\n");
5479
5480 vdec_core->cma_dev = &pdev->dev;
5481
63e810c0 5482 if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
5483 /* default to 250MHz */
5484 vdec_clock_hi_enable();
5485 }
5486
63e810c0 5487 if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) {
b9164398
NQ
5488 /* set vdec dmc request to urgent */
5489 WRITE_DMCREG(DMC_AM5_CHAN_CTRL, 0x3f203cf);
5490 }
b9164398
NQ
5491 INIT_LIST_HEAD(&vdec_core->connected_vdec_list);
5492 spin_lock_init(&vdec_core->lock);
05afa03d 5493 spin_lock_init(&vdec_core->canvas_lock);
97fe3d16 5494 spin_lock_init(&vdec_core->fps_lock);
0ed0f572 5495 spin_lock_init(&vdec_core->input_lock);
fe96802b 5496 ida_init(&vdec_core->ida);
b9164398
NQ
5497 vdec_core->thread = kthread_run(vdec_core_thread, vdec_core,
5498 "vdec-core");
5499
158de7c4
HZ
5500 vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",__WQ_LEGACY |
5501 WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work");
5502 /*work queue priority lower than vdec-core.*/
5166ea72
NQ
5503
5504 /* power manager init. */
5505 vdec_core->pm = (struct power_manager_s *)
5506 of_device_get_match_data(&pdev->dev);
5507 if (vdec_core->pm->init) {
5508 r = vdec_core->pm->init(&pdev->dev);
5509 if (r) {
5510 pr_err("vdec power manager init failed\n");
5511 return r;
5512 }
5513 }
5514
b9164398
NQ
5515 return 0;
5516}
5517
5518static int vdec_remove(struct platform_device *pdev)
5519{
5520 int i;
5521
5522 for (i = 0; i < VDEC_IRQ_MAX; i++) {
5523 if (vdec_core->isr_context[i].irq >= 0) {
5524 free_irq(vdec_core->isr_context[i].irq,
5525 &vdec_core->isr_context[i]);
5526 vdec_core->isr_context[i].irq = -1;
5527 vdec_core->isr_context[i].dev_isr = NULL;
5528 vdec_core->isr_context[i].dev_threaded_isr = NULL;
5529 vdec_core->isr_context[i].dev_id = NULL;
5530 }
5531 }
5532
5533 kthread_stop(vdec_core->thread);
5534
fe96802b 5535 destroy_workqueue(vdec_core->vdec_core_wq);
5166ea72
NQ
5536
5537 if (vdec_core->pm->release)
5538 vdec_core->pm->release(&pdev->dev);
5539
b9164398
NQ
5540 class_unregister(&vdec_class);
5541
5542 return 0;
5543}
5544
fe96802b 5545static struct mconfig vdec_configs[] = {
fe96802b
NQ
5546 MC_PU32("debug_trace_num", &debug_trace_num),
5547 MC_PI32("hevc_max_reset_count", &hevc_max_reset_count),
5548 MC_PU32("clk_config", &clk_config),
5549 MC_PI32("step_mode", &step_mode),
5550 MC_PI32("poweron_clock_level", &poweron_clock_level),
5551};
5552static struct mconfig_node vdec_node;
5553
5166ea72
NQ
5554extern const struct of_device_id amlogic_vdec_matches[];
5555
b9164398
NQ
5556static struct platform_driver vdec_driver = {
5557 .probe = vdec_probe,
5558 .remove = vdec_remove,
5559 .driver = {
5560 .name = "vdec",
5166ea72 5561 .of_match_table = amlogic_vdec_matches,
b9164398
NQ
5562 }
5563};
5564
fc199e88 5565static struct codec_profile_t amvdec_common_profile = {
5566 .name = "vdec_common",
5567 .profile = "vdec"
5568};
5569
f811c57d
TG
5570static struct codec_profile_t amvdec_input_profile = {
5571 .name = "vdec_input",
5572 .profile = "drm_framemode"
5573};
5574
b9164398
NQ
5575int vdec_module_init(void)
5576{
5577 if (platform_driver_register(&vdec_driver)) {
5578 pr_info("failed to register vdec module\n");
5579 return -ENODEV;
5580 }
fe96802b
NQ
5581 INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node,
5582 "vdec", vdec_configs, CONFIG_FOR_RW);
fc199e88 5583 vcodec_profile_register(&amvdec_common_profile);
5584
f811c57d 5585 vcodec_profile_register(&amvdec_input_profile);
b9164398
NQ
5586 return 0;
5587}
5588EXPORT_SYMBOL(vdec_module_init);
5589
5590void vdec_module_exit(void)
5591{
5592 platform_driver_unregister(&vdec_driver);
5593}
5594EXPORT_SYMBOL(vdec_module_exit);
5595
5596#if 0
5597static int __init vdec_module_init(void)
5598{
5599 if (platform_driver_register(&vdec_driver)) {
5600 pr_info("failed to register vdec module\n");
5601 return -ENODEV;
5602 }
fe96802b
NQ
5603 INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node,
5604 "vdec", vdec_configs, CONFIG_FOR_RW);
b9164398
NQ
5605 return 0;
5606}
5607
5608static void __exit vdec_module_exit(void)
5609{
5610 platform_driver_unregister(&vdec_driver);
5611}
5612#endif
5613
5614static int vdec_mem_device_init(struct reserved_mem *rmem, struct device *dev)
5615{
b9164398
NQ
5616 vdec_core->cma_dev = dev;
5617
5618 return 0;
5619}
5620
5621static const struct reserved_mem_ops rmem_vdec_ops = {
5622 .device_init = vdec_mem_device_init,
5623};
5624
5625static int __init vdec_mem_setup(struct reserved_mem *rmem)
5626{
5627 rmem->ops = &rmem_vdec_ops;
5628 pr_info("vdec: reserved mem setup\n");
5629
5630 return 0;
5631}
5632
cc41710a 5633
5634void vdec_set_vframe_comm(struct vdec_s *vdec, char *n)
a8f62ee0 5635{
cc41710a 5636 struct vdec_frames_s *mvfrm = vdec->mvfrm;
a8f62ee0 5637
cc41710a 5638 if (!mvfrm)
a8f62ee0 5639 return;
cc41710a 5640
5641 mvfrm->comm.vdec_id = vdec->id;
5642
5643 snprintf(mvfrm->comm.vdec_name, sizeof(mvfrm->comm.vdec_name)-1,
5644 "%s", n);
5645 mvfrm->comm.vdec_type = vdec->type;
5646}
5647EXPORT_SYMBOL(vdec_set_vframe_comm);
5648
833bb93d 5649u32 diff_pts(u32 a, u32 b)
5650{
5651 if (!a || !b)
5652 return 0;
5653 else
5654 return abs(a - b);
5655}
5656
5657/*
5658 * We only use the first 5 frames to calc duration.
5659 * The fifo[0]~fifo[4] means the frame 0 to frame 4.
5660 * we start to calculate the duration from frame 1.
5661 * And the caller guarantees that slot > 0.
5662 */
5663static void cal_dur_from_pts(struct vdec_s *vdec, u32 slot)
5664{
5665#define DURATION_THRESHOD 10
97585804 5666 static u32 must_send = 0, ready = 0;
833bb93d 5667 u32 old = 0, cur, diff;
5668 struct vframe_counter_s *fifo = vdec->mvfrm->fifo_buf;
5669
97585804 5670 if (vdec->mvfrm->wr == 1) {
5671 ready = 0;
5672 must_send = 0;
5673 }
5674
5675 if (must_send == 2)
5676 return ;
833bb93d 5677
97585804 5678 if (ready)
5679 ++must_send;
5680
5681 if ((vdec->format != VFORMAT_H264 && vdec->format != VFORMAT_HEVC) ||
5682 !fifo[slot].pts) {
5683 if (fifo[slot].frame_dur != ready) {
5684 if (must_send)
5685 ready = (ready + fifo[slot].frame_dur) / 2;
5686 else
5687 ready = fifo[slot].frame_dur;
5688 pr_debug("%s inner driver dur%u \n",__func__, ready);
833bb93d 5689 }
97585804 5690 goto end_handle;
833bb93d 5691 }
5692
833bb93d 5693 if (slot == 1) {
5694 cur = diff_pts(fifo[1].pts, fifo[0].pts);
5695 } else {
5696 old = diff_pts(fifo[slot - 1].pts, fifo[slot - 2].pts);
5697 cur = diff_pts(fifo[slot].pts, fifo[slot - 1].pts);
5698 }
5699
5700 diff = abs(cur - old);
5701 if (diff > DURATION_THRESHOD) {
5702 u32 dur, cur2;
5703
5704 cur2 = (cur << 4) / 15;
5705 diff = abs(cur2 - fifo[slot].frame_dur);
5706 if (fifo[slot].frame_dur == 3600)
5707 dur = cur2;
5708 else if (diff < DURATION_THRESHOD || diff > fifo[slot].frame_dur)
5709 dur = fifo[slot].frame_dur;
5710 else
5711 dur = cur2;
5712
97585804 5713 if (ready == dur)
5714 goto end_handle;
833bb93d 5715
97585804 5716 if (must_send)
5717 ready = (ready + dur) / 2;
5718 else
5719 ready = dur;
5720 pr_debug("%s vstatus %u dur%u -> %u, revised %u\n",__func__,fifo[slot].frame_dur, cur,cur2, dur);
833bb93d 5721 if (diff > 10 && slot >= 2)
5722 pr_debug("wr=%u,slot=%u pts %u, %u, %u\n",vdec->mvfrm->wr,slot,
5723 fifo[slot].pts, fifo[slot-1].pts,fifo[slot-2].pts);
97585804 5724 }
833bb93d 5725
97585804 5726end_handle:
5727 if (must_send) {
5728 ++must_send;
5729 vframe_rate_uevent(ready);
833bb93d 5730 }
5731}
5732
cc41710a 5733void vdec_fill_vdec_frame(struct vdec_s *vdec, struct vframe_qos_s *vframe_qos,
5734 struct vdec_info *vinfo,struct vframe_s *vf,
5735 u32 hw_dec_time)
5736{
833bb93d 5737#define MINIMUM_FRAMES 5
cc41710a 5738 u32 i;
5739 struct vframe_counter_s *fifo_buf;
5740 struct vdec_frames_s *mvfrm = vdec->mvfrm;
5741
5742 if (!mvfrm)
a8f62ee0 5743 return;
cc41710a 5744 fifo_buf = mvfrm->fifo_buf;
5745
5746 /* assume fps==60,mv->wr max value can support system running 828 days,
5747 this is enough for us */
5748 i = mvfrm->wr & (NUM_FRAME_VDEC-1); //find the slot num in fifo_buf
5749 mvfrm->fifo_buf[i].decode_time_cost = hw_dec_time;
5750 if (vframe_qos)
5751 memcpy(&fifo_buf[i].qos, vframe_qos, sizeof(struct vframe_qos_s));
5752 if (vinfo) {
5753 memcpy(&fifo_buf[i].frame_width, &vinfo->frame_width,
5754 ((char*)&vinfo->reserved[0] - (char*)&vinfo->frame_width));
4cd99df0 5755 /*copy for ipb report*/
5756 memcpy(&fifo_buf[i].i_decoded_frames, &vinfo->i_decoded_frames,
5757 ((char*)&vinfo->endipb_line[0] - (char*)&vinfo->i_decoded_frames));
5758 fifo_buf[i].av_resynch_counter = timestamp_avsync_counter_get();
cc41710a 5759 }
5760 if (vf) {
5761 fifo_buf[i].vf_type = vf->type;
5762 fifo_buf[i].signal_type = vf->signal_type;
5763 fifo_buf[i].pts = vf->pts;
5764 fifo_buf[i].pts_us64 = vf->pts_us64;
833bb93d 5765
5766 /* Calculate the duration from pts */
5767 if (mvfrm->wr < MINIMUM_FRAMES && mvfrm->wr > 0)
5768 cal_dur_from_pts(vdec, i);
cc41710a 5769 }
5770 mvfrm->wr++;
5771}
5772EXPORT_SYMBOL(vdec_fill_vdec_frame);
5773
85193e3c 5774void vdec_vframe_ready(struct vdec_s *vdec, struct vframe_s *vf) {
85193e3c 5775 if (vdec_secure(vdec)) {
5776 vf->flag |= VFRAME_FLAG_VIDEO_SECURE;
5777 } else {
5778 vf->flag &= ~VFRAME_FLAG_VIDEO_SECURE;
5779 }
5780}
5781EXPORT_SYMBOL(vdec_vframe_ready);
5782
cc41710a 5783/* In this function,if we use copy_to_user, we may encounter sleep,
5784which may block the vdec_fill_vdec_frame,this is not acceptable.
5785So, we should use a tmp buffer(passed by caller) to get the content */
5786u32 vdec_get_frame_vdec(struct vdec_s *vdec, struct vframe_counter_s *tmpbuf)
5787{
5788 u32 toread = 0;
5789 u32 slot_rd;
5790 struct vframe_counter_s *fifo_buf = NULL;
5791 struct vdec_frames_s *mvfrm = NULL;
a8f62ee0 5792
cc41710a 5793 /*
5794 switch (version) {
5795 case version_1:
5796 f1();
5797 case version_2:
5798 f2();
5799 default:
5800 break;
a8f62ee0 5801 }
cc41710a 5802 */
5803
5804 if (!vdec)
5805 return 0;
5806 mvfrm = vdec->mvfrm;
5807 if (!mvfrm)
5808 return 0;
a8f62ee0 5809
cc41710a 5810 fifo_buf = &mvfrm->fifo_buf[0];
a8f62ee0 5811
cc41710a 5812 toread = mvfrm->wr - mvfrm->rd;
5813 if (toread) {
5814 if (toread >= NUM_FRAME_VDEC - QOS_FRAME_NUM) {
5815 /* round the fifo_buf length happens, give QOS_FRAME_NUM for buffer */
5816 mvfrm->rd = mvfrm->wr - (NUM_FRAME_VDEC - QOS_FRAME_NUM);
5817 }
5818
5819 if (toread >= QOS_FRAME_NUM) {
5820 toread = QOS_FRAME_NUM; //by default, we use this num
5821 }
5822
5823 slot_rd = mvfrm->rd &( NUM_FRAME_VDEC-1); //In this case it equals to x%y
5824 if (slot_rd + toread <= NUM_FRAME_VDEC) {
5825 memcpy(tmpbuf, &fifo_buf[slot_rd], toread*sizeof(struct vframe_counter_s));
5826 } else {
5827 u32 exeed;
5828 exeed = slot_rd + toread - NUM_FRAME_VDEC;
5829 memcpy(tmpbuf, &fifo_buf[slot_rd], (NUM_FRAME_VDEC - slot_rd)*sizeof(struct vframe_counter_s));
5830 memcpy(&tmpbuf[NUM_FRAME_VDEC-slot_rd], &fifo_buf[0], exeed*sizeof(struct vframe_counter_s));
5831 }
5832
5833 mvfrm->rd += toread;
a8f62ee0 5834 }
cc41710a 5835 return toread;
a8f62ee0 5836}
cc41710a 5837EXPORT_SYMBOL(vdec_get_frame_vdec);
a8f62ee0 5838
bc28d20f 5839void vdec_set_vld_wp(struct vdec_s *vdec, u32 wp)
5840{
5841 if (vdec_single(vdec)) {
5842 WRITE_VREG(VLD_MEM_VIFIFO_WP, wp);
5843 }
5844}
5845EXPORT_SYMBOL(vdec_set_vld_wp);
5846
5847void vdec_config_vld_reg(struct vdec_s *vdec, u32 addr, u32 size)
5848{
5849 if (vdec_single(vdec)) {
5850 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
5851 /* reset VLD before setting all pointers */
5852 WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, 0);
5853 /*TODO: only > m6*/
5854 WRITE_VREG(DOS_SW_RESET0, (1 << 4));
5855 WRITE_VREG(DOS_SW_RESET0, 0);
5856
5857
5858 WRITE_VREG(POWER_CTL_VLD, 1 << 4);
5859
5860 WRITE_VREG(VLD_MEM_VIFIFO_START_PTR,
5861 addr);
5862 WRITE_VREG(VLD_MEM_VIFIFO_END_PTR,
5863 addr + size - 8);
5864 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
5865 addr);
5866
5867 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
5868 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
5869
5870 /* set to manual mode */
5871 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
5872 WRITE_VREG(VLD_MEM_VIFIFO_WP, addr);
5873
5874 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3);
5875 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
5876
5877 /* enable */
5878 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
5879 (0x11 << 16) | (1<<10) | (1 << 1) | (1 << 2));
5880 SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL,
5881 7 << 3);
5882 }
5883}
5884EXPORT_SYMBOL(vdec_config_vld_reg);
5885
b9164398 5886RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup);
a6c89e96
NQ
5887/*
5888uint force_hevc_clock_cntl;
5889EXPORT_SYMBOL(force_hevc_clock_cntl);
5890
5891module_param(force_hevc_clock_cntl, uint, 0664);
5892*/
158de7c4 5893module_param(debug, uint, 0664);
b9164398
NQ
5894module_param(debug_trace_num, uint, 0664);
5895module_param(hevc_max_reset_count, int, 0664);
5896module_param(clk_config, uint, 0664);
5897module_param(step_mode, int, 0664);
a6c89e96 5898module_param(debugflags, int, 0664);
05afa03d 5899module_param(parallel_decode, int, 0664);
97fe3d16
PY
5900module_param(fps_detection, int, 0664);
5901module_param(fps_clear, int, 0664);
42173624 5902module_param(force_nosecure_even_drm, int, 0664);
9457f9af 5903module_param(disable_switch_single_to_mult, int, 0664);
fe96802b 5904
a8f62ee0
RZ
5905module_param(frameinfo_flag, int, 0664);
5906MODULE_PARM_DESC(frameinfo_flag,
5907 "\n frameinfo_flag\n");
e8335f32 5908module_param(v4lvideo_add_di, int, 0664);
5909MODULE_PARM_DESC(v4lvideo_add_di,
5910 "\n v4lvideo_add_di\n");
5911
5912module_param(max_di_instance, int, 0664);
5913MODULE_PARM_DESC(max_di_instance,
5914 "\n max_di_instance\n");
5915
b39d60ee 5916module_param(debug_vdetect, int, 0664);
5917MODULE_PARM_DESC(debug_vdetect, "\n debug_vdetect\n");
5918
bba22b6d 5919#ifdef VDEC_FCC_SUPPORT
5920module_param(fcc_debug, int, 0664);
5921MODULE_PARM_DESC(fcc_debug, "\n fcc_debug\n");
5922#endif
5923
d631e9c2
HZ
5924module_param(enable_stream_mode_multi_dec, int, 0664);
5925EXPORT_SYMBOL(enable_stream_mode_multi_dec);
5926MODULE_PARM_DESC(enable_stream_mode_multi_dec,
5927 "\n enable multi-decoding on stream mode. \n");
b9164398
NQ
5928/*
5929*module_init(vdec_module_init);
5930*module_exit(vdec_module_exit);
5931*/
fe96802b
NQ
5932#define CREATE_TRACE_POINTS
5933#include "vdec_trace.h"
b9164398
NQ
5934MODULE_DESCRIPTION("AMLOGIC vdec driver");
5935MODULE_LICENSE("GPL");
5936MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");