vh265: pic crop info mistmatch issue[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>
36#include <linux/amlogic/media/vfm/vfm_ext.h>
a6c89e96
NQ
37/*for VDEC_DEBUG_SUPPORT*/
38#include <linux/time.h>
b9164398
NQ
39
40#include <linux/amlogic/media/utils/vdec_reg.h>
41#include "vdec.h"
fe96802b
NQ
42#include "vdec_trace.h"
43#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
44#include "vdec_profile.h"
45#endif
46#include <linux/of.h>
47#include <linux/of_fdt.h>
48#include <linux/libfdt_env.h>
49#include <linux/of_reserved_mem.h>
50#include <linux/dma-contiguous.h>
51#include <linux/cma.h>
52#include <linux/module.h>
53#include <linux/slab.h>
54#include <linux/dma-mapping.h>
55#include <linux/dma-contiguous.h>
56#include "../../../stream_input/amports/amports_priv.h"
57
58#include <linux/amlogic/media/utils/amports_config.h>
59#include "../utils/amvdec.h"
60#include "vdec_input.h"
61
62#include "../../../common/media_clock/clk/clk.h"
63#include <linux/reset.h>
fe96802b 64#include <linux/amlogic/cpu_version.h>
b9164398
NQ
65#include <linux/amlogic/media/codec_mm/codec_mm.h>
66#include <linux/amlogic/media/video_sink/video_keeper.h>
fe96802b
NQ
67#include <linux/amlogic/media/codec_mm/configs.h>
68#include <linux/amlogic/media/frame_sync/ptsserv.h>
69#include "secprot.h"
63e810c0 70#include "../../../common/chips/decoder_cpu_ver_info.h"
8458676f 71#include "frame_check.h"
b9164398
NQ
72
73static DEFINE_MUTEX(vdec_mutex);
74
75#define MC_SIZE (4096 * 4)
76#define CMA_ALLOC_SIZE SZ_64M
77#define MEM_NAME "vdec_prealloc"
78static int inited_vcodec_num;
976f3376 79#define jiffies_ms div64_u64(get_jiffies_64() * 1000, HZ)
b9164398
NQ
80static int poweron_clock_level;
81static int keep_vdec_mem;
82static unsigned int debug_trace_num = 16 * 20;
83static int step_mode;
84static unsigned int clk_config;
158de7c4
HZ
85/*
86 &1: sched_priority to MAX_RT_PRIO -1.
87 &2: always reload firmware.
be862a73 88 &4: vdec canvas debug enable
158de7c4
HZ
89 */
90static unsigned int debug;
8247f369 91
b9164398 92static int hevc_max_reset_count;
fe96802b 93
28e318df 94static int no_powerdown;
05afa03d 95static int parallel_decode = 1;
97fe3d16
PY
96static int fps_detection;
97static int fps_clear;
b9164398
NQ
98static DEFINE_SPINLOCK(vdec_spin_lock);
99
100#define HEVC_TEST_LIMIT 100
101#define GXBB_REV_A_MINOR 0xA
102
05afa03d
PY
103#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
104
b9164398
NQ
105struct am_reg {
106 char *name;
107 int offset;
108};
109
110struct vdec_isr_context_s {
111 int index;
112 int irq;
113 irq_handler_t dev_isr;
114 irq_handler_t dev_threaded_isr;
115 void *dev_id;
a6c89e96 116 struct vdec_s *vdec;
b9164398
NQ
117};
118
97fe3d16
PY
119struct decode_fps_s {
120 u32 frame_count;
121 u64 start_timestamp;
122 u64 last_timestamp;
123 u32 fps;
124};
125
b9164398
NQ
126struct vdec_core_s {
127 struct list_head connected_vdec_list;
128 spinlock_t lock;
05afa03d 129 spinlock_t canvas_lock;
97fe3d16 130 spinlock_t fps_lock;
fe96802b 131 struct ida ida;
b9164398
NQ
132 atomic_t vdec_nr;
133 struct vdec_s *vfm_vdec;
134 struct vdec_s *active_vdec;
05afa03d 135 struct vdec_s *active_hevc;
fe96802b 136 struct vdec_s *hint_fr_vdec;
b9164398
NQ
137 struct platform_device *vdec_core_platform_device;
138 struct device *cma_dev;
b9164398
NQ
139 struct semaphore sem;
140 struct task_struct *thread;
fe96802b 141 struct workqueue_struct *vdec_core_wq;
b9164398 142
a6c89e96 143 unsigned long sched_mask;
b9164398
NQ
144 struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX];
145 int power_ref_count[VDEC_MAX];
05afa03d
PY
146 struct vdec_s *last_vdec;
147 int parallel_dec;
148 unsigned long power_ref_mask;
149 int vdec_combine_flag;
97fe3d16 150 struct decode_fps_s decode_fps[MAX_INSTANCE_MUN];
05afa03d
PY
151};
152
153struct canvas_status_s {
154 int type;
155 int canvas_used_flag;
156 int id;
b9164398
NQ
157};
158
05afa03d 159
b9164398
NQ
160static struct vdec_core_s *vdec_core;
161
fe96802b
NQ
162static const char * const vdec_status_string[] = {
163 "VDEC_STATUS_UNINITIALIZED",
164 "VDEC_STATUS_DISCONNECTED",
165 "VDEC_STATUS_CONNECTED",
166 "VDEC_STATUS_ACTIVE"
167};
168
169static int debugflags;
170
05afa03d
PY
171static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1];
172
173
fe96802b
NQ
174int vdec_get_debug_flags(void)
175{
176 return debugflags;
177}
178EXPORT_SYMBOL(vdec_get_debug_flags);
179
180unsigned char is_mult_inc(unsigned int type)
181{
182 unsigned char ret = 0;
183 if (vdec_get_debug_flags() & 0xf000)
184 ret = (vdec_get_debug_flags() & 0x1000)
185 ? 1 : 0;
186 else if (type & PORT_TYPE_DECODER_SCHED)
187 ret = 1;
188 return ret;
189}
190EXPORT_SYMBOL(is_mult_inc);
191
a6c89e96
NQ
192static const bool cores_with_input[VDEC_MAX] = {
193 true, /* VDEC_1 */
194 false, /* VDEC_HCODEC */
195 false, /* VDEC_2 */
196 true, /* VDEC_HEVC / VDEC_HEVC_FRONT */
197 false, /* VDEC_HEVC_BACK */
198};
199
200static const int cores_int[VDEC_MAX] = {
201 VDEC_IRQ_1,
202 VDEC_IRQ_2,
203 VDEC_IRQ_0,
204 VDEC_IRQ_0,
205 VDEC_IRQ_HEVC_BACK
206};
207
05afa03d
PY
208unsigned long vdec_canvas_lock(struct vdec_core_s *core)
209{
210 unsigned long flags;
211 spin_lock_irqsave(&core->canvas_lock, flags);
212
213 return flags;
214}
215
216void vdec_canvas_unlock(struct vdec_core_s *core, unsigned long flags)
217{
218 spin_unlock_irqrestore(&core->canvas_lock, flags);
219}
220
97fe3d16
PY
221unsigned long vdec_fps_lock(struct vdec_core_s *core)
222{
223 unsigned long flags;
224 spin_lock_irqsave(&core->fps_lock, flags);
225
226 return flags;
227}
228
229void vdec_fps_unlock(struct vdec_core_s *core, unsigned long flags)
230{
231 spin_unlock_irqrestore(&core->fps_lock, flags);
232}
05afa03d 233
b9164398
NQ
234unsigned long vdec_core_lock(struct vdec_core_s *core)
235{
236 unsigned long flags;
237
238 spin_lock_irqsave(&core->lock, flags);
239
240 return flags;
241}
242
243void vdec_core_unlock(struct vdec_core_s *core, unsigned long flags)
244{
245 spin_unlock_irqrestore(&core->lock, flags);
246}
247
97fe3d16
PY
248static u64 vdec_get_us_time_system(void)
249{
250 struct timeval tv;
251
252 do_gettimeofday(&tv);
253
254 return div64_u64(timeval_to_ns(&tv), 1000);
255}
256
257static void vdec_fps_clear(int id)
258{
259 if (id >= MAX_INSTANCE_MUN)
260 return;
261
262 vdec_core->decode_fps[id].frame_count = 0;
263 vdec_core->decode_fps[id].start_timestamp = 0;
264 vdec_core->decode_fps[id].last_timestamp = 0;
265 vdec_core->decode_fps[id].fps = 0;
266}
267
268static void vdec_fps_clearall(void)
269{
270 int i;
271
272 for (i = 0; i < MAX_INSTANCE_MUN; i++) {
273 vdec_core->decode_fps[i].frame_count = 0;
274 vdec_core->decode_fps[i].start_timestamp = 0;
275 vdec_core->decode_fps[i].last_timestamp = 0;
276 vdec_core->decode_fps[i].fps = 0;
277 }
278}
279
280static void vdec_fps_detec(int id)
281{
282 unsigned long flags;
283
284 if (fps_detection == 0)
285 return;
286
287 if (id >= MAX_INSTANCE_MUN)
288 return;
289
290 flags = vdec_fps_lock(vdec_core);
291
292 if (fps_clear == 1) {
293 vdec_fps_clearall();
294 fps_clear = 0;
295 }
296
297 vdec_core->decode_fps[id].frame_count++;
298 if (vdec_core->decode_fps[id].frame_count == 1) {
299 vdec_core->decode_fps[id].start_timestamp =
300 vdec_get_us_time_system();
301 vdec_core->decode_fps[id].last_timestamp =
302 vdec_core->decode_fps[id].start_timestamp;
303 } else {
304 vdec_core->decode_fps[id].last_timestamp =
305 vdec_get_us_time_system();
306 vdec_core->decode_fps[id].fps =
307 (u32)div_u64(((u64)(vdec_core->decode_fps[id].frame_count) *
308 10000000000),
309 (vdec_core->decode_fps[id].last_timestamp -
310 vdec_core->decode_fps[id].start_timestamp));
311 }
312 vdec_fps_unlock(vdec_core, flags);
313}
314
315
316
b9164398
NQ
317static int get_canvas(unsigned int index, unsigned int base)
318{
319 int start;
320 int canvas_index = index * base;
a35da9f0 321 int ret;
b9164398
NQ
322
323 if ((base > 4) || (base == 0))
324 return -1;
325
326 if ((AMVDEC_CANVAS_START_INDEX + canvas_index + base - 1)
327 <= AMVDEC_CANVAS_MAX1) {
328 start = AMVDEC_CANVAS_START_INDEX + base * index;
329 } else {
330 canvas_index -= (AMVDEC_CANVAS_MAX1 -
331 AMVDEC_CANVAS_START_INDEX + 1) / base * base;
332 if (canvas_index <= AMVDEC_CANVAS_MAX2)
333 start = canvas_index / base;
334 else
335 return -1;
336 }
337
338 if (base == 1) {
a35da9f0 339 ret = start;
b9164398 340 } else if (base == 2) {
a35da9f0 341 ret = ((start + 1) << 16) | ((start + 1) << 8) | start;
b9164398 342 } else if (base == 3) {
a35da9f0 343 ret = ((start + 2) << 16) | ((start + 1) << 8) | start;
b9164398 344 } else if (base == 4) {
a35da9f0 345 ret = (((start + 3) << 24) | (start + 2) << 16) |
b9164398
NQ
346 ((start + 1) << 8) | start;
347 }
348
a35da9f0 349 return ret;
b9164398
NQ
350}
351
05afa03d
PY
352static int get_canvas_ex(int type, int id)
353{
354 int i;
355 unsigned long flags;
356
357 flags = vdec_canvas_lock(vdec_core);
358
359 for (i = 0; i < CANVAS_MAX_SIZE; i++) {
360 /*0x10-0x15 has been used by rdma*/
361 if ((i >= 0x10) && (i <= 0x15))
362 continue;
363 if ((canvas_stat[i].type == type) &&
364 (canvas_stat[i].id & (1 << id)) == 0) {
365 canvas_stat[i].canvas_used_flag++;
366 canvas_stat[i].id |= (1 << id);
be862a73
HZ
367 if (debug & 4)
368 pr_debug("get used canvas %d\n", i);
05afa03d
PY
369 vdec_canvas_unlock(vdec_core, flags);
370 if (i < AMVDEC_CANVAS_MAX2 + 1)
371 return i;
372 else
373 return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
374 }
375 }
376
377 for (i = 0; i < CANVAS_MAX_SIZE; i++) {
378 /*0x10-0x15 has been used by rdma*/
379 if ((i >= 0x10) && (i <= 0x15))
380 continue;
381 if (canvas_stat[i].type == 0) {
382 canvas_stat[i].type = type;
383 canvas_stat[i].canvas_used_flag = 1;
384 canvas_stat[i].id = (1 << id);
be862a73
HZ
385 if (debug & 4) {
386 pr_debug("get canvas %d\n", i);
387 pr_debug("canvas_used_flag %d\n",
388 canvas_stat[i].canvas_used_flag);
389 pr_debug("canvas_stat[i].id %d\n",
390 canvas_stat[i].id);
391 }
05afa03d
PY
392 vdec_canvas_unlock(vdec_core, flags);
393 if (i < AMVDEC_CANVAS_MAX2 + 1)
394 return i;
395 else
396 return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
397 }
398 }
399 vdec_canvas_unlock(vdec_core, flags);
400
401 pr_info("cannot get canvas\n");
402
403 return -1;
404}
405
406static void free_canvas_ex(int index, int id)
407{
408 unsigned long flags;
409 int offset;
410
411 flags = vdec_canvas_lock(vdec_core);
412 if (index >= 0 &&
413 index < AMVDEC_CANVAS_MAX2 + 1)
414 offset = index;
415 else if ((index >= AMVDEC_CANVAS_START_INDEX) &&
416 (index <= AMVDEC_CANVAS_MAX1))
417 offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX;
418 else {
419 vdec_canvas_unlock(vdec_core, flags);
420 return;
421 }
422
423 if ((canvas_stat[offset].canvas_used_flag > 0) &&
424 (canvas_stat[offset].id & (1 << id))) {
425 canvas_stat[offset].canvas_used_flag--;
426 canvas_stat[offset].id &= ~(1 << id);
427 if (canvas_stat[offset].canvas_used_flag == 0) {
428 canvas_stat[offset].type = 0;
429 canvas_stat[offset].id = 0;
430 }
be862a73
HZ
431 if (debug & 4) {
432 pr_debug("free index %d used_flag %d, type = %d, id = %d\n",
433 offset,
434 canvas_stat[offset].canvas_used_flag,
435 canvas_stat[offset].type,
436 canvas_stat[offset].id);
437 }
05afa03d
PY
438 }
439 vdec_canvas_unlock(vdec_core, flags);
440
441 return;
442
443}
444
445
446
447
448static int vdec_get_hw_type(int value)
449{
450 int type;
451 switch (value) {
452 case VFORMAT_HEVC:
453 case VFORMAT_VP9:
454 case VFORMAT_AVS2:
455 type = CORE_MASK_HEVC;
456 break;
457
458 case VFORMAT_MPEG12:
459 case VFORMAT_MPEG4:
460 case VFORMAT_H264:
461 case VFORMAT_MJPEG:
462 case VFORMAT_REAL:
463 case VFORMAT_JPEG:
464 case VFORMAT_VC1:
465 case VFORMAT_AVS:
466 case VFORMAT_YUV:
467 case VFORMAT_H264MVC:
468 case VFORMAT_H264_4K2K:
469 case VFORMAT_H264_ENC:
470 case VFORMAT_JPEG_ENC:
471 type = CORE_MASK_VDEC_1;
472 break;
473
474 default:
475 type = -1;
476 }
477
478 return type;
479}
480
481
482static void vdec_save_active_hw(struct vdec_s *vdec)
483{
484 int type;
485
486 type = vdec_get_hw_type(vdec->port->vformat);
487
488 if (type == CORE_MASK_HEVC) {
489 vdec_core->active_hevc = vdec;
490 } else if (type == CORE_MASK_VDEC_1) {
491 vdec_core->active_vdec = vdec;
492 } else {
493 pr_info("save_active_fw wrong\n");
494 }
495}
496
b9164398 497
fe96802b 498int vdec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
b9164398 499{
9b670a2d 500 if (vdec && vdec->dec_status &&
501 ((vdec->status == VDEC_STATUS_CONNECTED ||
502 vdec->status == VDEC_STATUS_ACTIVE)))
b9164398
NQ
503 return vdec->dec_status(vdec, vstatus);
504
9b670a2d 505 return 0;
b9164398
NQ
506}
507EXPORT_SYMBOL(vdec_status);
508
509int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
510{
511 int r;
512
513 if (vdec->set_trickmode) {
514 r = vdec->set_trickmode(vdec, trickmode);
515
516 if ((r == 0) && (vdec->slave) && (vdec->slave->set_trickmode))
517 r = vdec->slave->set_trickmode(vdec->slave,
518 trickmode);
976f3376 519 return r;
b9164398
NQ
520 }
521
522 return -1;
523}
524EXPORT_SYMBOL(vdec_set_trickmode);
525
d481db31
NQ
526int vdec_set_isreset(struct vdec_s *vdec, int isreset)
527{
528 vdec->is_reset = isreset;
529 pr_info("is_reset=%d\n", isreset);
530 if (vdec->set_isreset)
531 return vdec->set_isreset(vdec, isreset);
532 return 0;
533}
534EXPORT_SYMBOL(vdec_set_isreset);
535
28e318df
NQ
536int vdec_set_dv_metawithel(struct vdec_s *vdec, int isdvmetawithel)
537{
538 vdec->dolby_meta_with_el = isdvmetawithel;
539 pr_info("isdvmetawithel=%d\n", isdvmetawithel);
540 return 0;
541}
c23e8aee 542EXPORT_SYMBOL(vdec_set_dv_metawithel);
28e318df
NQ
543
544void vdec_set_no_powerdown(int flag)
545{
546 no_powerdown = flag;
547 pr_info("no_powerdown=%d\n", no_powerdown);
548 return;
549}
c23e8aee 550EXPORT_SYMBOL(vdec_set_no_powerdown);
28e318df 551
fe96802b
NQ
552void vdec_count_info(struct vdec_info *vs, unsigned int err,
553 unsigned int offset)
554{
555 if (err)
556 vs->error_frame_count++;
557 if (offset) {
558 if (0 == vs->frame_count) {
559 vs->offset = 0;
560 vs->samp_cnt = 0;
561 }
562 vs->frame_data = offset > vs->total_data ?
563 offset - vs->total_data : vs->total_data - offset;
564 vs->total_data = offset;
565 if (vs->samp_cnt < 96000 * 2) { /* 2s */
566 if (0 == vs->samp_cnt)
567 vs->offset = offset;
568 vs->samp_cnt += vs->frame_dur;
569 } else {
570 vs->bit_rate = (offset - vs->offset) / 2;
571 /*pr_info("bitrate : %u\n",vs->bit_rate);*/
572 vs->samp_cnt = 0;
573 }
574 vs->frame_count++;
575 }
576 /*pr_info("size : %u, offset : %u, dur : %u, cnt : %u\n",
577 vs->offset,offset,vs->frame_dur,vs->samp_cnt);*/
578 return;
579}
580EXPORT_SYMBOL(vdec_count_info);
c23e8aee
HZ
581int vdec_is_support_4k(void)
582{
a8d5afab 583 return !is_meson_gxl_package_805X();
c23e8aee
HZ
584}
585EXPORT_SYMBOL(vdec_is_support_4k);
fe96802b 586
b9164398 587/*
e0614bf7 588 * clk_config:
b9164398
NQ
589 *0:default
590 *1:no gp0_pll;
591 *2:always used gp0_pll;
592 *>=10:fixed n M clk;
593 *== 100 , 100M clks;
e0614bf7 594 */
b9164398
NQ
595unsigned int get_vdec_clk_config_settings(void)
596{
597 return clk_config;
598}
599void update_vdec_clk_config_settings(unsigned int config)
600{
601 clk_config = config;
602}
603EXPORT_SYMBOL(update_vdec_clk_config_settings);
604
605static bool hevc_workaround_needed(void)
606{
63e810c0 607 return (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) &&
b9164398
NQ
608 (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MINOR)
609 == GXBB_REV_A_MINOR);
610}
611
612struct device *get_codec_cma_device(void)
613{
614 return vdec_core->cma_dev;
615}
616
fe96802b 617#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
618static const char * const vdec_device_name[] = {
619 "amvdec_mpeg12", "ammvdec_mpeg12",
620 "amvdec_mpeg4", "ammvdec_mpeg4",
621 "amvdec_h264", "ammvdec_h264",
622 "amvdec_mjpeg", "ammvdec_mjpeg",
623 "amvdec_real", "ammvdec_real",
624 "amjpegdec", "ammjpegdec",
625 "amvdec_vc1", "ammvdec_vc1",
626 "amvdec_avs", "ammvdec_avs",
627 "amvdec_yuv", "ammvdec_yuv",
628 "amvdec_h264mvc", "ammvdec_h264mvc",
629 "amvdec_h264_4k2k", "ammvdec_h264_4k2k",
630 "amvdec_h265", "ammvdec_h265",
631 "amvenc_avc", "amvenc_avc",
632 "jpegenc", "jpegenc",
a6c89e96
NQ
633 "amvdec_vp9", "ammvdec_vp9",
634 "amvdec_avs2", "ammvdec_avs2"
b9164398
NQ
635};
636
b9164398
NQ
637
638#else
639
640static const char * const vdec_device_name[] = {
641 "amvdec_mpeg12",
642 "amvdec_mpeg4",
643 "amvdec_h264",
644 "amvdec_mjpeg",
645 "amvdec_real",
646 "amjpegdec",
647 "amvdec_vc1",
648 "amvdec_avs",
649 "amvdec_yuv",
650 "amvdec_h264mvc",
651 "amvdec_h264_4k2k",
652 "amvdec_h265",
653 "amvenc_avc",
654 "jpegenc",
a6c89e96
NQ
655 "amvdec_vp9",
656 "amvdec_avs2"
b9164398
NQ
657};
658
b9164398
NQ
659#endif
660
a6c89e96
NQ
661#ifdef VDEC_DEBUG_SUPPORT
662static u64 get_current_clk(void)
663{
664 /*struct timespec xtime = current_kernel_time();
665 u64 usec = xtime.tv_sec * 1000000;
666 usec += xtime.tv_nsec / 1000;
667 */
668 u64 usec = sched_clock();
669 return usec;
670}
671
672static void inc_profi_count(unsigned long mask, u32 *count)
673{
674 enum vdec_type_e type;
675
676 for (type = VDEC_1; type < VDEC_MAX; type++) {
677 if (mask & (1 << type))
678 count[type]++;
679 }
680}
681
682static void update_profi_clk_run(struct vdec_s *vdec,
683 unsigned long mask, u64 clk)
684{
685 enum vdec_type_e type;
686
687 for (type = VDEC_1; type < VDEC_MAX; type++) {
688 if (mask & (1 << type)) {
689 vdec->start_run_clk[type] = clk;
690 if (vdec->profile_start_clk[type] == 0)
691 vdec->profile_start_clk[type] = clk;
692 vdec->total_clk[type] = clk
693 - vdec->profile_start_clk[type];
694 /*pr_info("set start_run_clk %ld\n",
695 vdec->start_run_clk);*/
696
697 }
698 }
699}
700
701static void update_profi_clk_stop(struct vdec_s *vdec,
702 unsigned long mask, u64 clk)
703{
704 enum vdec_type_e type;
705
706 for (type = VDEC_1; type < VDEC_MAX; type++) {
707 if (mask & (1 << type)) {
708 if (vdec->start_run_clk[type] == 0)
709 pr_info("error, start_run_clk[%d] not set\n", type);
710
711 /*pr_info("update run_clk type %d, %ld, %ld, %ld\n",
712 type,
713 clk,
714 vdec->start_run_clk[type],
715 vdec->run_clk[type]);*/
716 vdec->run_clk[type] +=
717 (clk - vdec->start_run_clk[type]);
718 }
719 }
720}
721
722#endif
723
b9164398
NQ
724int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p)
725{
726 if (copy_from_user((void *)&vdec->sys_info_store, (void *)p,
727 sizeof(struct dec_sysinfo)))
728 return -EFAULT;
729
730 return 0;
731}
732EXPORT_SYMBOL(vdec_set_decinfo);
733
734/* construct vdec strcture */
735struct vdec_s *vdec_create(struct stream_port_s *port,
736 struct vdec_s *master)
737{
738 struct vdec_s *vdec;
739 int type = VDEC_TYPE_SINGLE;
fe96802b
NQ
740 int id;
741 if (is_mult_inc(port->type))
b9164398
NQ
742 type = (port->type & PORT_TYPE_FRAME) ?
743 VDEC_TYPE_FRAME_BLOCK :
744 VDEC_TYPE_STREAM_PARSER;
745
fe96802b
NQ
746 id = ida_simple_get(&vdec_core->ida,
747 0, MAX_INSTANCE_MUN, GFP_KERNEL);
748 if (id < 0) {
749 pr_info("vdec_create request id failed!ret =%d\n", id);
750 return NULL;
751 }
b9164398
NQ
752 vdec = vzalloc(sizeof(struct vdec_s));
753
754 /* TBD */
755 if (vdec) {
756 vdec->magic = 0x43454456;
fe96802b 757 vdec->id = -1;
b9164398
NQ
758 vdec->type = type;
759 vdec->port = port;
760 vdec->sys_info = &vdec->sys_info_store;
761
762 INIT_LIST_HEAD(&vdec->list);
763
b9164398 764 atomic_inc(&vdec_core->vdec_nr);
fe96802b
NQ
765 vdec->id = id;
766 vdec_input_init(&vdec->input, vdec);
b9164398
NQ
767 if (master) {
768 vdec->master = master;
769 master->slave = vdec;
770 master->sched = 1;
771 }
772 }
773
5b851ff9 774 pr_debug("vdec_create instance %p, total %d\n", vdec,
b9164398
NQ
775 atomic_read(&vdec_core->vdec_nr));
776
fe96802b
NQ
777 //trace_vdec_create(vdec); /*DEBUG_TMP*/
778
b9164398
NQ
779 return vdec;
780}
781EXPORT_SYMBOL(vdec_create);
782
783int vdec_set_format(struct vdec_s *vdec, int format)
784{
785 vdec->format = format;
fe96802b 786 vdec->port_flag |= PORT_FLAG_VFORMAT;
b9164398 787
fe96802b 788 if (vdec->slave) {
b9164398 789 vdec->slave->format = format;
fe96802b
NQ
790 vdec->slave->port_flag |= PORT_FLAG_VFORMAT;
791 }
792
793 //trace_vdec_set_format(vdec, format);/*DEBUG_TMP*/
b9164398
NQ
794
795 return 0;
796}
797EXPORT_SYMBOL(vdec_set_format);
798
799int vdec_set_pts(struct vdec_s *vdec, u32 pts)
800{
801 vdec->pts = pts;
fe96802b 802 vdec->pts64 = div64_u64((u64)pts * 100, 9);
b9164398 803 vdec->pts_valid = true;
fe96802b 804 //trace_vdec_set_pts(vdec, (u64)pts);/*DEBUG_TMP*/
b9164398
NQ
805 return 0;
806}
807EXPORT_SYMBOL(vdec_set_pts);
808
6b7ee58f
NQ
809void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp)
810{
811 vdec->timestamp = timestamp;
812 vdec->timestamp_valid = true;
813}
814EXPORT_SYMBOL(vdec_set_timestamp);
815
b9164398
NQ
816int vdec_set_pts64(struct vdec_s *vdec, u64 pts64)
817{
818 vdec->pts64 = pts64;
fe96802b 819 vdec->pts = (u32)div64_u64(pts64 * 9, 100);
b9164398 820 vdec->pts_valid = true;
fe96802b
NQ
821
822 //trace_vdec_set_pts64(vdec, pts64);/*DEBUG_TMP*/
b9164398
NQ
823 return 0;
824}
825EXPORT_SYMBOL(vdec_set_pts64);
826
6b7ee58f
NQ
827int vdec_get_status(struct vdec_s *vdec)
828{
829 return vdec->status;
830}
831EXPORT_SYMBOL(vdec_get_status);
832
b9164398
NQ
833void vdec_set_status(struct vdec_s *vdec, int status)
834{
fe96802b 835 //trace_vdec_set_status(vdec, status);/*DEBUG_TMP*/
b9164398
NQ
836 vdec->status = status;
837}
838EXPORT_SYMBOL(vdec_set_status);
839
840void vdec_set_next_status(struct vdec_s *vdec, int status)
841{
fe96802b 842 //trace_vdec_set_next_status(vdec, status);/*DEBUG_TMP*/
b9164398
NQ
843 vdec->next_status = status;
844}
845EXPORT_SYMBOL(vdec_set_next_status);
846
847int vdec_set_video_path(struct vdec_s *vdec, int video_path)
848{
849 vdec->frame_base_video_path = video_path;
850 return 0;
851}
852EXPORT_SYMBOL(vdec_set_video_path);
853
fe96802b
NQ
854int vdec_set_receive_id(struct vdec_s *vdec, int receive_id)
855{
856 vdec->vf_receiver_inst = receive_id;
857 return 0;
858}
859EXPORT_SYMBOL(vdec_set_receive_id);
860
b9164398
NQ
861/* add frame data to input chain */
862int vdec_write_vframe(struct vdec_s *vdec, const char *buf, size_t count)
863{
864 return vdec_input_add_frame(&vdec->input, buf, count);
865}
866EXPORT_SYMBOL(vdec_write_vframe);
867
fe96802b
NQ
868/* add a work queue thread for vdec*/
869void vdec_schedule_work(struct work_struct *work)
870{
871 if (vdec_core->vdec_core_wq)
872 queue_work(vdec_core->vdec_core_wq, work);
873 else
874 schedule_work(work);
875}
876EXPORT_SYMBOL(vdec_schedule_work);
877
878static struct vdec_s *vdec_get_associate(struct vdec_s *vdec)
879{
880 if (vdec->master)
881 return vdec->master;
882 else if (vdec->slave)
883 return vdec->slave;
884 return NULL;
885}
886
887static void vdec_sync_input_read(struct vdec_s *vdec)
888{
889 if (!vdec_stream_based(vdec))
890 return;
891
892 if (vdec_dual(vdec)) {
893 u32 me, other;
894 if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
895 me = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
896 other =
897 vdec_get_associate(vdec)->input.stream_cookie;
898 if (me > other)
899 return;
900 else if (me == other) {
901 me = READ_VREG(VLD_MEM_VIFIFO_RP);
902 other =
903 vdec_get_associate(vdec)->input.swap_rp;
904 if (me > other) {
905 WRITE_PARSER_REG(PARSER_VIDEO_RP,
906 vdec_get_associate(vdec)->
907 input.swap_rp);
908 return;
909 }
910 }
911 WRITE_PARSER_REG(PARSER_VIDEO_RP,
912 READ_VREG(VLD_MEM_VIFIFO_RP));
913 } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
914 me = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
915 if (((me & 0x80000000) == 0) &&
916 (vdec->input.streaming_rp & 0x80000000))
917 me += 1ULL << 32;
918 other = vdec_get_associate(vdec)->input.streaming_rp;
919 if (me > other) {
920 WRITE_PARSER_REG(PARSER_VIDEO_RP,
921 vdec_get_associate(vdec)->
922 input.swap_rp);
923 return;
924 }
925
926 WRITE_PARSER_REG(PARSER_VIDEO_RP,
927 READ_VREG(HEVC_STREAM_RD_PTR));
928 }
929 } else if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
930 WRITE_PARSER_REG(PARSER_VIDEO_RP,
931 READ_VREG(VLD_MEM_VIFIFO_RP));
932 } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
933 WRITE_PARSER_REG(PARSER_VIDEO_RP,
934 READ_VREG(HEVC_STREAM_RD_PTR));
935 }
936}
937
938static void vdec_sync_input_write(struct vdec_s *vdec)
939{
940 if (!vdec_stream_based(vdec))
941 return;
942
943 if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
944 WRITE_VREG(VLD_MEM_VIFIFO_WP,
945 READ_PARSER_REG(PARSER_VIDEO_WP));
946 } else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
947 WRITE_VREG(HEVC_STREAM_WR_PTR,
948 READ_PARSER_REG(PARSER_VIDEO_WP));
949 }
950}
951
b9164398 952/*
e0614bf7
ZZ
953 *get next frame from input chain
954 */
b9164398 955/*
e0614bf7 956 *THE VLD_FIFO is 512 bytes and Video buffer level
b9164398
NQ
957 * empty interrupt is set to 0x80 bytes threshold
958 */
959#define VLD_PADDING_SIZE 1024
960#define HEVC_PADDING_SIZE (1024*16)
b9164398
NQ
961int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p)
962{
fe96802b 963 struct vdec_input_s *input = &vdec->input;
b9164398
NQ
964 struct vframe_chunk_s *chunk = NULL;
965 struct vframe_block_list_s *block = NULL;
966 int dummy;
967
968 /* full reset to HW input */
969 if (input->target == VDEC_INPUT_TARGET_VLD) {
970 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
971
972 /* reset VLD fifo for all vdec */
973 WRITE_VREG(DOS_SW_RESET0, (1<<5) | (1<<4) | (1<<3));
974 WRITE_VREG(DOS_SW_RESET0, 0);
975
fe96802b 976 dummy = READ_RESET_REG(RESET0_REGISTER);
b9164398
NQ
977 WRITE_VREG(POWER_CTL_VLD, 1 << 4);
978 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
979#if 0
980 /*move to driver*/
981 if (input_frame_based(input))
982 WRITE_VREG(HEVC_STREAM_CONTROL, 0);
983
984 /*
985 * 2: assist
986 * 3: parser
987 * 4: parser_state
988 * 8: dblk
989 * 11:mcpu
990 * 12:ccpu
991 * 13:ddr
992 * 14:iqit
993 * 15:ipp
994 * 17:qdct
995 * 18:mpred
996 * 19:sao
997 * 24:hevc_afifo
998 */
999 WRITE_VREG(DOS_SW_RESET3,
1000 (1<<3)|(1<<4)|(1<<8)|(1<<11)|(1<<12)|(1<<14)|(1<<15)|
1001 (1<<17)|(1<<18)|(1<<19));
1002 WRITE_VREG(DOS_SW_RESET3, 0);
1003#endif
1004 }
1005
1006 /*
e0614bf7 1007 *setup HW decoder input buffer (VLD context)
b9164398
NQ
1008 * based on input->type and input->target
1009 */
1010 if (input_frame_based(input)) {
1011 chunk = vdec_input_next_chunk(&vdec->input);
1012
1013 if (chunk == NULL) {
1014 *p = NULL;
1015 return -1;
1016 }
1017
1018 block = chunk->block;
1019
1020 if (input->target == VDEC_INPUT_TARGET_VLD) {
1021 WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, block->start);
1022 WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, block->start +
1023 block->size - 8);
1024 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
1025 round_down(block->start + chunk->offset,
fe96802b 1026 VDEC_FIFO_ALIGN));
b9164398
NQ
1027
1028 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
1029 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1030
1031 /* set to manual mode */
1032 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
1033 WRITE_VREG(VLD_MEM_VIFIFO_RP,
1034 round_down(block->start + chunk->offset,
fe96802b 1035 VDEC_FIFO_ALIGN));
b9164398
NQ
1036 dummy = chunk->offset + chunk->size +
1037 VLD_PADDING_SIZE;
1038 if (dummy >= block->size)
1039 dummy -= block->size;
1040 WRITE_VREG(VLD_MEM_VIFIFO_WP,
fe96802b
NQ
1041 round_down(block->start + dummy,
1042 VDEC_FIFO_ALIGN));
b9164398
NQ
1043
1044 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3);
1045 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
1046
1047 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
1048 (0x11 << 16) | (1<<10) | (7<<3));
1049
1050 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1051 WRITE_VREG(HEVC_STREAM_START_ADDR, block->start);
1052 WRITE_VREG(HEVC_STREAM_END_ADDR, block->start +
1053 block->size);
1054 WRITE_VREG(HEVC_STREAM_RD_PTR, block->start +
1055 chunk->offset);
1056 dummy = chunk->offset + chunk->size +
1057 HEVC_PADDING_SIZE;
1058 if (dummy >= block->size)
1059 dummy -= block->size;
1060 WRITE_VREG(HEVC_STREAM_WR_PTR,
fe96802b
NQ
1061 round_down(block->start + dummy,
1062 VDEC_FIFO_ALIGN));
b9164398
NQ
1063
1064 /* set endian */
1065 SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
1066 }
1067
1068 *p = chunk;
1069 return chunk->size;
1070
1071 } else {
fe96802b 1072 /* stream based */
b9164398
NQ
1073 u32 rp = 0, wp = 0, fifo_len = 0;
1074 int size;
fe96802b
NQ
1075 bool swap_valid = input->swap_valid;
1076 unsigned long swap_page_phys = input->swap_page_phys;
1077
1078 if (vdec_dual(vdec) &&
1079 ((vdec->flag & VDEC_FLAG_SELF_INPUT_CONTEXT) == 0)) {
1080 /* keep using previous input context */
1081 struct vdec_s *master = (vdec->slave) ?
1082 vdec : vdec->master;
1083 if (master->input.last_swap_slave) {
1084 swap_valid = master->slave->input.swap_valid;
1085 swap_page_phys =
1086 master->slave->input.swap_page_phys;
1087 } else {
1088 swap_valid = master->input.swap_valid;
1089 swap_page_phys = master->input.swap_page_phys;
1090 }
1091 }
1092
1093 if (swap_valid) {
b9164398 1094 if (input->target == VDEC_INPUT_TARGET_VLD) {
fe96802b
NQ
1095 if (vdec->format == VFORMAT_H264)
1096 SET_VREG_MASK(POWER_CTL_VLD,
1097 (1 << 9));
1098
b9164398
NQ
1099 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1100
1101 /* restore read side */
1102 WRITE_VREG(VLD_MEM_SWAP_ADDR,
fe96802b 1103 swap_page_phys);
b9164398
NQ
1104 WRITE_VREG(VLD_MEM_SWAP_CTL, 1);
1105
1106 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
1107 ;
1108 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
1109
1110 /* restore wrap count */
1111 WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT,
1112 input->stream_cookie);
1113
1114 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1115 fifo_len = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
1116
1117 /* enable */
1118 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
1119 (0x11 << 16) | (1<<10));
1120
fe96802b
NQ
1121 /* sync with front end */
1122 vdec_sync_input_read(vdec);
1123 vdec_sync_input_write(vdec);
b9164398
NQ
1124
1125 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1126 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1127 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
1128
1129 /* restore read side */
1130 WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
fe96802b 1131 swap_page_phys);
b9164398
NQ
1132 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 1);
1133
1134 while (READ_VREG(HEVC_STREAM_SWAP_CTRL)
1135 & (1<<7))
1136 ;
1137 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
1138
1139 /* restore stream offset */
1140 WRITE_VREG(HEVC_SHIFT_BYTE_COUNT,
1141 input->stream_cookie);
1142
1143 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1144 fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
1145 >> 16) & 0x7f;
1146
1147
1148 /* enable */
1149
fe96802b
NQ
1150 /* sync with front end */
1151 vdec_sync_input_read(vdec);
1152 vdec_sync_input_write(vdec);
b9164398
NQ
1153
1154 wp = READ_VREG(HEVC_STREAM_WR_PTR);
fe96802b
NQ
1155
1156 /*pr_info("vdec: restore context\r\n");*/
b9164398
NQ
1157 }
1158
1159 } else {
1160 if (input->target == VDEC_INPUT_TARGET_VLD) {
1161 WRITE_VREG(VLD_MEM_VIFIFO_START_PTR,
1162 input->start);
1163 WRITE_VREG(VLD_MEM_VIFIFO_END_PTR,
1164 input->start + input->size - 8);
1165 WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
1166 input->start);
1167
1168 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
1169 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
1170
1171 /* set to manual mode */
1172 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
1173 WRITE_VREG(VLD_MEM_VIFIFO_RP, input->start);
1174 WRITE_VREG(VLD_MEM_VIFIFO_WP,
fe96802b 1175 READ_PARSER_REG(PARSER_VIDEO_WP));
b9164398
NQ
1176
1177 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1178
1179 /* enable */
1180 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
1181 (0x11 << 16) | (1<<10));
1182
1183 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1184
1185 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1186 WRITE_VREG(HEVC_STREAM_START_ADDR,
1187 input->start);
1188 WRITE_VREG(HEVC_STREAM_END_ADDR,
1189 input->start + input->size);
1190 WRITE_VREG(HEVC_STREAM_RD_PTR,
1191 input->start);
1192 WRITE_VREG(HEVC_STREAM_WR_PTR,
fe96802b 1193 READ_PARSER_REG(PARSER_VIDEO_WP));
b9164398
NQ
1194
1195 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1196 wp = READ_VREG(HEVC_STREAM_WR_PTR);
1197 fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
1198 >> 16) & 0x7f;
1199
1200 /* enable */
1201 }
1202 }
1203 *p = NULL;
1204 if (wp >= rp)
1205 size = wp - rp + fifo_len;
1206 else
1207 size = wp + input->size - rp + fifo_len;
1208 if (size < 0) {
1209 pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n",
1210 __func__, input->size, wp, rp, fifo_len, size);
1211 size = 0;
1212 }
1213 return size;
1214 }
1215}
1216EXPORT_SYMBOL(vdec_prepare_input);
1217
1218void vdec_enable_input(struct vdec_s *vdec)
1219{
1220 struct vdec_input_s *input = &vdec->input;
1221
1222 if (vdec->status != VDEC_STATUS_ACTIVE)
1223 return;
1224
1225 if (input->target == VDEC_INPUT_TARGET_VLD)
1226 SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1<<2) | (1<<1));
1227 else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1228 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
1229 if (vdec_stream_based(vdec))
1230 CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
1231 else
1232 SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
1233 SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1<<29));
1234 }
1235}
1236EXPORT_SYMBOL(vdec_enable_input);
1237
fe96802b
NQ
1238int vdec_set_input_buffer(struct vdec_s *vdec, u32 start, u32 size)
1239{
1240 int r = vdec_input_set_buffer(&vdec->input, start, size);
1241
1242 if (r)
1243 return r;
1244
1245 if (vdec->slave)
1246 r = vdec_input_set_buffer(&vdec->slave->input, start, size);
1247
1248 return r;
1249}
1250EXPORT_SYMBOL(vdec_set_input_buffer);
1251
1252/*
1253 * vdec_eos returns the possibility that there are
1254 * more input can be used by decoder through vdec_prepare_input
1255 * Note: this function should be called prior to vdec_vframe_dirty
1256 * by decoder driver to determine if EOS happens for stream based
1257 * decoding when there is no sufficient data for a frame
1258 */
1259bool vdec_has_more_input(struct vdec_s *vdec)
1260{
1261 struct vdec_input_s *input = &vdec->input;
1262
1263 if (!input->eos)
1264 return true;
1265
1266 if (input_frame_based(input))
1267 return vdec_input_next_input_chunk(input) != NULL;
1268 else {
1269 if (input->target == VDEC_INPUT_TARGET_VLD)
1270 return READ_VREG(VLD_MEM_VIFIFO_WP) !=
1271 READ_PARSER_REG(PARSER_VIDEO_WP);
1272 else {
1273 return (READ_VREG(HEVC_STREAM_WR_PTR) & ~0x3) !=
1274 (READ_PARSER_REG(PARSER_VIDEO_WP) & ~0x3);
1275 }
1276 }
1277}
1278EXPORT_SYMBOL(vdec_has_more_input);
1279
1280void vdec_set_prepare_level(struct vdec_s *vdec, int level)
1281{
1282 vdec->input.prepare_level = level;
1283}
1284EXPORT_SYMBOL(vdec_set_prepare_level);
1285
b9164398
NQ
1286void vdec_set_flag(struct vdec_s *vdec, u32 flag)
1287{
1288 vdec->flag = flag;
1289}
fe96802b
NQ
1290EXPORT_SYMBOL(vdec_set_flag);
1291
1292void vdec_set_eos(struct vdec_s *vdec, bool eos)
1293{
1294 vdec->input.eos = eos;
1295
1296 if (vdec->slave)
1297 vdec->slave->input.eos = eos;
1298}
1299EXPORT_SYMBOL(vdec_set_eos);
b9164398 1300
a6c89e96
NQ
1301#ifdef VDEC_DEBUG_SUPPORT
1302void vdec_set_step_mode(void)
1303{
1304 step_mode = 0x1ff;
1305}
1306EXPORT_SYMBOL(vdec_set_step_mode);
1307#endif
1308
b9164398
NQ
1309void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec)
1310{
1311 if (vdec && next_vdec) {
1312 vdec->sched = 0;
1313 next_vdec->sched = 1;
1314 }
1315}
fe96802b
NQ
1316EXPORT_SYMBOL(vdec_set_next_sched);
1317
1318/*
1319 * Swap Context: S0 S1 S2 S3 S4
1320 * Sample sequence: M S M M S
1321 * Master Context: S0 S0 S2 S3 S3
1322 * Slave context: NA S1 S1 S2 S4
1323 * ^
1324 * ^
1325 * ^
1326 * the tricky part
1327 * If there are back to back decoding of master or slave
1328 * then the context of the counter part should be updated
1329 * with current decoder. In this example, S1 should be
1330 * updated to S2.
1331 * This is done by swap the swap_page and related info
1332 * between two layers.
1333 */
1334static void vdec_borrow_input_context(struct vdec_s *vdec)
1335{
1336 struct page *swap_page;
1337 unsigned long swap_page_phys;
1338 struct vdec_input_s *me;
1339 struct vdec_input_s *other;
1340
1341 if (!vdec_dual(vdec))
1342 return;
1343
1344 me = &vdec->input;
1345 other = &vdec_get_associate(vdec)->input;
1346
1347 /* swap the swap_context, borrow counter part's
1348 * swap context storage and update all related info.
1349 * After vdec_vframe_dirty, vdec_save_input_context
1350 * will be called to update current vdec's
1351 * swap context
1352 */
1353 swap_page = other->swap_page;
1354 other->swap_page = me->swap_page;
1355 me->swap_page = swap_page;
1356
1357 swap_page_phys = other->swap_page_phys;
1358 other->swap_page_phys = me->swap_page_phys;
1359 me->swap_page_phys = swap_page_phys;
1360
1361 other->swap_rp = me->swap_rp;
1362 other->streaming_rp = me->streaming_rp;
1363 other->stream_cookie = me->stream_cookie;
1364 other->swap_valid = me->swap_valid;
1365}
1366
b9164398
NQ
1367void vdec_vframe_dirty(struct vdec_s *vdec, struct vframe_chunk_s *chunk)
1368{
1369 if (chunk)
1370 chunk->flag |= VFRAME_CHUNK_FLAG_CONSUMED;
1371
1372 if (vdec_stream_based(vdec)) {
fe96802b
NQ
1373 vdec->input.swap_needed = true;
1374
1375 if (vdec_dual(vdec)) {
1376 vdec_get_associate(vdec)->input.dirty_count = 0;
1377 vdec->input.dirty_count++;
1378 if (vdec->input.dirty_count > 1) {
1379 vdec->input.dirty_count = 1;
1380 vdec_borrow_input_context(vdec);
1381 }
b9164398 1382 }
fe96802b
NQ
1383
1384 /* for stream based mode, we update read and write pointer
1385 * also in case decoder wants to keep working on decoding
1386 * for more frames while input front end has more data
1387 */
1388 vdec_sync_input_read(vdec);
1389 vdec_sync_input_write(vdec);
1390
1391 vdec->need_more_data |= VDEC_NEED_MORE_DATA_DIRTY;
1392 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
b9164398
NQ
1393 }
1394}
1395EXPORT_SYMBOL(vdec_vframe_dirty);
1396
fe96802b
NQ
1397bool vdec_need_more_data(struct vdec_s *vdec)
1398{
1399 if (vdec_stream_based(vdec))
1400 return vdec->need_more_data & VDEC_NEED_MORE_DATA;
1401
1402 return false;
1403}
1404EXPORT_SYMBOL(vdec_need_more_data);
1405
976f3376
HZ
1406
1407void hevc_wait_ddr(void)
1408{
1409 unsigned long flags;
1410 spin_lock_irqsave(&vdec_spin_lock, flags);
1411 codec_dmcbus_write(DMC_REQ_CTRL,
1412 codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4)));
1413 spin_unlock_irqrestore(&vdec_spin_lock, flags);
1414
1415 while (!(codec_dmcbus_read(DMC_CHAN_STS)
1416 & (1 << 4)))
1417 ;
1418}
1419
b9164398
NQ
1420void vdec_save_input_context(struct vdec_s *vdec)
1421{
fe96802b 1422 struct vdec_input_s *input = &vdec->input;
b9164398 1423
fe96802b 1424#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
1425 vdec_profile(vdec, VDEC_PROFILE_EVENT_SAVE_INPUT);
1426#endif
1427
1428 if (input->target == VDEC_INPUT_TARGET_VLD)
1429 WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1<<15);
1430
1431 if (input_stream_based(input) && (input->swap_needed)) {
1432 if (input->target == VDEC_INPUT_TARGET_VLD) {
1433 WRITE_VREG(VLD_MEM_SWAP_ADDR,
fe96802b 1434 input->swap_page_phys);
b9164398
NQ
1435 WRITE_VREG(VLD_MEM_SWAP_CTL, 3);
1436 while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
1437 ;
1438 WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
1439 vdec->input.stream_cookie =
1440 READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
fe96802b
NQ
1441 vdec->input.swap_rp =
1442 READ_VREG(VLD_MEM_VIFIFO_RP);
1443 vdec->input.total_rd_count =
1444 (u64)vdec->input.stream_cookie *
1445 vdec->input.size + vdec->input.swap_rp -
1446 READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL);
b9164398
NQ
1447 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1448 WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
fe96802b 1449 input->swap_page_phys);
b9164398
NQ
1450 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 3);
1451
1452 while (READ_VREG(HEVC_STREAM_SWAP_CTRL) & (1<<7))
1453 ;
1454 WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
1455
1456 vdec->input.stream_cookie =
1457 READ_VREG(HEVC_SHIFT_BYTE_COUNT);
fe96802b
NQ
1458 vdec->input.swap_rp =
1459 READ_VREG(HEVC_STREAM_RD_PTR);
1460 if (((vdec->input.stream_cookie & 0x80000000) == 0) &&
1461 (vdec->input.streaming_rp & 0x80000000))
1462 vdec->input.streaming_rp += 1ULL << 32;
1463 vdec->input.streaming_rp &= 0xffffffffULL << 32;
1464 vdec->input.streaming_rp |= vdec->input.stream_cookie;
1465 vdec->input.total_rd_count = vdec->input.streaming_rp;
b9164398
NQ
1466 }
1467
1468 input->swap_valid = true;
fe96802b
NQ
1469 input->swap_needed = false;
1470 /*pr_info("vdec: save context\r\n");*/
b9164398 1471
fe96802b
NQ
1472 vdec_sync_input_read(vdec);
1473
1474 if (vdec_dual(vdec)) {
1475 struct vdec_s *master = (vdec->slave) ?
1476 vdec : vdec->master;
1477 master->input.last_swap_slave = (master->slave == vdec);
1478 /* pr_info("master->input.last_swap_slave = %d\n",
1479 master->input.last_swap_slave); */
1480 }
976f3376
HZ
1481
1482 hevc_wait_ddr();
b9164398
NQ
1483 }
1484}
1485EXPORT_SYMBOL(vdec_save_input_context);
1486
1487void vdec_clean_input(struct vdec_s *vdec)
1488{
1489 struct vdec_input_s *input = &vdec->input;
1490
1491 while (!list_empty(&input->vframe_chunk_list)) {
1492 struct vframe_chunk_s *chunk =
1493 vdec_input_next_chunk(input);
87046a60 1494 if (chunk && (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED))
b9164398
NQ
1495 vdec_input_release_chunk(input, chunk);
1496 else
1497 break;
1498 }
1499 vdec_save_input_context(vdec);
1500}
1501EXPORT_SYMBOL(vdec_clean_input);
1502
fe96802b 1503int vdec_sync_input(struct vdec_s *vdec)
b9164398 1504{
fe96802b
NQ
1505 struct vdec_input_s *input = &vdec->input;
1506 u32 rp = 0, wp = 0, fifo_len = 0;
1507 int size;
1508
1509 vdec_sync_input_read(vdec);
1510 vdec_sync_input_write(vdec);
1511 if (input->target == VDEC_INPUT_TARGET_VLD) {
1512 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1513 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1514
1515 } else if (input->target == VDEC_INPUT_TARGET_HEVC) {
1516 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1517 wp = READ_VREG(HEVC_STREAM_WR_PTR);
1518 fifo_len = (READ_VREG(HEVC_STREAM_FIFO_CTL)
1519 >> 16) & 0x7f;
1520 }
1521 if (wp >= rp)
1522 size = wp - rp + fifo_len;
1523 else
1524 size = wp + input->size - rp + fifo_len;
1525 if (size < 0) {
1526 pr_info("%s error: input->size %x wp %x rp %x fifo_len %x => size %x\r\n",
1527 __func__, input->size, wp, rp, fifo_len, size);
1528 size = 0;
b9164398 1529 }
fe96802b
NQ
1530 return size;
1531
1532}
1533EXPORT_SYMBOL(vdec_sync_input);
1534
1535const char *vdec_status_str(struct vdec_s *vdec)
1536{
1537 return vdec->status < ARRAY_SIZE(vdec_status_string) ?
1538 vdec_status_string[vdec->status] : "INVALID";
b9164398
NQ
1539}
1540
1541const char *vdec_type_str(struct vdec_s *vdec)
1542{
1543 switch (vdec->type) {
1544 case VDEC_TYPE_SINGLE:
1545 return "VDEC_TYPE_SINGLE";
1546 case VDEC_TYPE_STREAM_PARSER:
1547 return "VDEC_TYPE_STREAM_PARSER";
1548 case VDEC_TYPE_FRAME_BLOCK:
1549 return "VDEC_TYPE_FRAME_BLOCK";
1550 case VDEC_TYPE_FRAME_CIRCULAR:
1551 return "VDEC_TYPE_FRAME_CIRCULAR";
1552 default:
1553 return "VDEC_TYPE_INVALID";
1554 }
1555}
1556
1557const char *vdec_device_name_str(struct vdec_s *vdec)
1558{
1559 return vdec_device_name[vdec->format * 2 + 1];
1560}
fe96802b 1561EXPORT_SYMBOL(vdec_device_name_str);
b9164398
NQ
1562
1563void walk_vdec_core_list(char *s)
1564{
1565 struct vdec_s *vdec;
1566 struct vdec_core_s *core = vdec_core;
1567 unsigned long flags;
1568
1569 pr_info("%s --->\n", s);
1570
1571 flags = vdec_core_lock(vdec_core);
1572
1573 if (list_empty(&core->connected_vdec_list)) {
1574 pr_info("connected vdec list empty\n");
1575 } else {
1576 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
1577 pr_info("\tvdec (%p), status = %s\n", vdec,
1578 vdec_status_str(vdec));
1579 }
1580 }
1581
1582 vdec_core_unlock(vdec_core, flags);
1583}
1584EXPORT_SYMBOL(walk_vdec_core_list);
1585
fe96802b
NQ
1586/* insert vdec to vdec_core for scheduling,
1587 * for dual running decoders, connect/disconnect always runs in pairs
1588 */
b9164398
NQ
1589int vdec_connect(struct vdec_s *vdec)
1590{
1591 unsigned long flags;
1592
fe96802b
NQ
1593 //trace_vdec_connect(vdec);/*DEBUG_TMP*/
1594
b9164398
NQ
1595 if (vdec->status != VDEC_STATUS_DISCONNECTED)
1596 return 0;
1597
1598 vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
1599 vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED);
1600
1601 init_completion(&vdec->inactive_done);
1602
1603 if (vdec->slave) {
1604 vdec_set_status(vdec->slave, VDEC_STATUS_CONNECTED);
1605 vdec_set_next_status(vdec->slave, VDEC_STATUS_CONNECTED);
1606
1607 init_completion(&vdec->slave->inactive_done);
1608 }
1609
1610 flags = vdec_core_lock(vdec_core);
1611
1612 list_add_tail(&vdec->list, &vdec_core->connected_vdec_list);
1613
1614 if (vdec->slave) {
1615 list_add_tail(&vdec->slave->list,
1616 &vdec_core->connected_vdec_list);
1617 }
1618
1619 vdec_core_unlock(vdec_core, flags);
1620
1621 up(&vdec_core->sem);
1622
1623 return 0;
1624}
1625EXPORT_SYMBOL(vdec_connect);
1626
1627/* remove vdec from vdec_core scheduling */
1628int vdec_disconnect(struct vdec_s *vdec)
1629{
fe96802b 1630#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
1631 vdec_profile(vdec, VDEC_PROFILE_EVENT_DISCONNECT);
1632#endif
fe96802b 1633 //trace_vdec_disconnect(vdec);/*DEBUG_TMP*/
b9164398
NQ
1634
1635 if ((vdec->status != VDEC_STATUS_CONNECTED) &&
1636 (vdec->status != VDEC_STATUS_ACTIVE)) {
1637 return 0;
1638 }
6da7a8e8 1639 mutex_lock(&vdec_mutex);
b9164398 1640 /*
e0614bf7 1641 *when a vdec is under the management of scheduler
b9164398
NQ
1642 * the status change will only be from vdec_core_thread
1643 */
1644 vdec_set_next_status(vdec, VDEC_STATUS_DISCONNECTED);
1645
1646 if (vdec->slave)
1647 vdec_set_next_status(vdec->slave, VDEC_STATUS_DISCONNECTED);
1648 else if (vdec->master)
1649 vdec_set_next_status(vdec->master, VDEC_STATUS_DISCONNECTED);
6da7a8e8 1650 mutex_unlock(&vdec_mutex);
b9164398
NQ
1651 up(&vdec_core->sem);
1652
87046a60 1653 if(!wait_for_completion_timeout(&vdec->inactive_done,
1654 msecs_to_jiffies(2000)))
1655 goto discon_timeout;
b9164398 1656
87046a60 1657 if (vdec->slave) {
1658 if(!wait_for_completion_timeout(&vdec->slave->inactive_done,
1659 msecs_to_jiffies(2000)))
1660 goto discon_timeout;
1661 } else if (vdec->master) {
1662 if(!wait_for_completion_timeout(&vdec->master->inactive_done,
1663 msecs_to_jiffies(2000)))
1664 goto discon_timeout;
1665 }
b9164398 1666
87046a60 1667 return 0;
1668discon_timeout:
1669 pr_err("%s timeout!!! status: 0x%x\n", __func__, vdec->status);
b9164398
NQ
1670 return 0;
1671}
1672EXPORT_SYMBOL(vdec_disconnect);
1673
1674/* release vdec structure */
1675int vdec_destroy(struct vdec_s *vdec)
1676{
fe96802b
NQ
1677 //trace_vdec_destroy(vdec);/*DEBUG_TMP*/
1678
1679 vdec_input_release(&vdec->input);
b9164398 1680
fe96802b 1681#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
1682 vdec_profile_flush(vdec);
1683#endif
fe96802b 1684 ida_simple_remove(&vdec_core->ida, vdec->id);
b9164398
NQ
1685 vfree(vdec);
1686
1687 atomic_dec(&vdec_core->vdec_nr);
1688
1689 return 0;
1690}
1691EXPORT_SYMBOL(vdec_destroy);
1692
1693/*
1694 * Only support time sliced decoding for frame based input,
1695 * so legacy decoder can exist with time sliced decoder.
1696 */
1697static const char *get_dev_name(bool use_legacy_vdec, int format)
1698{
fe96802b 1699#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
1700 if (use_legacy_vdec)
1701 return vdec_device_name[format * 2];
1702 else
1703 return vdec_device_name[format * 2 + 1];
1704#else
1705 return vdec_device_name[format];
1706#endif
1707}
1708
d5c1c0ff 1709struct vdec_s *vdec_get_with_id(unsigned int id)
8458676f 1710{
1711 struct vdec_s *vdec, *ret_vdec = NULL;
1712 struct vdec_core_s *core = vdec_core;
1713 unsigned long flags;
1714
1715 if (id >= MAX_INSTANCE_MUN)
1716 return NULL;
1717
1718 flags = vdec_core_lock(vdec_core);
1719 if (!list_empty(&core->connected_vdec_list)) {
1720 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
1721 if (vdec->id == id) {
1722 pr_info("searched avaliable vdec connected, id = %d\n", id);
1723 ret_vdec = vdec;
1724 break;
1725 }
1726 }
1727 }
1728 vdec_core_unlock(vdec_core, flags);
1729
1730 return ret_vdec;
1731}
1732
b9164398 1733/*
e0614bf7 1734 *register vdec_device
b9164398
NQ
1735 * create output, vfm or create ionvideo output
1736 */
1737s32 vdec_init(struct vdec_s *vdec, int is_4k)
1738{
1739 int r = 0;
1740 struct vdec_s *p = vdec;
b9164398 1741 const char *dev_name;
fe96802b 1742 int id = PLATFORM_DEVID_AUTO;/*if have used my self*/
b9164398
NQ
1743
1744 dev_name = get_dev_name(vdec_single(vdec), vdec->format);
1745
1746 if (dev_name == NULL)
1747 return -ENODEV;
1748
1749 pr_info("vdec_init, dev_name:%s, vdec_type=%s\n",
1750 dev_name, vdec_type_str(vdec));
1751
1752 /*
e0614bf7 1753 *todo: VFM patch control should be configurable,
b9164398
NQ
1754 * for now all stream based input uses default VFM path.
1755 */
1756 if (vdec_stream_based(vdec) && !vdec_dual(vdec)) {
1757 if (vdec_core->vfm_vdec == NULL) {
5b851ff9 1758 pr_debug("vdec_init set vfm decoder %p\n", vdec);
b9164398
NQ
1759 vdec_core->vfm_vdec = vdec;
1760 } else {
1761 pr_info("vdec_init vfm path busy.\n");
1762 return -EBUSY;
1763 }
1764 }
1765
b9164398
NQ
1766 mutex_lock(&vdec_mutex);
1767 inited_vcodec_num++;
1768 mutex_unlock(&vdec_mutex);
1769
1770 vdec_input_set_type(&vdec->input, vdec->type,
1771 (vdec->format == VFORMAT_HEVC ||
a6c89e96 1772 vdec->format == VFORMAT_AVS2 ||
b9164398
NQ
1773 vdec->format == VFORMAT_VP9) ?
1774 VDEC_INPUT_TARGET_HEVC :
1775 VDEC_INPUT_TARGET_VLD);
1776
1777 p->cma_dev = vdec_core->cma_dev;
1778 p->get_canvas = get_canvas;
05afa03d
PY
1779 p->get_canvas_ex = get_canvas_ex;
1780 p->free_canvas_ex = free_canvas_ex;
97fe3d16 1781 p->vdec_fps_detec = vdec_fps_detec;
5f3fbfb7
HZ
1782 atomic_set(&p->inirq_flag, 0);
1783 atomic_set(&p->inirq_thread_flag, 0);
b9164398
NQ
1784 /* todo */
1785 if (!vdec_dual(vdec))
fe96802b 1786 p->use_vfm_path = vdec_stream_based(vdec);
b9164398 1787 /* vdec_dev_reg.flag = 0; */
fe96802b
NQ
1788 if (vdec->id >= 0)
1789 id = vdec->id;
05afa03d
PY
1790 p->parallel_dec = parallel_decode;
1791 vdec_core->parallel_dec = parallel_decode;
8458676f 1792 vdec->canvas_mode = CANVAS_BLKMODE_32X32;
1793#ifdef FRAME_CHECK
8458676f 1794 vdec_frame_check_init(vdec);
1795#endif
fe96802b 1796 p->dev = platform_device_register_data(
b9164398
NQ
1797 &vdec_core->vdec_core_platform_device->dev,
1798 dev_name,
fe96802b 1799 id,
b9164398
NQ
1800 &p, sizeof(struct vdec_s *));
1801
1802 if (IS_ERR(p->dev)) {
1803 r = PTR_ERR(p->dev);
1804 pr_err("vdec: Decoder device %s register failed (%d)\n",
1805 dev_name, r);
1806
1807 mutex_lock(&vdec_mutex);
1808 inited_vcodec_num--;
1809 mutex_unlock(&vdec_mutex);
1810
fe96802b
NQ
1811 goto error;
1812 } else if (!p->dev->dev.driver) {
1813 pr_info("vdec: Decoder device %s driver probe failed.\n",
1814 dev_name);
1815 r = -ENODEV;
1816
b9164398
NQ
1817 goto error;
1818 }
1819
1820 if ((p->type == VDEC_TYPE_FRAME_BLOCK) && (p->run == NULL)) {
1821 r = -ENODEV;
1822 pr_err("vdec: Decoder device not handled (%s)\n", dev_name);
1823
1824 mutex_lock(&vdec_mutex);
1825 inited_vcodec_num--;
1826 mutex_unlock(&vdec_mutex);
1827
1828 goto error;
1829 }
1830
1831 if (p->use_vfm_path) {
1832 vdec->vf_receiver_inst = -1;
fe96802b 1833 vdec->vfm_map_id[0] = 0;
b9164398
NQ
1834 } else if (!vdec_dual(vdec)) {
1835 /* create IONVIDEO instance and connect decoder's
1836 * vf_provider interface to it
1837 */
1838 if (p->type != VDEC_TYPE_FRAME_BLOCK) {
1839 r = -ENODEV;
1840 pr_err("vdec: Incorrect decoder type\n");
1841
1842 mutex_lock(&vdec_mutex);
1843 inited_vcodec_num--;
1844 mutex_unlock(&vdec_mutex);
1845
1846 goto error;
1847 }
1848 if (p->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO) {
1849#if 1
ff4c2158
NQ
1850 r = ionvideo_assign_map(&vdec->vf_receiver_name,
1851 &vdec->vf_receiver_inst);
b9164398 1852#else
2b796d78
ZZ
1853 /*
1854 * temporarily just use decoder instance ID as iondriver ID
1855 * to solve OMX iondriver instance number check time sequence
1856 * only the limitation is we can NOT mix different video
1857 * decoders since same ID will be used for different decoder
1858 * formats.
1859 */
1860 vdec->vf_receiver_inst = p->dev->id;
1861 r = ionvideo_assign_map(&vdec->vf_receiver_name,
1862 &vdec->vf_receiver_inst);
b9164398 1863#endif
2b796d78
ZZ
1864 if (r < 0) {
1865 pr_err("IonVideo frame receiver allocation failed.\n");
b9164398 1866
2b796d78
ZZ
1867 mutex_lock(&vdec_mutex);
1868 inited_vcodec_num--;
1869 mutex_unlock(&vdec_mutex);
b9164398 1870
2b796d78
ZZ
1871 goto error;
1872 }
b9164398 1873
fe96802b
NQ
1874 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
1875 "%s %s", vdec->vf_provider_name,
1876 vdec->vf_receiver_name);
1877 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
1878 "vdec-map-%d", vdec->id);
b9164398
NQ
1879 } else if (p->frame_base_video_path ==
1880 FRAME_BASE_PATH_AMLVIDEO_AMVIDEO) {
2b796d78
ZZ
1881 if (vdec_secure(vdec)) {
1882 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
1883 "%s %s", vdec->vf_provider_name,
1884 "amlvideo amvideo");
1885 } else {
1886 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
1887 "%s %s", vdec->vf_provider_name,
60e7b9fa 1888 "amlvideo ppmgr deinterlace amvideo");
2b796d78 1889 }
b9164398 1890 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
fe96802b 1891 "vdec-map-%d", vdec->id);
b9164398
NQ
1892 } else if (p->frame_base_video_path ==
1893 FRAME_BASE_PATH_AMLVIDEO1_AMVIDEO2) {
1894 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
1895 "%s %s", vdec->vf_provider_name,
dbba62e2 1896 "aml_video.1 videosync.0 videopip");
b9164398 1897 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
fe96802b 1898 "vdec-map-%d", vdec->id);
6b7ee58f
NQ
1899 } else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) {
1900 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
65a98643
NQ
1901 "%s %s", vdec->vf_provider_name,
1902 vdec->vf_receiver_name);
6b7ee58f
NQ
1903 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
1904 "vdec-map-%d", vdec->id);
2b796d78
ZZ
1905 } else if (p->frame_base_video_path == FRAME_BASE_PATH_TUNNEL_MODE) {
1906 snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
1907 "%s %s", vdec->vf_provider_name,
1908 "amvideo");
8ee39d2d 1909 snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
1910 "vdec-map-%d", vdec->id);
b9164398
NQ
1911 }
1912
1913 if (vfm_map_add(vdec->vfm_map_id,
1914 vdec->vfm_map_chain) < 0) {
1915 r = -ENOMEM;
1916 pr_err("Decoder pipeline map creation failed %s.\n",
1917 vdec->vfm_map_id);
1918 vdec->vfm_map_id[0] = 0;
1919
1920 mutex_lock(&vdec_mutex);
1921 inited_vcodec_num--;
1922 mutex_unlock(&vdec_mutex);
1923
1924 goto error;
1925 }
1926
5b851ff9 1927 pr_debug("vfm map %s created\n", vdec->vfm_map_id);
b9164398
NQ
1928
1929 /*
e0614bf7 1930 *assume IONVIDEO driver already have a few vframe_receiver
b9164398
NQ
1931 * registered.
1932 * 1. Call iondriver function to allocate a IONVIDEO path and
1933 * provide receiver's name and receiver op.
1934 * 2. Get decoder driver's provider name from driver instance
1935 * 3. vfm_map_add(name, "<decoder provider name>
1936 * <iondriver receiver name>"), e.g.
1937 * vfm_map_add("vdec_ion_map_0", "mpeg4_0 iondriver_1");
1938 * 4. vf_reg_provider and vf_reg_receiver
1939 * Note: the decoder provider's op uses vdec as op_arg
1940 * the iondriver receiver's op uses iondev device as
1941 * op_arg
1942 */
1943
1944 }
1945
1946 if (!vdec_single(vdec)) {
1947 vf_reg_provider(&p->vframe_provider);
1948
1949 vf_notify_receiver(p->vf_provider_name,
1950 VFRAME_EVENT_PROVIDER_START,
1951 vdec);
fe96802b
NQ
1952
1953 if (vdec_core->hint_fr_vdec == NULL)
1954 vdec_core->hint_fr_vdec = vdec;
1955
1956 if (vdec_core->hint_fr_vdec == vdec) {
1957 if (p->sys_info->rate != 0) {
6d2907a6 1958 if (!vdec->is_reset) {
d481db31
NQ
1959 vf_notify_receiver(p->vf_provider_name,
1960 VFRAME_EVENT_PROVIDER_FR_HINT,
1961 (void *)
1962 ((unsigned long)
1963 p->sys_info->rate));
6d2907a6
LC
1964 vdec->fr_hint_state = VDEC_HINTED;
1965 }
fe96802b
NQ
1966 } else {
1967 vdec->fr_hint_state = VDEC_NEED_HINT;
1968 }
1969 }
b9164398
NQ
1970 }
1971
28e318df 1972 p->dolby_meta_with_el = 0;
5b851ff9 1973 pr_debug("vdec_init, vf_provider_name = %s\n", p->vf_provider_name);
fe96802b
NQ
1974 vdec_input_prepare_bufs(/*prepared buffer for fast playing.*/
1975 &vdec->input,
1976 vdec->sys_info->width,
1977 vdec->sys_info->height);
b9164398
NQ
1978 /* vdec is now ready to be active */
1979 vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
1980
1981 return 0;
1982
1983error:
1984 return r;
1985}
1986EXPORT_SYMBOL(vdec_init);
1987
fe96802b
NQ
1988/* vdec_create/init/release/destroy are applied to both dual running decoders
1989 */
b9164398
NQ
1990void vdec_release(struct vdec_s *vdec)
1991{
fe96802b 1992 //trace_vdec_release(vdec);/*DEBUG_TMP*/
a6c89e96
NQ
1993#ifdef VDEC_DEBUG_SUPPORT
1994 if (step_mode) {
1995 pr_info("VDEC_DEBUG: in step_mode, wait release\n");
1996 while (step_mode)
1997 udelay(10);
1998 pr_info("VDEC_DEBUG: step_mode is clear\n");
1999 }
2000#endif
b9164398
NQ
2001 vdec_disconnect(vdec);
2002
fe96802b
NQ
2003 if (vdec->vframe_provider.name) {
2004 if (!vdec_single(vdec)) {
2005 if (vdec_core->hint_fr_vdec == vdec
6d2907a6 2006 && vdec->fr_hint_state == VDEC_HINTED)
fe96802b
NQ
2007 vf_notify_receiver(
2008 vdec->vf_provider_name,
2009 VFRAME_EVENT_PROVIDER_FR_END_HINT,
2010 NULL);
2011 vdec->fr_hint_state = VDEC_NO_NEED_HINT;
2012 }
b9164398 2013 vf_unreg_provider(&vdec->vframe_provider);
fe96802b 2014 }
b9164398
NQ
2015
2016 if (vdec_core->vfm_vdec == vdec)
2017 vdec_core->vfm_vdec = NULL;
2018
fe96802b
NQ
2019 if (vdec_core->hint_fr_vdec == vdec)
2020 vdec_core->hint_fr_vdec = NULL;
2021
b9164398
NQ
2022 if (vdec->vf_receiver_inst >= 0) {
2023 if (vdec->vfm_map_id[0]) {
2024 vfm_map_remove(vdec->vfm_map_id);
2025 vdec->vfm_map_id[0] = 0;
2026 }
b9164398
NQ
2027 }
2028
5f3fbfb7
HZ
2029 while ((atomic_read(&vdec->inirq_flag) > 0)
2030 || (atomic_read(&vdec->inirq_thread_flag) > 0))
2031 schedule();
2032
8458676f 2033#ifdef FRAME_CHECK
2034 vdec_frame_check_exit(vdec);
8458676f 2035#endif
97fe3d16 2036 vdec_fps_clear(vdec->id);
5050c738 2037
b9164398 2038 platform_device_unregister(vdec->dev);
a35da9f0
PY
2039 pr_debug("vdec_release instance %p, total %d\n", vdec,
2040 atomic_read(&vdec_core->vdec_nr));
b9164398
NQ
2041 vdec_destroy(vdec);
2042
2043 mutex_lock(&vdec_mutex);
2044 inited_vcodec_num--;
2045 mutex_unlock(&vdec_mutex);
fe96802b 2046
b9164398
NQ
2047}
2048EXPORT_SYMBOL(vdec_release);
2049
a6c89e96
NQ
2050/* For dual running decoders, vdec_reset is only called with master vdec.
2051 */
b9164398
NQ
2052int vdec_reset(struct vdec_s *vdec)
2053{
a6c89e96
NQ
2054 //trace_vdec_reset(vdec); /*DEBUG_TMP*/
2055
b9164398
NQ
2056 vdec_disconnect(vdec);
2057
2058 if (vdec->vframe_provider.name)
2059 vf_unreg_provider(&vdec->vframe_provider);
2060
2061 if ((vdec->slave) && (vdec->slave->vframe_provider.name))
2062 vf_unreg_provider(&vdec->slave->vframe_provider);
2063
2064 if (vdec->reset) {
2065 vdec->reset(vdec);
2066 if (vdec->slave)
2067 vdec->slave->reset(vdec->slave);
2068 }
158de7c4 2069 vdec->mc_loaded = 0;/*clear for reload firmware*/
b9164398
NQ
2070 vdec_input_release(&vdec->input);
2071
6b7ee58f
NQ
2072 vdec_input_init(&vdec->input, vdec);
2073
2074 vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width,
2075 vdec->sys_info->height);
2076
b9164398
NQ
2077 vf_reg_provider(&vdec->vframe_provider);
2078 vf_notify_receiver(vdec->vf_provider_name,
2079 VFRAME_EVENT_PROVIDER_START, vdec);
2080
2081 if (vdec->slave) {
2082 vf_reg_provider(&vdec->slave->vframe_provider);
2083 vf_notify_receiver(vdec->slave->vf_provider_name,
2084 VFRAME_EVENT_PROVIDER_START, vdec->slave);
158de7c4 2085 vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
b9164398
NQ
2086 }
2087
2088 vdec_connect(vdec);
2089
2090 return 0;
2091}
2092EXPORT_SYMBOL(vdec_reset);
2093
fe96802b
NQ
2094void vdec_free_cmabuf(void)
2095{
2096 mutex_lock(&vdec_mutex);
2097
a35da9f0 2098 /*if (inited_vcodec_num > 0) {
fe96802b
NQ
2099 mutex_unlock(&vdec_mutex);
2100 return;
a35da9f0 2101 }*/
fe96802b
NQ
2102 mutex_unlock(&vdec_mutex);
2103}
2104
665a4a8e 2105void vdec_core_request(struct vdec_s *vdec, unsigned long mask)
b9164398 2106{
a6c89e96 2107 vdec->core_mask |= mask;
b9164398 2108
a6c89e96
NQ
2109 if (vdec->slave)
2110 vdec->slave->core_mask |= mask;
05afa03d
PY
2111 if (vdec_core->parallel_dec == 1) {
2112 if (mask & CORE_MASK_COMBINE)
2113 vdec_core->vdec_combine_flag++;
2114 }
a6c89e96 2115
a6c89e96
NQ
2116}
2117EXPORT_SYMBOL(vdec_core_request);
2118
2119int vdec_core_release(struct vdec_s *vdec, unsigned long mask)
2120{
2121 vdec->core_mask &= ~mask;
2122
2123 if (vdec->slave)
2124 vdec->slave->core_mask &= ~mask;
05afa03d
PY
2125 if (vdec_core->parallel_dec == 1) {
2126 if (mask & CORE_MASK_COMBINE)
2127 vdec_core->vdec_combine_flag--;
2128 }
a6c89e96
NQ
2129 return 0;
2130}
2131EXPORT_SYMBOL(vdec_core_release);
2132
a35da9f0 2133bool vdec_core_with_input(unsigned long mask)
a6c89e96
NQ
2134{
2135 enum vdec_type_e type;
2136
2137 for (type = VDEC_1; type < VDEC_MAX; type++) {
2138 if ((mask & (1 << type)) && cores_with_input[type])
2139 return true;
b9164398
NQ
2140 }
2141
a6c89e96
NQ
2142 return false;
2143}
2144
2145void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask)
2146{
2147 unsigned long i;
2148 unsigned long t = mask;
6da7a8e8 2149 mutex_lock(&vdec_mutex);
a6c89e96
NQ
2150 while (t) {
2151 i = __ffs(t);
2152 clear_bit(i, &vdec->active_mask);
2153 t &= ~(1 << i);
2154 }
2155
2156 if (vdec->active_mask == 0)
2157 vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
6da7a8e8
PY
2158
2159 mutex_unlock(&vdec_mutex);
a6c89e96
NQ
2160}
2161EXPORT_SYMBOL(vdec_core_finish_run);
2162/*
2163 * find what core resources are available for vdec
2164 */
2165static unsigned long vdec_schedule_mask(struct vdec_s *vdec,
2166 unsigned long active_mask)
2167{
2168 unsigned long mask = vdec->core_mask &
2169 ~CORE_MASK_COMBINE;
2170
2171 if (vdec->core_mask & CORE_MASK_COMBINE) {
2172 /* combined cores must be granted together */
2173 if ((mask & ~active_mask) == mask)
2174 return mask;
2175 else
2176 return 0;
2177 } else
2178 return mask & ~vdec->sched_mask & ~active_mask;
b9164398
NQ
2179}
2180
2181/*
e0614bf7 2182 *Decoder callback
b9164398
NQ
2183 * Each decoder instance uses this callback to notify status change, e.g. when
2184 * decoder finished using HW resource.
2185 * a sample callback from decoder's driver is following:
2186 *
2187 * if (hw->vdec_cb) {
2188 * vdec_set_next_status(vdec, VDEC_STATUS_CONNECTED);
2189 * hw->vdec_cb(vdec, hw->vdec_cb_arg);
2190 * }
2191 */
2192static void vdec_callback(struct vdec_s *vdec, void *data)
2193{
2194 struct vdec_core_s *core = (struct vdec_core_s *)data;
2195
fe96802b 2196#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
2197 vdec_profile(vdec, VDEC_PROFILE_EVENT_CB);
2198#endif
2199
2200 up(&core->sem);
2201}
2202
2203static irqreturn_t vdec_isr(int irq, void *dev_id)
2204{
2205 struct vdec_isr_context_s *c =
2206 (struct vdec_isr_context_s *)dev_id;
05afa03d 2207 struct vdec_s *vdec = vdec_core->last_vdec;
5f3fbfb7 2208 irqreturn_t ret = IRQ_HANDLED;
05afa03d
PY
2209
2210 if (vdec_core->parallel_dec == 1) {
2211 if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq)
2212 vdec = vdec_core->active_hevc;
2213 else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq)
2214 vdec = vdec_core->active_vdec;
2215 else
2216 vdec = NULL;
2217 }
2218
5f3fbfb7
HZ
2219 if (vdec)
2220 atomic_set(&vdec->inirq_flag, 1);
2221 if (c->dev_isr) {
2222 ret = c->dev_isr(irq, c->dev_id);
2223 goto isr_done;
2224 }
b9164398 2225
a6c89e96
NQ
2226 if ((c != &vdec_core->isr_context[VDEC_IRQ_0]) &&
2227 (c != &vdec_core->isr_context[VDEC_IRQ_1]) &&
2228 (c != &vdec_core->isr_context[VDEC_IRQ_HEVC_BACK])) {
b9164398
NQ
2229#if 0
2230 pr_warn("vdec interrupt w/o a valid receiver\n");
2231#endif
5f3fbfb7 2232 goto isr_done;
b9164398
NQ
2233 }
2234
2235 if (!vdec) {
2236#if 0
2237 pr_warn("vdec interrupt w/o an active instance running. core = %p\n",
2238 core);
2239#endif
5f3fbfb7 2240 goto isr_done;
b9164398
NQ
2241 }
2242
2243 if (!vdec->irq_handler) {
2244#if 0
2245 pr_warn("vdec instance has no irq handle.\n");
2246#endif
5f3fbfb7 2247 goto isr_done;
b9164398
NQ
2248 }
2249
5f3fbfb7
HZ
2250 ret = vdec->irq_handler(vdec, c->index);
2251isr_done:
2252 if (vdec)
2253 atomic_set(&vdec->inirq_flag, 0);
2254 return ret;
b9164398
NQ
2255}
2256
2257static irqreturn_t vdec_thread_isr(int irq, void *dev_id)
2258{
2259 struct vdec_isr_context_s *c =
2260 (struct vdec_isr_context_s *)dev_id;
05afa03d 2261 struct vdec_s *vdec = vdec_core->last_vdec;
5f3fbfb7 2262 irqreturn_t ret = IRQ_HANDLED;
05afa03d
PY
2263
2264 if (vdec_core->parallel_dec == 1) {
2265 if (irq == vdec_core->isr_context[VDEC_IRQ_0].irq)
2266 vdec = vdec_core->active_hevc;
2267 else if (irq == vdec_core->isr_context[VDEC_IRQ_1].irq)
2268 vdec = vdec_core->active_vdec;
2269 else
2270 vdec = NULL;
2271 }
2272
5f3fbfb7
HZ
2273 if (vdec)
2274 atomic_set(&vdec->inirq_thread_flag, 1);
2275 if (c->dev_threaded_isr) {
2276 ret = c->dev_threaded_isr(irq, c->dev_id);
2277 goto thread_isr_done;
2278 }
b9164398 2279 if (!vdec)
5f3fbfb7 2280 goto thread_isr_done;
b9164398
NQ
2281
2282 if (!vdec->threaded_irq_handler)
5f3fbfb7
HZ
2283 goto thread_isr_done;
2284 ret = vdec->threaded_irq_handler(vdec, c->index);
2285thread_isr_done:
2286 if (vdec)
2287 atomic_set(&vdec->inirq_thread_flag, 0);
2288 return ret;
b9164398
NQ
2289}
2290
a6c89e96 2291unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
b9164398 2292{
a6c89e96 2293 unsigned long ready_mask;
fe96802b 2294 struct vdec_input_s *input = &vdec->input;
a6c89e96
NQ
2295 if ((vdec->status != VDEC_STATUS_CONNECTED) &&
2296 (vdec->status != VDEC_STATUS_ACTIVE))
b9164398
NQ
2297 return false;
2298
2299 if (!vdec->run_ready)
2300 return false;
2301
d5c1c0ff 2302 /* when crc32 error, block at error frame */
2303 if (vdec->vfc.err_crc_block)
2304 return false;
2305
b9164398
NQ
2306 if ((vdec->slave || vdec->master) &&
2307 (vdec->sched == 0))
2308 return false;
a6c89e96
NQ
2309#ifdef VDEC_DEBUG_SUPPORT
2310 inc_profi_count(mask, vdec->check_count);
2311#endif
2312 if (vdec_core_with_input(mask)) {
2313 /* check frame based input underrun */
2314 if (input && !input->eos && input_frame_based(input)
2315 && (!vdec_input_next_chunk(input))) {
2316#ifdef VDEC_DEBUG_SUPPORT
2317 inc_profi_count(mask, vdec->input_underrun_count);
2318#endif
fe96802b 2319 return false;
a6c89e96
NQ
2320 }
2321 /* check streaming prepare level threshold if not EOS */
2322 if (input && input_stream_based(input) && !input->eos) {
2323 u32 rp, wp, level;
2324
2325 rp = READ_PARSER_REG(PARSER_VIDEO_RP);
2326 wp = READ_PARSER_REG(PARSER_VIDEO_WP);
2327 if (wp < rp)
2328 level = input->size + wp - rp;
2329 else
2330 level = wp - rp;
2331
2332 if ((level < input->prepare_level) &&
2333 (pts_get_rec_num(PTS_TYPE_VIDEO,
2334 vdec->input.total_rd_count) < 2)) {
2335 vdec->need_more_data |= VDEC_NEED_MORE_DATA;
2336#ifdef VDEC_DEBUG_SUPPORT
2337 inc_profi_count(mask, vdec->input_underrun_count);
2338 if (step_mode & 0x200) {
2339 if ((step_mode & 0xff) == vdec->id) {
2340 step_mode |= 0xff;
2341 return mask;
2342 }
2343 }
2344#endif
2345 return false;
2346 } else if (level > input->prepare_level)
2347 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
2348 }
fe96802b
NQ
2349 }
2350
b9164398
NQ
2351 if (step_mode) {
2352 if ((step_mode & 0xff) != vdec->id)
a6c89e96
NQ
2353 return 0;
2354 step_mode |= 0xff; /*VDEC_DEBUG_SUPPORT*/
b9164398
NQ
2355 }
2356
a6c89e96 2357 /*step_mode &= ~0xff; not work for id of 0, removed*/
b9164398 2358
fe96802b 2359#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
2360 vdec_profile(vdec, VDEC_PROFILE_EVENT_CHK_RUN_READY);
2361#endif
2362
a6c89e96
NQ
2363 ready_mask = vdec->run_ready(vdec, mask) & mask;
2364#ifdef VDEC_DEBUG_SUPPORT
2365 if (ready_mask != mask)
2366 inc_profi_count(ready_mask ^ mask, vdec->not_run_ready_count);
2367#endif
fe96802b 2368#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
a6c89e96 2369 if (ready_mask)
b9164398
NQ
2370 vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN_READY);
2371#endif
2372
a6c89e96
NQ
2373 return ready_mask;
2374}
2375
2376/* bridge on/off vdec's interrupt processing to vdec core */
2377static void vdec_route_interrupt(struct vdec_s *vdec, unsigned long mask,
2378 bool enable)
2379{
2380 enum vdec_type_e type;
2381
2382 for (type = VDEC_1; type < VDEC_MAX; type++) {
2383 if (mask & (1 << type)) {
2384 struct vdec_isr_context_s *c =
2385 &vdec_core->isr_context[cores_int[type]];
2386 if (enable)
2387 c->vdec = vdec;
2388 else if (c->vdec == vdec)
2389 c->vdec = NULL;
2390 }
2391 }
b9164398
NQ
2392}
2393
fe96802b
NQ
2394/*
2395 * Set up secure protection for each decoder instance running.
2396 * Note: The operation from REE side only resets memory access
2397 * to a default policy and even a non_secure type will still be
2398 * changed to secure type automatically when secure source is
2399 * detected inside TEE.
2400 * Perform need_more_data checking and set flag is decoder
2401 * is not consuming data.
2402 */
a6c89e96 2403void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask)
fe96802b
NQ
2404{
2405 struct vdec_input_s *input = &vdec->input;
a6c89e96 2406 int secure = (vdec_secure(vdec)) ? DMC_DEV_TYPE_SECURE :
fe96802b
NQ
2407 DMC_DEV_TYPE_NON_SECURE;
2408
a6c89e96
NQ
2409 vdec_route_interrupt(vdec, mask, true);
2410
2411 if (!vdec_core_with_input(mask))
2412 return;
2413
fe96802b 2414 if (input->target == VDEC_INPUT_TARGET_VLD)
a6c89e96 2415 tee_config_device_secure(DMC_DEV_ID_VDEC, secure);
fe96802b 2416 else if (input->target == VDEC_INPUT_TARGET_HEVC)
a6c89e96 2417 tee_config_device_secure(DMC_DEV_ID_HEVC, secure);
fe96802b
NQ
2418
2419 if (vdec_stream_based(vdec) &&
2420 ((vdec->need_more_data & VDEC_NEED_MORE_DATA_RUN) &&
2421 (vdec->need_more_data & VDEC_NEED_MORE_DATA_DIRTY) == 0)) {
2422 vdec->need_more_data |= VDEC_NEED_MORE_DATA;
2423 }
2424
2425 vdec->need_more_data |= VDEC_NEED_MORE_DATA_RUN;
2426 vdec->need_more_data &= ~VDEC_NEED_MORE_DATA_DIRTY;
2427}
2428
b9164398
NQ
2429/* struct vdec_core_shread manages all decoder instance in active list. When
2430 * a vdec is added into the active list, it can onlt be in two status:
2431 * VDEC_STATUS_CONNECTED(the decoder does not own HW resource and ready to run)
2432 * VDEC_STATUS_ACTIVE(the decoder owns HW resources and is running).
2433 * Removing a decoder from active list is only performed within core thread.
2434 * Adding a decoder into active list is performed from user thread.
2435 */
2436static int vdec_core_thread(void *data)
2437{
b9164398 2438 struct vdec_core_s *core = (struct vdec_core_s *)data;
158de7c4 2439 struct sched_param param = {.sched_priority = MAX_RT_PRIO/2};
05afa03d 2440 int i;
b9164398
NQ
2441
2442 sched_setscheduler(current, SCHED_FIFO, &param);
2443
2444 allow_signal(SIGTERM);
05afa03d 2445
b9164398 2446 while (down_interruptible(&core->sem) == 0) {
a6c89e96
NQ
2447 struct vdec_s *vdec, *tmp, *worker;
2448 unsigned long sched_mask = 0;
b9164398
NQ
2449 LIST_HEAD(disconnecting_list);
2450
2451 if (kthread_should_stop())
2452 break;
6da7a8e8 2453 mutex_lock(&vdec_mutex);
05afa03d
PY
2454
2455 if (core->parallel_dec == 1) {
2456 for (i = VDEC_1; i < VDEC_MAX; i++) {
2457 core->power_ref_mask =
2458 core->power_ref_count[i] > 0 ?
2459 (core->power_ref_mask | (1 << i)) :
2460 (core->power_ref_mask & ~(1 << i));
2461 }
2462 }
b9164398 2463 /* clean up previous active vdec's input */
a6c89e96
NQ
2464 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
2465 unsigned long mask = vdec->sched_mask &
2466 (vdec->active_mask ^ vdec->sched_mask);
2467
2468 vdec_route_interrupt(vdec, mask, false);
2469
2470#ifdef VDEC_DEBUG_SUPPORT
2471 update_profi_clk_stop(vdec, mask, get_current_clk());
2472#endif
2473 /*
2474 * If decoder released some core resources (mask), then
2475 * check if these core resources are associated
2476 * with any input side and do input clean up accordingly
2477 */
2478 if (vdec_core_with_input(mask)) {
2479 struct vdec_input_s *input = &vdec->input;
2480 while (!list_empty(
2481 &input->vframe_chunk_list)) {
2482 struct vframe_chunk_s *chunk =
2483 vdec_input_next_chunk(input);
87046a60 2484 if (chunk && (chunk->flag &
2485 VFRAME_CHUNK_FLAG_CONSUMED))
a6c89e96
NQ
2486 vdec_input_release_chunk(input,
2487 chunk);
2488 else
2489 break;
2490 }
2491
2492 vdec_save_input_context(vdec);
b9164398
NQ
2493 }
2494
a6c89e96
NQ
2495 vdec->sched_mask &= ~mask;
2496 core->sched_mask &= ~mask;
b9164398
NQ
2497 }
2498
2499 /*
e0614bf7 2500 *todo:
b9164398
NQ
2501 * this is the case when the decoder is in active mode and
2502 * the system side wants to stop it. Currently we rely on
2503 * the decoder instance to go back to VDEC_STATUS_CONNECTED
2504 * from VDEC_STATUS_ACTIVE by its own. However, if for some
2505 * reason the decoder can not exist by itself (dead decoding
2506 * or whatever), then we may have to add another vdec API
2507 * to kill the vdec and release its HW resource and make it
2508 * become inactive again.
2509 * if ((core->active_vdec) &&
2510 * (core->active_vdec->status == VDEC_STATUS_DISCONNECTED)) {
2511 * }
2512 */
2513
b9164398
NQ
2514 /* check disconnected decoders */
2515 list_for_each_entry_safe(vdec, tmp,
2516 &core->connected_vdec_list, list) {
2517 if ((vdec->status == VDEC_STATUS_CONNECTED) &&
2518 (vdec->next_status == VDEC_STATUS_DISCONNECTED)) {
05afa03d
PY
2519 if (core->parallel_dec == 1) {
2520 if (vdec_core->active_hevc == vdec)
2521 vdec_core->active_hevc = NULL;
2522 if (vdec_core->active_vdec == vdec)
2523 vdec_core->active_vdec = NULL;
2524 }
2525 if (core->last_vdec == vdec)
2526 core->last_vdec = NULL;
b9164398
NQ
2527 list_move(&vdec->list, &disconnecting_list);
2528 }
2529 }
6da7a8e8 2530 mutex_unlock(&vdec_mutex);
a6c89e96 2531 /* elect next vdec to be scheduled */
05afa03d 2532 vdec = core->last_vdec;
a6c89e96
NQ
2533 if (vdec) {
2534 vdec = list_entry(vdec->list.next, struct vdec_s, list);
b9164398
NQ
2535 list_for_each_entry_from(vdec,
2536 &core->connected_vdec_list, list) {
a6c89e96
NQ
2537 sched_mask = vdec_schedule_mask(vdec,
2538 core->sched_mask);
2539 if (!sched_mask)
2540 continue;
2541 sched_mask = vdec_ready_to_run(vdec,
2542 sched_mask);
2543 if (sched_mask)
b9164398
NQ
2544 break;
2545 }
2546
a6c89e96
NQ
2547 if (&vdec->list == &core->connected_vdec_list)
2548 vdec = NULL;
2549 }
2550
2551 if (!vdec) {
2552 /* search from beginning */
2553 list_for_each_entry(vdec,
2554 &core->connected_vdec_list, list) {
2555 sched_mask = vdec_schedule_mask(vdec,
2556 core->sched_mask);
05afa03d 2557 if (vdec == core->last_vdec) {
a6c89e96
NQ
2558 if (!sched_mask) {
2559 vdec = NULL;
b9164398 2560 break;
a6c89e96
NQ
2561 }
2562
2563 sched_mask = vdec_ready_to_run(vdec,
2564 sched_mask);
b9164398 2565
a6c89e96 2566 if (!sched_mask) {
b9164398
NQ
2567 vdec = NULL;
2568 break;
2569 }
a6c89e96 2570 break;
b9164398 2571 }
a6c89e96
NQ
2572
2573 if (!sched_mask)
2574 continue;
2575
2576 sched_mask = vdec_ready_to_run(vdec,
2577 sched_mask);
2578 if (sched_mask)
2579 break;
b9164398
NQ
2580 }
2581
2582 if (&vdec->list == &core->connected_vdec_list)
2583 vdec = NULL;
b9164398
NQ
2584 }
2585
a6c89e96
NQ
2586 worker = vdec;
2587
2588 if (vdec) {
2589 unsigned long mask = sched_mask;
2590 unsigned long i;
2591
2592 /* setting active_mask should be atomic.
2593 * it can be modified by decoder driver callbacks.
2594 */
2595 while (sched_mask) {
2596 i = __ffs(sched_mask);
2597 set_bit(i, &vdec->active_mask);
2598 sched_mask &= ~(1 << i);
2599 }
2600
2601 /* vdec's sched_mask is only set from core thread */
2602 vdec->sched_mask |= mask;
05afa03d
PY
2603 if (core->last_vdec) {
2604 if ((core->last_vdec != vdec) &&
2605 (core->last_vdec->mc_type != vdec->mc_type))
158de7c4
HZ
2606 vdec->mc_loaded = 0;/*clear for reload firmware*/
2607 }
05afa03d 2608 core->last_vdec = vdec;
158de7c4
HZ
2609 if (debug & 2)
2610 vdec->mc_loaded = 0;/*alway reload firmware*/
b9164398
NQ
2611 vdec_set_status(vdec, VDEC_STATUS_ACTIVE);
2612
a6c89e96 2613 core->sched_mask |= mask;
05afa03d
PY
2614 if (core->parallel_dec == 1)
2615 vdec_save_active_hw(vdec);
fe96802b 2616#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
b9164398
NQ
2617 vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN);
2618#endif
a6c89e96
NQ
2619 vdec_prepare_run(vdec, mask);
2620#ifdef VDEC_DEBUG_SUPPORT
2621 inc_profi_count(mask, vdec->run_count);
2622 update_profi_clk_run(vdec, mask, get_current_clk());
2623#endif
2624 vdec->run(vdec, mask, vdec_callback, core);
2625
fe96802b 2626
a6c89e96
NQ
2627 /* we have some cores scheduled, keep working until
2628 * all vdecs are checked with no cores to schedule
2629 */
05afa03d
PY
2630 if (core->parallel_dec == 1) {
2631 if (vdec_core->vdec_combine_flag == 0)
2632 up(&core->sem);
2633 } else
2634 up(&core->sem);
b9164398
NQ
2635 }
2636
2637 /* remove disconnected decoder from active list */
2638 list_for_each_entry_safe(vdec, tmp, &disconnecting_list, list) {
2639 list_del(&vdec->list);
2640 vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
05afa03d 2641 /*core->last_vdec = NULL;*/
b9164398
NQ
2642 complete(&vdec->inactive_done);
2643 }
2644
a6c89e96
NQ
2645 /* if there is no new work scheduled and nothing
2646 * is running, sleep 20ms
2647 */
05afa03d
PY
2648 if (core->parallel_dec == 1) {
2649 if (vdec_core->vdec_combine_flag == 0) {
2650 if ((!worker) &&
2651 ((core->sched_mask != core->power_ref_mask)) &&
2652 (atomic_read(&vdec_core->vdec_nr) > 0)) {
2653 usleep_range(1000, 2000);
2654 up(&core->sem);
2655 }
2656 } else {
2657 if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) {
2658 usleep_range(1000, 2000);
2659 up(&core->sem);
2660 }
2661 }
2662 } else if ((!worker) && (!core->sched_mask) && (atomic_read(&vdec_core->vdec_nr) > 0)) {
14d1803e 2663 usleep_range(1000, 2000);
b9164398
NQ
2664 up(&core->sem);
2665 }
3f4a083c 2666
b9164398
NQ
2667 }
2668
2669 return 0;
2670}
2671
2672#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
2673static bool test_hevc(u32 decomp_addr, u32 us_delay)
2674{
2675 int i;
2676
2677 /* SW_RESET IPP */
2678 WRITE_VREG(HEVCD_IPP_TOP_CNTL, 1);
2679 WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0);
2680
2681 /* initialize all canvas table */
2682 WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0);
2683 for (i = 0; i < 32; i++)
2684 WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
2685 0x1 | (i << 8) | decomp_addr);
2686 WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 1);
2687 WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1);
2688 for (i = 0; i < 32; i++)
2689 WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
2690
2691 /* Initialize mcrcc */
2692 WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2);
2693 WRITE_VREG(HEVCD_MCRCC_CTL2, 0x0);
2694 WRITE_VREG(HEVCD_MCRCC_CTL3, 0x0);
2695 WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
2696
2697 /* Decomp initialize */
2698 WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x0);
2699 WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0);
2700
2701 /* Frame level initialization */
2702 WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG, 0x100 | (0x100 << 16));
2703 WRITE_VREG(HEVCD_IPP_TOP_TILECONFIG3, 0x0);
2704 WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 0x1 << 5);
2705 WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x2 | (0x2 << 2));
2706
2707 WRITE_VREG(HEVCD_IPP_CONFIG, 0x0);
2708 WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, 0x0);
2709
2710 /* Enable SWIMP mode */
2711 WRITE_VREG(HEVCD_IPP_SWMPREDIF_CONFIG, 0x1);
2712
2713 /* Enable frame */
2714 WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x2);
2715 WRITE_VREG(HEVCD_IPP_TOP_FRMCTL, 0x1);
2716
2717 /* Send SW-command CTB info */
2718 WRITE_VREG(HEVCD_IPP_SWMPREDIF_CTBINFO, 0x1 << 31);
2719
2720 /* Send PU_command */
2721 WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO0, (0x4 << 9) | (0x4 << 16));
2722 WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO1, 0x1 << 3);
2723 WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO2, 0x0);
2724 WRITE_VREG(HEVCD_IPP_SWMPREDIF_PUINFO3, 0x0);
2725
2726 udelay(us_delay);
2727
2728 WRITE_VREG(HEVCD_IPP_DBG_SEL, 0x2 << 4);
2729
2730 return (READ_VREG(HEVCD_IPP_DBG_DATA) & 3) == 1;
2731}
2732
865e748b
NQ
2733void vdec_power_reset(void)
2734{
2735 /* enable vdec1 isolation */
2736 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
2737 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc0);
2738 /* power off vdec1 memories */
2739 WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
2740 /* vdec1 power off */
2741 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
2742 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc);
2743
2744 if (has_vdec2()) {
2745 /* enable vdec2 isolation */
2746 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
2747 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x300);
2748 /* power off vdec2 memories */
2749 WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL);
2750 /* vdec2 power off */
2751 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
2752 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0x30);
2753 }
2754
2755 if (has_hdec()) {
2756 /* enable hcodec isolation */
2757 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
2758 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0x30);
2759 /* power off hcodec memories */
2760 WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL);
2761 /* hcodec power off */
2762 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
2763 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 3);
2764 }
2765
2766 if (has_hevc_vdec()) {
2767 /* enable hevc isolation */
2768 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
2769 READ_AOREG(AO_RTI_GEN_PWR_ISO0) | 0xc00);
2770 /* power off hevc memories */
2771 WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
2772 /* hevc power off */
2773 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
2774 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) | 0xc0);
2775 }
2776}
2777EXPORT_SYMBOL(vdec_power_reset);
2778
b9164398
NQ
2779void vdec_poweron(enum vdec_type_e core)
2780{
2781 void *decomp_addr = NULL;
2782 dma_addr_t decomp_dma_addr;
2783 u32 decomp_addr_aligned = 0;
2784 int hevc_loop = 0;
2785
2786 if (core >= VDEC_MAX)
2787 return;
2788
2789 mutex_lock(&vdec_mutex);
2790
2791 vdec_core->power_ref_count[core]++;
2792 if (vdec_core->power_ref_count[core] > 1) {
2793 mutex_unlock(&vdec_mutex);
2794 return;
2795 }
2796
2797 if (vdec_on(core)) {
2798 mutex_unlock(&vdec_mutex);
2799 return;
2800 }
2801
2802 if (hevc_workaround_needed() &&
2803 (core == VDEC_HEVC)) {
2804 decomp_addr = codec_mm_dma_alloc_coherent(MEM_NAME,
2805 SZ_64K + SZ_4K, &decomp_dma_addr, GFP_KERNEL, 0);
2806
2807 if (decomp_addr) {
2808 decomp_addr_aligned = ALIGN(decomp_dma_addr, SZ_64K);
2809 memset((u8 *)decomp_addr +
2810 (decomp_addr_aligned - decomp_dma_addr),
2811 0xff, SZ_4K);
2812 } else
2813 pr_err("vdec: alloc HEVC gxbb decomp buffer failed.\n");
2814 }
2815
2816 if (core == VDEC_1) {
2817 /* vdec1 power on */
2818 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
6f5ee885
NQ
2819 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
2820 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
2821 ? ~0x2 : ~0xc));
b9164398
NQ
2822 /* wait 10uS */
2823 udelay(10);
2824 /* vdec1 soft reset */
2825 WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
2826 WRITE_VREG(DOS_SW_RESET0, 0);
2827 /* enable vdec1 clock */
2828 /*
e0614bf7
ZZ
2829 *add power on vdec clock level setting,only for m8 chip,
2830 * m8baby and m8m2 can dynamic adjust vdec clock,
2831 * power on with default clock level
2832 */
65a98643 2833 amports_switch_gate("clk_vdec_mux", 1);
b9164398
NQ
2834 vdec_clock_hi_enable();
2835 /* power up vdec memories */
2836 WRITE_VREG(DOS_MEM_PD_VDEC, 0);
2837 /* remove vdec1 isolation */
2838 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
6f5ee885
NQ
2839 READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
2840 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
2841 ? ~0x2 : ~0xC0));
b9164398
NQ
2842 /* reset DOS top registers */
2843 WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0);
63e810c0
CG
2844 if (get_cpu_major_id() >=
2845 AM_MESON_CPU_MAJOR_ID_GXBB) {
b9164398 2846 /*
e0614bf7
ZZ
2847 *enable VDEC_1 DMC request
2848 */
b9164398
NQ
2849 unsigned long flags;
2850
2851 spin_lock_irqsave(&vdec_spin_lock, flags);
2852 codec_dmcbus_write(DMC_REQ_CTRL,
2853 codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13));
2854 spin_unlock_irqrestore(&vdec_spin_lock, flags);
2855 }
2856 } else if (core == VDEC_2) {
2857 if (has_vdec2()) {
2858 /* vdec2 power on */
2859 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
2860 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
2861 ~0x30);
2862 /* wait 10uS */
2863 udelay(10);
2864 /* vdec2 soft reset */
2865 WRITE_VREG(DOS_SW_RESET2, 0xffffffff);
2866 WRITE_VREG(DOS_SW_RESET2, 0);
2867 /* enable vdec1 clock */
2868 vdec2_clock_hi_enable();
2869 /* power up vdec memories */
2870 WRITE_VREG(DOS_MEM_PD_VDEC2, 0);
2871 /* remove vdec2 isolation */
2872 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
2873 READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
2874 ~0x300);
2875 /* reset DOS top registers */
2876 WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0);
2877 }
2878 } else if (core == VDEC_HCODEC) {
2879 if (has_hdec()) {
2880 /* hcodec power on */
2881 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
6f5ee885
NQ
2882 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
2883 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
2884 ? ~0x1 : ~0x3));
b9164398
NQ
2885 /* wait 10uS */
2886 udelay(10);
2887 /* hcodec soft reset */
2888 WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
2889 WRITE_VREG(DOS_SW_RESET1, 0);
2890 /* enable hcodec clock */
2891 hcodec_clock_enable();
2892 /* power up hcodec memories */
2893 WRITE_VREG(DOS_MEM_PD_HCODEC, 0);
2894 /* remove hcodec isolation */
2895 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
6f5ee885
NQ
2896 READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
2897 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
2898 ? ~0x1 : ~0x30));
b9164398
NQ
2899 }
2900 } else if (core == VDEC_HEVC) {
2901 if (has_hevc_vdec()) {
2902 bool hevc_fixed = false;
2903
2904 while (!hevc_fixed) {
2905 /* hevc power on */
2906 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
2907 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
6f5ee885
NQ
2908 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
2909 ? ~0x4 : ~0xc0));
b9164398
NQ
2910 /* wait 10uS */
2911 udelay(10);
2912 /* hevc soft reset */
2913 WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
2914 WRITE_VREG(DOS_SW_RESET3, 0);
2915 /* enable hevc clock */
65a98643
NQ
2916 amports_switch_gate("clk_hevc_mux", 1);
2917 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
2918 amports_switch_gate("clk_hevcb_mux", 1);
b9164398 2919 hevc_clock_hi_enable();
118bcc65 2920 hevc_back_clock_hi_enable();
b9164398
NQ
2921 /* power up hevc memories */
2922 WRITE_VREG(DOS_MEM_PD_HEVC, 0);
2923 /* remove hevc isolation */
2924 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
2925 READ_AOREG(AO_RTI_GEN_PWR_ISO0) &
6f5ee885
NQ
2926 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
2927 ? ~0x4 : ~0xc00));
b9164398
NQ
2928
2929 if (!hevc_workaround_needed())
2930 break;
2931
2932 if (decomp_addr)
2933 hevc_fixed = test_hevc(
2934 decomp_addr_aligned, 20);
2935
2936 if (!hevc_fixed) {
2937 hevc_loop++;
2938
2939 mutex_unlock(&vdec_mutex);
2940
2941 if (hevc_loop >= HEVC_TEST_LIMIT) {
2942 pr_warn("hevc power sequence over limit\n");
2943 pr_warn("=====================================================\n");
2944 pr_warn(" This chip is identified to have HW failure.\n");
2945 pr_warn(" Please contact sqa-platform to replace the platform.\n");
2946 pr_warn("=====================================================\n");
2947
2948 panic("Force panic for chip detection !!!\n");
2949
2950 break;
2951 }
2952
2953 vdec_poweroff(VDEC_HEVC);
2954
2955 mdelay(10);
2956
2957 mutex_lock(&vdec_mutex);
2958 }
2959 }
2960
2961 if (hevc_loop > hevc_max_reset_count)
2962 hevc_max_reset_count = hevc_loop;
2963
2964 WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
2965 udelay(10);
2966 WRITE_VREG(DOS_SW_RESET3, 0);
2967 }
2968 }
2969
2970 if (decomp_addr)
2971 codec_mm_dma_free_coherent(MEM_NAME,
2972 SZ_64K + SZ_4K, decomp_addr, decomp_dma_addr, 0);
2973
2974 mutex_unlock(&vdec_mutex);
2975}
2976EXPORT_SYMBOL(vdec_poweron);
2977
2978void vdec_poweroff(enum vdec_type_e core)
2979{
2980 if (core >= VDEC_MAX)
2981 return;
2982
2983 mutex_lock(&vdec_mutex);
2984
2985 vdec_core->power_ref_count[core]--;
2986 if (vdec_core->power_ref_count[core] > 0) {
2987 mutex_unlock(&vdec_mutex);
2988 return;
2989 }
2990
2991 if (core == VDEC_1) {
63e810c0
CG
2992 if (get_cpu_major_id() >=
2993 AM_MESON_CPU_MAJOR_ID_GXBB) {
b9164398
NQ
2994 /* disable VDEC_1 DMC REQ*/
2995 unsigned long flags;
2996
2997 spin_lock_irqsave(&vdec_spin_lock, flags);
2998 codec_dmcbus_write(DMC_REQ_CTRL,
2999 codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13)));
3000 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3001 udelay(10);
3002 }
3003 /* enable vdec1 isolation */
3004 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
6f5ee885
NQ
3005 READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
3006 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3007 ? 0x2 : 0xc0));
b9164398
NQ
3008 /* power off vdec1 memories */
3009 WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
3010 /* disable vdec1 clock */
3011 vdec_clock_off();
3012 /* vdec1 power off */
3013 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
6f5ee885
NQ
3014 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
3015 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3016 ? 0x2 : 0xc));
b9164398
NQ
3017 } else if (core == VDEC_2) {
3018 if (has_vdec2()) {
3019 /* enable vdec2 isolation */
3020 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
3021 READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
3022 0x300);
3023 /* power off vdec2 memories */
3024 WRITE_VREG(DOS_MEM_PD_VDEC2, 0xffffffffUL);
3025 /* disable vdec2 clock */
3026 vdec2_clock_off();
3027 /* vdec2 power off */
3028 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
3029 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
3030 0x30);
3031 }
3032 } else if (core == VDEC_HCODEC) {
3033 if (has_hdec()) {
3034 /* enable hcodec isolation */
3035 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
6f5ee885
NQ
3036 READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
3037 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3038 ? 0x1 : 0x30));
b9164398
NQ
3039 /* power off hcodec memories */
3040 WRITE_VREG(DOS_MEM_PD_HCODEC, 0xffffffffUL);
3041 /* disable hcodec clock */
3042 hcodec_clock_off();
3043 /* hcodec power off */
3044 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
6f5ee885
NQ
3045 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
3046 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3047 ? 0x1 : 3));
b9164398
NQ
3048 }
3049 } else if (core == VDEC_HEVC) {
3050 if (has_hevc_vdec()) {
28e318df
NQ
3051 if (no_powerdown == 0) {
3052 /* enable hevc isolation */
3053 WRITE_AOREG(AO_RTI_GEN_PWR_ISO0,
b9164398 3054 READ_AOREG(AO_RTI_GEN_PWR_ISO0) |
6f5ee885
NQ
3055 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3056 ? 0x4 : 0xc00));
b9164398
NQ
3057 /* power off hevc memories */
3058 WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
a6c89e96 3059
b9164398
NQ
3060 /* disable hevc clock */
3061 hevc_clock_off();
63e810c0 3062 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
a6c89e96
NQ
3063 hevc_back_clock_off();
3064
b9164398
NQ
3065 /* hevc power off */
3066 WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
6f5ee885
NQ
3067 READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
3068 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3069 ? 0x4 : 0xc0));
28e318df
NQ
3070 } else {
3071 pr_info("!!!!!!!!not power down\n");
3072 hevc_reset_core(NULL);
3073 no_powerdown = 0;
3074 }
b9164398
NQ
3075 }
3076 }
3077 mutex_unlock(&vdec_mutex);
3078}
3079EXPORT_SYMBOL(vdec_poweroff);
3080
3081bool vdec_on(enum vdec_type_e core)
3082{
3083 bool ret = false;
3084
3085 if (core == VDEC_1) {
6f5ee885
NQ
3086 if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
3087 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3088 ? 0x2 : 0xc)) == 0) &&
b9164398
NQ
3089 (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100))
3090 ret = true;
3091 } else if (core == VDEC_2) {
3092 if (has_vdec2()) {
3093 if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) & 0x30) == 0) &&
3094 (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100))
3095 ret = true;
3096 }
3097 } else if (core == VDEC_HCODEC) {
3098 if (has_hdec()) {
6f5ee885
NQ
3099 if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
3100 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3101 ? 0x1 : 0x3)) == 0) &&
b9164398
NQ
3102 (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000))
3103 ret = true;
3104 }
3105 } else if (core == VDEC_HEVC) {
3106 if (has_hevc_vdec()) {
6f5ee885
NQ
3107 if (((READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) &
3108 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SM1
3109 ? 0x4 : 0xc0)) == 0) &&
b9164398
NQ
3110 (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x1000000))
3111 ret = true;
3112 }
3113 }
3114
3115 return ret;
3116}
3117EXPORT_SYMBOL(vdec_on);
3118
3119#elif 0 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
3120void vdec_poweron(enum vdec_type_e core)
3121{
3122 ulong flags;
3123
3124 spin_lock_irqsave(&lock, flags);
3125
3126 if (core == VDEC_1) {
3127 /* vdec1 soft reset */
3128 WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
3129 WRITE_VREG(DOS_SW_RESET0, 0);
3130 /* enable vdec1 clock */
3131 vdec_clock_enable();
3132 /* reset DOS top registers */
3133 WRITE_VREG(DOS_VDEC_MCRCC_STALL_CTRL, 0);
3134 } else if (core == VDEC_2) {
3135 /* vdec2 soft reset */
3136 WRITE_VREG(DOS_SW_RESET2, 0xffffffff);
3137 WRITE_VREG(DOS_SW_RESET2, 0);
3138 /* enable vdec2 clock */
3139 vdec2_clock_enable();
3140 /* reset DOS top registers */
3141 WRITE_VREG(DOS_VDEC2_MCRCC_STALL_CTRL, 0);
3142 } else if (core == VDEC_HCODEC) {
3143 /* hcodec soft reset */
3144 WRITE_VREG(DOS_SW_RESET1, 0xffffffff);
3145 WRITE_VREG(DOS_SW_RESET1, 0);
3146 /* enable hcodec clock */
3147 hcodec_clock_enable();
3148 }
3149
3150 spin_unlock_irqrestore(&lock, flags);
3151}
3152
3153void vdec_poweroff(enum vdec_type_e core)
3154{
3155 ulong flags;
3156
3157 spin_lock_irqsave(&lock, flags);
3158
3159 if (core == VDEC_1) {
3160 /* disable vdec1 clock */
3161 vdec_clock_off();
3162 } else if (core == VDEC_2) {
3163 /* disable vdec2 clock */
3164 vdec2_clock_off();
3165 } else if (core == VDEC_HCODEC) {
3166 /* disable hcodec clock */
3167 hcodec_clock_off();
3168 }
3169
3170 spin_unlock_irqrestore(&lock, flags);
3171}
3172
3173bool vdec_on(enum vdec_type_e core)
3174{
3175 bool ret = false;
3176
3177 if (core == VDEC_1) {
3178 if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x100)
3179 ret = true;
3180 } else if (core == VDEC_2) {
3181 if (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0x100)
3182 ret = true;
3183 } else if (core == VDEC_HCODEC) {
3184 if (READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x1000000)
3185 ret = true;
3186 }
3187
3188 return ret;
3189}
3190#endif
3191
3192int vdec_source_changed(int format, int width, int height, int fps)
3193{
3194 /* todo: add level routines for clock adjustment per chips */
3195 int ret = -1;
3196 static int on_setting;
3197
3198 if (on_setting > 0)
3199 return ret;/*on changing clk,ignore this change*/
3200
3201 if (vdec_source_get(VDEC_1) == width * height * fps)
3202 return ret;
3203
3204
3205 on_setting = 1;
3206 ret = vdec_source_changed_for_clk_set(format, width, height, fps);
5b851ff9 3207 pr_debug("vdec1 video changed to %d x %d %d fps clk->%dMHZ\n",
b9164398
NQ
3208 width, height, fps, vdec_clk_get(VDEC_1));
3209 on_setting = 0;
3210 return ret;
3211
3212}
3213EXPORT_SYMBOL(vdec_source_changed);
3214
ecd31bc4 3215void vdec_disable_DMC(struct vdec_s *vdec)
3216{
3217 /*close first,then wait pedding end,timing suggestion from vlsi*/
3218 unsigned long flags;
3219 spin_lock_irqsave(&vdec_spin_lock, flags);
3220 codec_dmcbus_write(DMC_REQ_CTRL,
3221 codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13)));
3222 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3223
3224 while (!(codec_dmcbus_read(DMC_CHAN_STS)
3225 & (1 << 13)))
3226 ;
3227}
3228EXPORT_SYMBOL(vdec_disable_DMC);
3229
3230void vdec_enable_DMC(struct vdec_s *vdec)
3231{
3232 unsigned long flags;
3233 spin_lock_irqsave(&vdec_spin_lock, flags);
3234 codec_dmcbus_write(DMC_REQ_CTRL,
3235 codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13));
3236 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3237}
3238
3239EXPORT_SYMBOL(vdec_enable_DMC);
3240
87046a60 3241void vdec_reset_core(struct vdec_s *vdec)
3242{
3243 unsigned long flags;
3244 spin_lock_irqsave(&vdec_spin_lock, flags);
3245 codec_dmcbus_write(DMC_REQ_CTRL,
3246 codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 13)));
3247 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3248
3249 while (!(codec_dmcbus_read(DMC_CHAN_STS)
3250 & (1 << 13)))
3251 ;
3252 /*
3253 * 2: assist
3254 * 3: vld_reset
3255 * 4: vld_part_reset
3256 * 5: vfifo reset
3257 * 6: iqidct
3258 * 7: mc
3259 * 8: dblk
3260 * 9: pic_dc
3261 * 10: psc
3262 * 11: mcpu
3263 * 12: ccpu
3264 * 13: ddr
3265 * 14: afifo
3266 */
3267
3268 WRITE_VREG(DOS_SW_RESET0,
3269 (1<<3)|(1<<4)|(1<<5));
3270
3271 WRITE_VREG(DOS_SW_RESET0, 0);
3272
3273 spin_lock_irqsave(&vdec_spin_lock, flags);
3274 codec_dmcbus_write(DMC_REQ_CTRL,
3275 codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 13));
3276 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3277}
3278EXPORT_SYMBOL(vdec_reset_core);
3279
fe96802b
NQ
3280void hevc_reset_core(struct vdec_s *vdec)
3281{
3282 unsigned long flags;
3283 WRITE_VREG(HEVC_STREAM_CONTROL, 0);
3284 spin_lock_irqsave(&vdec_spin_lock, flags);
3285 codec_dmcbus_write(DMC_REQ_CTRL,
3286 codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4)));
3287 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3288
3289 while (!(codec_dmcbus_read(DMC_CHAN_STS)
3290 & (1 << 4)))
3291 ;
3292
28e318df 3293 if (vdec == NULL || input_frame_based(vdec))
fe96802b
NQ
3294 WRITE_VREG(HEVC_STREAM_CONTROL, 0);
3295
3296 /*
3297 * 2: assist
3298 * 3: parser
3299 * 4: parser_state
3300 * 8: dblk
3301 * 11:mcpu
3302 * 12:ccpu
3303 * 13:ddr
3304 * 14:iqit
3305 * 15:ipp
3306 * 17:qdct
3307 * 18:mpred
3308 * 19:sao
3309 * 24:hevc_afifo
3310 */
3311 WRITE_VREG(DOS_SW_RESET3,
3312 (1<<3)|(1<<4)|(1<<8)|(1<<11)|
3313 (1<<12)|(1<<13)|(1<<14)|(1<<15)|
3314 (1<<17)|(1<<18)|(1<<19)|(1<<24));
3315
3316 WRITE_VREG(DOS_SW_RESET3, 0);
3317
3318
3319 spin_lock_irqsave(&vdec_spin_lock, flags);
3320 codec_dmcbus_write(DMC_REQ_CTRL,
3321 codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4));
3322 spin_unlock_irqrestore(&vdec_spin_lock, flags);
3323
3324}
3325EXPORT_SYMBOL(hevc_reset_core);
3326
b9164398
NQ
3327int vdec2_source_changed(int format, int width, int height, int fps)
3328{
3329 int ret = -1;
3330 static int on_setting;
3331
3332 if (has_vdec2()) {
3333 /* todo: add level routines for clock adjustment per chips */
3334 if (on_setting != 0)
3335 return ret;/*on changing clk,ignore this change*/
3336
3337 if (vdec_source_get(VDEC_2) == width * height * fps)
3338 return ret;
3339
3340 on_setting = 1;
3341 ret = vdec_source_changed_for_clk_set(format,
3342 width, height, fps);
5b851ff9 3343 pr_debug("vdec2 video changed to %d x %d %d fps clk->%dMHZ\n",
b9164398
NQ
3344 width, height, fps, vdec_clk_get(VDEC_2));
3345 on_setting = 0;
3346 return ret;
3347 }
3348 return 0;
3349}
3350EXPORT_SYMBOL(vdec2_source_changed);
3351
3352int hevc_source_changed(int format, int width, int height, int fps)
3353{
3354 /* todo: add level routines for clock adjustment per chips */
3355 int ret = -1;
3356 static int on_setting;
3357
3358 if (on_setting != 0)
3359 return ret;/*on changing clk,ignore this change*/
3360
3361 if (vdec_source_get(VDEC_HEVC) == width * height * fps)
3362 return ret;
3363
3364 on_setting = 1;
3365 ret = vdec_source_changed_for_clk_set(format, width, height, fps);
5b851ff9 3366 pr_debug("hevc video changed to %d x %d %d fps clk->%dMHZ\n",
b9164398
NQ
3367 width, height, fps, vdec_clk_get(VDEC_HEVC));
3368 on_setting = 0;
3369
3370 return ret;
3371}
3372EXPORT_SYMBOL(hevc_source_changed);
3373
b9164398
NQ
3374static struct am_reg am_risc[] = {
3375 {"MSP", 0x300},
3376 {"MPSR", 0x301},
3377 {"MCPU_INT_BASE", 0x302},
3378 {"MCPU_INTR_GRP", 0x303},
3379 {"MCPU_INTR_MSK", 0x304},
3380 {"MCPU_INTR_REQ", 0x305},
3381 {"MPC-P", 0x306},
3382 {"MPC-D", 0x307},
3383 {"MPC_E", 0x308},
3384 {"MPC_W", 0x309},
3385 {"CSP", 0x320},
3386 {"CPSR", 0x321},
3387 {"CCPU_INT_BASE", 0x322},
3388 {"CCPU_INTR_GRP", 0x323},
3389 {"CCPU_INTR_MSK", 0x324},
3390 {"CCPU_INTR_REQ", 0x325},
3391 {"CPC-P", 0x326},
3392 {"CPC-D", 0x327},
3393 {"CPC_E", 0x328},
3394 {"CPC_W", 0x329},
3395 {"AV_SCRATCH_0", 0x09c0},
3396 {"AV_SCRATCH_1", 0x09c1},
3397 {"AV_SCRATCH_2", 0x09c2},
3398 {"AV_SCRATCH_3", 0x09c3},
3399 {"AV_SCRATCH_4", 0x09c4},
3400 {"AV_SCRATCH_5", 0x09c5},
3401 {"AV_SCRATCH_6", 0x09c6},
3402 {"AV_SCRATCH_7", 0x09c7},
3403 {"AV_SCRATCH_8", 0x09c8},
3404 {"AV_SCRATCH_9", 0x09c9},
3405 {"AV_SCRATCH_A", 0x09ca},
3406 {"AV_SCRATCH_B", 0x09cb},
3407 {"AV_SCRATCH_C", 0x09cc},
3408 {"AV_SCRATCH_D", 0x09cd},
3409 {"AV_SCRATCH_E", 0x09ce},
3410 {"AV_SCRATCH_F", 0x09cf},
3411 {"AV_SCRATCH_G", 0x09d0},
3412 {"AV_SCRATCH_H", 0x09d1},
3413 {"AV_SCRATCH_I", 0x09d2},
3414 {"AV_SCRATCH_J", 0x09d3},
3415 {"AV_SCRATCH_K", 0x09d4},
3416 {"AV_SCRATCH_L", 0x09d5},
3417 {"AV_SCRATCH_M", 0x09d6},
3418 {"AV_SCRATCH_N", 0x09d7},
3419};
3420
3421static ssize_t amrisc_regs_show(struct class *class,
3422 struct class_attribute *attr, char *buf)
3423{
3424 char *pbuf = buf;
3425 struct am_reg *regs = am_risc;
3426 int rsize = sizeof(am_risc) / sizeof(struct am_reg);
3427 int i;
e0614bf7 3428 unsigned int val;
b9164398
NQ
3429 ssize_t ret;
3430
63e810c0 3431 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
3432 mutex_lock(&vdec_mutex);
3433 if (!vdec_on(VDEC_1)) {
3434 mutex_unlock(&vdec_mutex);
3435 pbuf += sprintf(pbuf, "amrisc is power off\n");
3436 ret = pbuf - buf;
3437 return ret;
3438 }
63e810c0 3439 } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
3440 /*TODO:M6 define */
3441 /*
3442 * switch_mod_gate_by_type(MOD_VDEC, 1);
3443 */
3444 amports_switch_gate("vdec", 1);
3445 }
3446 pbuf += sprintf(pbuf, "amrisc registers show:\n");
3447 for (i = 0; i < rsize; i++) {
3448 val = READ_VREG(regs[i].offset);
3449 pbuf += sprintf(pbuf, "%s(%#x)\t:%#x(%d)\n",
3450 regs[i].name, regs[i].offset, val, val);
3451 }
63e810c0 3452 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
b9164398 3453 mutex_unlock(&vdec_mutex);
63e810c0 3454 else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
3455 /*TODO:M6 define */
3456 /*
3457 * switch_mod_gate_by_type(MOD_VDEC, 0);
3458 */
3459 amports_switch_gate("vdec", 0);
3460 }
3461 ret = pbuf - buf;
3462 return ret;
3463}
3464
3465static ssize_t dump_trace_show(struct class *class,
3466 struct class_attribute *attr, char *buf)
3467{
3468 int i;
3469 char *pbuf = buf;
3470 ssize_t ret;
3471 u16 *trace_buf = kmalloc(debug_trace_num * 2, GFP_KERNEL);
3472
3473 if (!trace_buf) {
3474 pbuf += sprintf(pbuf, "No Memory bug\n");
3475 ret = pbuf - buf;
3476 return ret;
3477 }
63e810c0 3478 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
3479 mutex_lock(&vdec_mutex);
3480 if (!vdec_on(VDEC_1)) {
3481 mutex_unlock(&vdec_mutex);
3482 kfree(trace_buf);
3483 pbuf += sprintf(pbuf, "amrisc is power off\n");
3484 ret = pbuf - buf;
3485 return ret;
3486 }
63e810c0 3487 } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
3488 /*TODO:M6 define */
3489 /*
3490 * switch_mod_gate_by_type(MOD_VDEC, 1);
3491 */
3492 amports_switch_gate("vdec", 1);
3493 }
3494 pr_info("dump trace steps:%d start\n", debug_trace_num);
3495 i = 0;
3496 while (i <= debug_trace_num - 16) {
3497 trace_buf[i] = READ_VREG(MPC_E);
3498 trace_buf[i + 1] = READ_VREG(MPC_E);
3499 trace_buf[i + 2] = READ_VREG(MPC_E);
3500 trace_buf[i + 3] = READ_VREG(MPC_E);
3501 trace_buf[i + 4] = READ_VREG(MPC_E);
3502 trace_buf[i + 5] = READ_VREG(MPC_E);
3503 trace_buf[i + 6] = READ_VREG(MPC_E);
3504 trace_buf[i + 7] = READ_VREG(MPC_E);
3505 trace_buf[i + 8] = READ_VREG(MPC_E);
3506 trace_buf[i + 9] = READ_VREG(MPC_E);
3507 trace_buf[i + 10] = READ_VREG(MPC_E);
3508 trace_buf[i + 11] = READ_VREG(MPC_E);
3509 trace_buf[i + 12] = READ_VREG(MPC_E);
3510 trace_buf[i + 13] = READ_VREG(MPC_E);
3511 trace_buf[i + 14] = READ_VREG(MPC_E);
3512 trace_buf[i + 15] = READ_VREG(MPC_E);
3513 i += 16;
3514 };
3515 pr_info("dump trace steps:%d finished\n", debug_trace_num);
63e810c0 3516 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
b9164398 3517 mutex_unlock(&vdec_mutex);
63e810c0 3518 else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
3519 /*TODO:M6 define */
3520 /*
3521 * switch_mod_gate_by_type(MOD_VDEC, 0);
3522 */
3523 amports_switch_gate("vdec", 0);
3524 }
3525 for (i = 0; i < debug_trace_num; i++) {
3526 if (i % 4 == 0) {
3527 if (i % 16 == 0)
3528 pbuf += sprintf(pbuf, "\n");
3529 else if (i % 8 == 0)
3530 pbuf += sprintf(pbuf, " ");
3531 else /* 4 */
3532 pbuf += sprintf(pbuf, " ");
3533 }
3534 pbuf += sprintf(pbuf, "%04x:", trace_buf[i]);
3535 }
3536 while (i < debug_trace_num)
3537 ;
3538 kfree(trace_buf);
3539 pbuf += sprintf(pbuf, "\n");
3540 ret = pbuf - buf;
3541 return ret;
3542}
3543
3544static ssize_t clock_level_show(struct class *class,
3545 struct class_attribute *attr, char *buf)
3546{
3547 char *pbuf = buf;
3548 size_t ret;
3549
3550 pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_1));
3551
3552 if (has_vdec2())
3553 pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_2));
3554
3555 if (has_hevc_vdec())
3556 pbuf += sprintf(pbuf, "%dMHZ\n", vdec_clk_get(VDEC_HEVC));
3557
3558 ret = pbuf - buf;
3559 return ret;
3560}
3561
3562static ssize_t store_poweron_clock_level(struct class *class,
3563 struct class_attribute *attr,
3564 const char *buf, size_t size)
3565{
e0614bf7 3566 unsigned int val;
b9164398
NQ
3567 ssize_t ret;
3568
3569 /*ret = sscanf(buf, "%d", &val);*/
3570 ret = kstrtoint(buf, 0, &val);
3571
3572 if (ret != 0)
3573 return -EINVAL;
3574 poweron_clock_level = val;
3575 return size;
3576}
3577
3578static ssize_t show_poweron_clock_level(struct class *class,
3579 struct class_attribute *attr, char *buf)
3580{
3581 return sprintf(buf, "%d\n", poweron_clock_level);
3582}
3583
3584/*
e0614bf7
ZZ
3585 *if keep_vdec_mem == 1
3586 *always don't release
3587 *vdec 64 memory for fast play.
3588 */
b9164398
NQ
3589static ssize_t store_keep_vdec_mem(struct class *class,
3590 struct class_attribute *attr,
3591 const char *buf, size_t size)
3592{
e0614bf7 3593 unsigned int val;
b9164398
NQ
3594 ssize_t ret;
3595
3596 /*ret = sscanf(buf, "%d", &val);*/
3597 ret = kstrtoint(buf, 0, &val);
3598 if (ret != 0)
3599 return -EINVAL;
3600 keep_vdec_mem = val;
3601 return size;
3602}
3603
3604static ssize_t show_keep_vdec_mem(struct class *class,
3605 struct class_attribute *attr, char *buf)
3606{
3607 return sprintf(buf, "%d\n", keep_vdec_mem);
3608}
3609
a6c89e96
NQ
3610#ifdef VDEC_DEBUG_SUPPORT
3611static ssize_t store_debug(struct class *class,
3612 struct class_attribute *attr,
3613 const char *buf, size_t size)
3614{
3615 struct vdec_s *vdec;
3616 struct vdec_core_s *core = vdec_core;
3617 unsigned long flags;
3618
3619 unsigned id;
3620 unsigned val;
3621 ssize_t ret;
3622 char cbuf[32];
3623
3624 cbuf[0] = 0;
3625 ret = sscanf(buf, "%s %x %x", cbuf, &id, &val);
3626 /*pr_info(
3627 "%s(%s)=>ret %ld: %s, %x, %x\n",
3628 __func__, buf, ret, cbuf, id, val);*/
3629 if (strcmp(cbuf, "schedule") == 0) {
3630 pr_info("VDEC_DEBUG: force schedule\n");
3631 up(&core->sem);
3632 } else if (strcmp(cbuf, "power_off") == 0) {
3633 pr_info("VDEC_DEBUG: power off core %d\n", id);
3634 vdec_poweroff(id);
3635 } else if (strcmp(cbuf, "power_on") == 0) {
3636 pr_info("VDEC_DEBUG: power_on core %d\n", id);
3637 vdec_poweron(id);
3638 } else if (strcmp(cbuf, "wr") == 0) {
3639 pr_info("VDEC_DEBUG: WRITE_VREG(0x%x, 0x%x)\n",
3640 id, val);
3641 WRITE_VREG(id, val);
3642 } else if (strcmp(cbuf, "rd") == 0) {
3643 pr_info("VDEC_DEBUG: READ_VREG(0x%x) = 0x%x\n",
3644 id, READ_VREG(id));
3645 } else if (strcmp(cbuf, "read_hevc_clk_reg") == 0) {
3646 pr_info(
3647 "VDEC_DEBUG: HHI_VDEC4_CLK_CNTL = 0x%x, HHI_VDEC2_CLK_CNTL = 0x%x\n",
3648 READ_HHI_REG(HHI_VDEC4_CLK_CNTL),
3649 READ_HHI_REG(HHI_VDEC2_CLK_CNTL));
3650 }
3651
3652 flags = vdec_core_lock(vdec_core);
3653
3654 list_for_each_entry(vdec,
3655 &core->connected_vdec_list, list) {
3656 pr_info("vdec: status %d, id %d\n", vdec->status, vdec->id);
3657 if (((vdec->status == VDEC_STATUS_CONNECTED
3658 || vdec->status == VDEC_STATUS_ACTIVE)) &&
3659 (vdec->id == id)) {
3660 /*to add*/
3661 break;
3662 }
3663 }
3664 vdec_core_unlock(vdec_core, flags);
3665 return size;
3666}
3667
3668static ssize_t show_debug(struct class *class,
3669 struct class_attribute *attr, char *buf)
3670{
3671 char *pbuf = buf;
3672 struct vdec_s *vdec;
3673 struct vdec_core_s *core = vdec_core;
3674 unsigned long flags = vdec_core_lock(vdec_core);
1e37ecab 3675 u64 tmp;
a6c89e96
NQ
3676
3677 pbuf += sprintf(pbuf,
3678 "============== help:\n");
3679 pbuf += sprintf(pbuf,
3680 "'echo xxx > debug' usuage:\n");
3681 pbuf += sprintf(pbuf,
3682 "schedule - trigger schedule thread to run\n");
3683 pbuf += sprintf(pbuf,
3684 "power_off core_num - call vdec_poweroff(core_num)\n");
3685 pbuf += sprintf(pbuf,
3686 "power_on core_num - call vdec_poweron(core_num)\n");
3687 pbuf += sprintf(pbuf,
3688 "wr adr val - call WRITE_VREG(adr, val)\n");
3689 pbuf += sprintf(pbuf,
3690 "rd adr - call READ_VREG(adr)\n");
3691 pbuf += sprintf(pbuf,
3692 "read_hevc_clk_reg - read HHI register for hevc clk\n");
3693 pbuf += sprintf(pbuf,
3694 "===================\n");
3695
3696 pbuf += sprintf(pbuf,
3697 "name(core)\tschedule_count\trun_count\tinput_underrun\tdecbuf_not_ready\trun_time\n");
3698 list_for_each_entry(vdec,
3699 &core->connected_vdec_list, list) {
3700 enum vdec_type_e type;
976f3376
HZ
3701 if ((vdec->status == VDEC_STATUS_CONNECTED
3702 || vdec->status == VDEC_STATUS_ACTIVE)) {
a6c89e96
NQ
3703 for (type = VDEC_1; type < VDEC_MAX; type++) {
3704 if (vdec->core_mask & (1 << type)) {
3705 pbuf += sprintf(pbuf, "%s(%d):",
3706 vdec->vf_provider_name, type);
3707 pbuf += sprintf(pbuf, "\t%d",
3708 vdec->check_count[type]);
3709 pbuf += sprintf(pbuf, "\t%d",
3710 vdec->run_count[type]);
3711 pbuf += sprintf(pbuf, "\t%d",
3712 vdec->input_underrun_count[type]);
3713 pbuf += sprintf(pbuf, "\t%d",
3714 vdec->not_run_ready_count[type]);
1e37ecab
AX
3715 tmp = vdec->run_clk[type] * 100;
3716 do_div(tmp, vdec->total_clk[type]);
a6c89e96
NQ
3717 pbuf += sprintf(pbuf,
3718 "\t%d%%\n",
3719 vdec->total_clk[type] == 0 ? 0 :
1e37ecab 3720 (u32)tmp);
a6c89e96
NQ
3721 }
3722 }
976f3376 3723 }
a6c89e96
NQ
3724 }
3725
3726 vdec_core_unlock(vdec_core, flags);
3727 return pbuf - buf;
3728
3729}
3730#endif
b9164398
NQ
3731
3732/*irq num as same as .dts*/
3733/*
e0614bf7
ZZ
3734 * interrupts = <0 3 1
3735 * 0 23 1
3736 * 0 32 1
3737 * 0 43 1
3738 * 0 44 1
3739 * 0 45 1>;
3740 * interrupt-names = "vsync",
3741 * "demux",
3742 * "parser",
3743 * "mailbox_0",
3744 * "mailbox_1",
3745 * "mailbox_2";
3746 */
b9164398
NQ
3747s32 vdec_request_threaded_irq(enum vdec_irq_num num,
3748 irq_handler_t handler,
3749 irq_handler_t thread_fn,
3750 unsigned long irqflags,
3751 const char *devname, void *dev)
3752{
3753 s32 res_irq;
3754 s32 ret = 0;
3755
3756 if (num >= VDEC_IRQ_MAX) {
3757 pr_err("[%s] request irq error, irq num too big!", __func__);
3758 return -EINVAL;
3759 }
3760
3761 if (vdec_core->isr_context[num].irq < 0) {
3762 res_irq = platform_get_irq(
3763 vdec_core->vdec_core_platform_device, num);
3764 if (res_irq < 0) {
3765 pr_err("[%s] get irq error!", __func__);
3766 return -EINVAL;
3767 }
3768
3769 vdec_core->isr_context[num].irq = res_irq;
3770 vdec_core->isr_context[num].dev_isr = handler;
3771 vdec_core->isr_context[num].dev_threaded_isr = thread_fn;
3772 vdec_core->isr_context[num].dev_id = dev;
3773
3774 ret = request_threaded_irq(res_irq,
3775 vdec_isr,
3776 vdec_thread_isr,
3777 (thread_fn) ? IRQF_ONESHOT : irqflags,
3778 devname,
3779 &vdec_core->isr_context[num]);
3780
3781 if (ret) {
3782 vdec_core->isr_context[num].irq = -1;
3783 vdec_core->isr_context[num].dev_isr = NULL;
3784 vdec_core->isr_context[num].dev_threaded_isr = NULL;
3785 vdec_core->isr_context[num].dev_id = NULL;
3786
3787 pr_err("vdec irq register error for %s.\n", devname);
3788 return -EIO;
3789 }
3790 } else {
3791 vdec_core->isr_context[num].dev_isr = handler;
3792 vdec_core->isr_context[num].dev_threaded_isr = thread_fn;
3793 vdec_core->isr_context[num].dev_id = dev;
3794 }
3795
3796 return ret;
3797}
3798EXPORT_SYMBOL(vdec_request_threaded_irq);
3799
3800s32 vdec_request_irq(enum vdec_irq_num num, irq_handler_t handler,
3801 const char *devname, void *dev)
3802{
5b851ff9 3803 pr_debug("vdec_request_irq %p, %s\n", handler, devname);
b9164398
NQ
3804
3805 return vdec_request_threaded_irq(num,
3806 handler,
3807 NULL,/*no thread_fn*/
3808 IRQF_SHARED,
3809 devname,
3810 dev);
3811}
3812EXPORT_SYMBOL(vdec_request_irq);
3813
3814void vdec_free_irq(enum vdec_irq_num num, void *dev)
3815{
3816 if (num >= VDEC_IRQ_MAX) {
3817 pr_err("[%s] request irq error, irq num too big!", __func__);
3818 return;
3819 }
b9164398 3820 /*
e0614bf7 3821 *assume amrisc is stopped already and there is no mailbox interrupt
b9164398
NQ
3822 * when we reset pointers here.
3823 */
3824 vdec_core->isr_context[num].dev_isr = NULL;
3825 vdec_core->isr_context[num].dev_threaded_isr = NULL;
3826 vdec_core->isr_context[num].dev_id = NULL;
5f3fbfb7 3827 synchronize_irq(vdec_core->isr_context[num].irq);
b9164398
NQ
3828}
3829EXPORT_SYMBOL(vdec_free_irq);
3830
a6c89e96
NQ
3831struct vdec_s *vdec_get_default_vdec_for_userdata(void)
3832{
3833 struct vdec_s *vdec;
3834 struct vdec_s *ret_vdec;
3835 struct vdec_core_s *core = vdec_core;
3836 unsigned long flags;
3837 int id;
3838
3839 flags = vdec_core_lock(vdec_core);
3840
3841 id = 0x10000000;
3842 ret_vdec = NULL;
3843 if (!list_empty(&core->connected_vdec_list)) {
3844 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
3845 if (vdec->id < id) {
3846 id = vdec->id;
3847 ret_vdec = vdec;
3848 }
3849 }
3850 }
3851
3852 vdec_core_unlock(vdec_core, flags);
3853
3854 return ret_vdec;
3855}
3856EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata);
3857
9cc3c918
RZ
3858struct vdec_s *vdec_get_vdec_by_id(int vdec_id)
3859{
3860 struct vdec_s *vdec;
3861 struct vdec_s *ret_vdec;
3862 struct vdec_core_s *core = vdec_core;
3863 unsigned long flags;
3864
3865 flags = vdec_core_lock(vdec_core);
3866
3867 ret_vdec = NULL;
3868 if (!list_empty(&core->connected_vdec_list)) {
3869 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
3870 if (vdec->id == vdec_id) {
3871 ret_vdec = vdec;
3872 break;
3873 }
3874 }
3875 }
3876
3877 vdec_core_unlock(vdec_core, flags);
3878
3879 return ret_vdec;
3880}
3881EXPORT_SYMBOL(vdec_get_vdec_by_id);
3882
a6c89e96
NQ
3883int vdec_read_user_data(struct vdec_s *vdec,
3884 struct userdata_param_t *p_userdata_param)
3885{
3886 int ret = 0;
3887
3888 if (!vdec)
3889 vdec = vdec_get_default_vdec_for_userdata();
3890
3891 if (vdec) {
3892 if (vdec->user_data_read)
3893 ret = vdec->user_data_read(vdec, p_userdata_param);
3894 }
3895 return ret;
3896}
3897EXPORT_SYMBOL(vdec_read_user_data);
3898
3899int vdec_wakeup_userdata_poll(struct vdec_s *vdec)
3900{
9cc3c918 3901 if (vdec) {
b78f4cd9 3902 if (vdec->wakeup_userdata_poll)
9cc3c918 3903 vdec->wakeup_userdata_poll(vdec);
b78f4cd9 3904 }
a6c89e96
NQ
3905
3906 return 0;
3907}
3908EXPORT_SYMBOL(vdec_wakeup_userdata_poll);
3909
3910void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
3911{
3912 if (!vdec)
3913 vdec = vdec_get_default_vdec_for_userdata();
3914
3915 if (vdec) {
3916 if (vdec->reset_userdata_fifo)
3917 vdec->reset_userdata_fifo(vdec, bInit);
3918 }
3919}
3920EXPORT_SYMBOL(vdec_reset_userdata_fifo);
3921
b9164398
NQ
3922static int dump_mode;
3923static ssize_t dump_risc_mem_store(struct class *class,
3924 struct class_attribute *attr,
3925 const char *buf, size_t size)/*set*/
3926{
e0614bf7 3927 unsigned int val;
b9164398
NQ
3928 ssize_t ret;
3929 char dump_mode_str[4] = "PRL";
3930
3931 /*ret = sscanf(buf, "%d", &val);*/
3932 ret = kstrtoint(buf, 0, &val);
3933
3934 if (ret != 0)
3935 return -EINVAL;
3936 dump_mode = val & 0x3;
3937 pr_info("set dump mode to %d,%c_mem\n",
3938 dump_mode, dump_mode_str[dump_mode]);
3939 return size;
3940}
3941static u32 read_amrisc_reg(int reg)
3942{
3943 WRITE_VREG(0x31b, reg);
3944 return READ_VREG(0x31c);
3945}
3946
3947static void dump_pmem(void)
3948{
3949 int i;
3950
3951 WRITE_VREG(0x301, 0x8000);
3952 WRITE_VREG(0x31d, 0);
3953 pr_info("start dump amrisc pmem of risc\n");
3954 for (i = 0; i < 0xfff; i++) {
3955 /*same as .o format*/
3956 pr_info("%08x // 0x%04x:\n", read_amrisc_reg(i), i);
3957 }
3958}
3959
3960static void dump_lmem(void)
3961{
3962 int i;
3963
3964 WRITE_VREG(0x301, 0x8000);
3965 WRITE_VREG(0x31d, 2);
3966 pr_info("start dump amrisc lmem\n");
3967 for (i = 0; i < 0x3ff; i++) {
3968 /*same as */
3969 pr_info("[%04x] = 0x%08x:\n", i, read_amrisc_reg(i));
3970 }
3971}
3972
3973static ssize_t dump_risc_mem_show(struct class *class,
3974 struct class_attribute *attr, char *buf)
3975{
3976 char *pbuf = buf;
3977 int ret;
3978
63e810c0 3979 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
3980 mutex_lock(&vdec_mutex);
3981 if (!vdec_on(VDEC_1)) {
3982 mutex_unlock(&vdec_mutex);
3983 pbuf += sprintf(pbuf, "amrisc is power off\n");
3984 ret = pbuf - buf;
3985 return ret;
3986 }
63e810c0 3987 } else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
3988 /*TODO:M6 define */
3989 /*
3990 * switch_mod_gate_by_type(MOD_VDEC, 1);
3991 */
3992 amports_switch_gate("vdec", 1);
3993 }
3994 /*start do**/
3995 switch (dump_mode) {
3996 case 0:
3997 dump_pmem();
3998 break;
3999 case 2:
4000 dump_lmem();
4001 break;
4002 default:
4003 break;
4004 }
4005
4006 /*done*/
63e810c0 4007 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
b9164398 4008 mutex_unlock(&vdec_mutex);
63e810c0 4009 else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
b9164398
NQ
4010 /*TODO:M6 define */
4011 /*
4012 * switch_mod_gate_by_type(MOD_VDEC, 0);
4013 */
4014 amports_switch_gate("vdec", 0);
4015 }
4016 return sprintf(buf, "done\n");
4017}
4018
4019static ssize_t core_show(struct class *class, struct class_attribute *attr,
4020 char *buf)
4021{
4022 struct vdec_core_s *core = vdec_core;
4023 char *pbuf = buf;
4024
4025 if (list_empty(&core->connected_vdec_list))
4026 pbuf += sprintf(pbuf, "connected vdec list empty\n");
4027 else {
4028 struct vdec_s *vdec;
4029
a6c89e96
NQ
4030 pbuf += sprintf(pbuf,
4031 " Core: last_sched %p, sched_mask %lx\n",
05afa03d 4032 core->last_vdec,
a6c89e96
NQ
4033 core->sched_mask);
4034
b9164398
NQ
4035 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
4036 pbuf += sprintf(pbuf,
a6c89e96 4037 "\tvdec.%d (%p (%s)), status = %s,\ttype = %s, \tactive_mask = %lx\n",
fe96802b
NQ
4038 vdec->id,
4039 vdec,
4040 vdec_device_name[vdec->format * 2],
b9164398 4041 vdec_status_str(vdec),
a6c89e96
NQ
4042 vdec_type_str(vdec),
4043 vdec->active_mask);
b9164398
NQ
4044 }
4045 }
4046
4047 return pbuf - buf;
4048}
4049
fe96802b
NQ
4050static ssize_t vdec_status_show(struct class *class,
4051 struct class_attribute *attr, char *buf)
4052{
4053 char *pbuf = buf;
4054 struct vdec_s *vdec;
4055 struct vdec_info vs;
4056 unsigned char vdec_num = 0;
4057 struct vdec_core_s *core = vdec_core;
4058 unsigned long flags = vdec_core_lock(vdec_core);
4059
4060 if (list_empty(&core->connected_vdec_list)) {
4061 pbuf += sprintf(pbuf, "No vdec.\n");
4062 goto out;
4063 }
4064
4065 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
9b670a2d 4066 if ((vdec->status == VDEC_STATUS_CONNECTED
4067 || vdec->status == VDEC_STATUS_ACTIVE)) {
fe96802b
NQ
4068 memset(&vs, 0, sizeof(vs));
4069 if (vdec_status(vdec, &vs)) {
4070 pbuf += sprintf(pbuf, "err.\n");
4071 goto out;
4072 }
4073 pbuf += sprintf(pbuf,
4074 "vdec channel %u statistics:\n",
4075 vdec_num);
4076 pbuf += sprintf(pbuf,
4077 "%13s : %s\n", "device name",
4078 vs.vdec_name);
4079 pbuf += sprintf(pbuf,
4080 "%13s : %u\n", "frame width",
4081 vs.frame_width);
4082 pbuf += sprintf(pbuf,
4083 "%13s : %u\n", "frame height",
4084 vs.frame_height);
4085 pbuf += sprintf(pbuf,
4086 "%13s : %u %s\n", "frame rate",
4087 vs.frame_rate, "fps");
4088 pbuf += sprintf(pbuf,
4089 "%13s : %u %s\n", "bit rate",
4090 vs.bit_rate / 1024 * 8, "kbps");
4091 pbuf += sprintf(pbuf,
4092 "%13s : %u\n", "status",
4093 vs.status);
4094 pbuf += sprintf(pbuf,
4095 "%13s : %u\n", "frame dur",
4096 vs.frame_dur);
4097 pbuf += sprintf(pbuf,
4098 "%13s : %u %s\n", "frame data",
4099 vs.frame_data / 1024, "KB");
4100 pbuf += sprintf(pbuf,
4101 "%13s : %u\n", "frame count",
4102 vs.frame_count);
4103 pbuf += sprintf(pbuf,
4104 "%13s : %u\n", "drop count",
4105 vs.drop_frame_count);
4106 pbuf += sprintf(pbuf,
4107 "%13s : %u\n", "fra err count",
4108 vs.error_frame_count);
4109 pbuf += sprintf(pbuf,
4110 "%13s : %u\n", "hw err count",
4111 vs.error_count);
4112 pbuf += sprintf(pbuf,
4113 "%13s : %llu %s\n\n", "total data",
4114 vs.total_data / 1024, "KB");
4115
4116 vdec_num++;
4117 }
4118 }
4119out:
4120 vdec_core_unlock(vdec_core, flags);
4121 return pbuf - buf;
4122}
4123
4124static ssize_t dump_vdec_blocks_show(struct class *class,
4125 struct class_attribute *attr, char *buf)
4126{
4127 struct vdec_core_s *core = vdec_core;
4128 char *pbuf = buf;
4129
4130 if (list_empty(&core->connected_vdec_list))
4131 pbuf += sprintf(pbuf, "connected vdec list empty\n");
4132 else {
4133 struct vdec_s *vdec;
4134 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
4135 pbuf += vdec_input_dump_blocks(&vdec->input,
4136 pbuf, PAGE_SIZE - (pbuf - buf));
4137 }
4138 }
4139
4140 return pbuf - buf;
4141}
4142static ssize_t dump_vdec_chunks_show(struct class *class,
4143 struct class_attribute *attr, char *buf)
4144{
4145 struct vdec_core_s *core = vdec_core;
4146 char *pbuf = buf;
4147
4148 if (list_empty(&core->connected_vdec_list))
4149 pbuf += sprintf(pbuf, "connected vdec list empty\n");
4150 else {
4151 struct vdec_s *vdec;
4152 list_for_each_entry(vdec, &core->connected_vdec_list, list) {
4153 pbuf += vdec_input_dump_chunks(&vdec->input,
4154 pbuf, PAGE_SIZE - (pbuf - buf));
4155 }
4156 }
4157
4158 return pbuf - buf;
4159}
4160
fe96802b
NQ
4161static ssize_t dump_decoder_state_show(struct class *class,
4162 struct class_attribute *attr, char *buf)
4163{
4164 char *pbuf = buf;
4165 struct vdec_s *vdec;
4166 struct vdec_core_s *core = vdec_core;
4167 unsigned long flags = vdec_core_lock(vdec_core);
4168
4169 if (list_empty(&core->connected_vdec_list)) {
4170 pbuf += sprintf(pbuf, "No vdec.\n");
4171 } else {
4172 list_for_each_entry(vdec,
4173 &core->connected_vdec_list, list) {
4174 if ((vdec->status == VDEC_STATUS_CONNECTED
4175 || vdec->status == VDEC_STATUS_ACTIVE)
4176 && vdec->dump_state)
4177 vdec->dump_state(vdec);
4178 }
4179 }
4180 vdec_core_unlock(vdec_core, flags);
4181
4182 return pbuf - buf;
4183}
d481db31 4184
97fe3d16
PY
4185static ssize_t dump_fps_show(struct class *class,
4186 struct class_attribute *attr, char *buf)
4187{
4188 char *pbuf = buf;
4189 struct vdec_core_s *core = vdec_core;
4190 int i;
4191
4192 unsigned long flags = vdec_fps_lock(vdec_core);
4193 for (i = 0; i < MAX_INSTANCE_MUN; i++)
4194 pbuf += sprintf(pbuf, "%d ", core->decode_fps[i].fps);
4195
4196 pbuf += sprintf(pbuf, "\n");
4197 vdec_fps_unlock(vdec_core, flags);
4198
4199 return pbuf - buf;
4200}
4201
d481db31 4202
fe96802b 4203
b9164398
NQ
4204static struct class_attribute vdec_class_attrs[] = {
4205 __ATTR_RO(amrisc_regs),
4206 __ATTR_RO(dump_trace),
4207 __ATTR_RO(clock_level),
4208 __ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP,
4209 show_poweron_clock_level, store_poweron_clock_level),
4210 __ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP,
4211 dump_risc_mem_show, dump_risc_mem_store),
4212 __ATTR(keep_vdec_mem, S_IRUGO | S_IWUSR | S_IWGRP,
4213 show_keep_vdec_mem, store_keep_vdec_mem),
4214 __ATTR_RO(core),
fe96802b
NQ
4215 __ATTR_RO(vdec_status),
4216 __ATTR_RO(dump_vdec_blocks),
4217 __ATTR_RO(dump_vdec_chunks),
d481db31 4218 __ATTR_RO(dump_decoder_state),
a6c89e96
NQ
4219#ifdef VDEC_DEBUG_SUPPORT
4220 __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP,
4221 show_debug, store_debug),
8458676f 4222#endif
4223#ifdef FRAME_CHECK
4224 __ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP,
4225 dump_yuv_show, dump_yuv_store),
4226 __ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP,
4227 frame_check_show, frame_check_store),
a6c89e96 4228#endif
97fe3d16 4229 __ATTR_RO(dump_fps),
b9164398
NQ
4230 __ATTR_NULL
4231};
4232
4233static struct class vdec_class = {
4234 .name = "vdec",
4235 .class_attrs = vdec_class_attrs,
4236 };
4237
b9164398
NQ
4238struct device *get_vdec_device(void)
4239{
4240 return &vdec_core->vdec_core_platform_device->dev;
4241}
4242EXPORT_SYMBOL(get_vdec_device);
4243
4244static int vdec_probe(struct platform_device *pdev)
4245{
4246 s32 i, r;
4247
4248 vdec_core = (struct vdec_core_s *)devm_kzalloc(&pdev->dev,
4249 sizeof(struct vdec_core_s), GFP_KERNEL);
4250 if (vdec_core == NULL) {
4251 pr_err("vdec core allocation failed.\n");
4252 return -ENOMEM;
4253 }
4254
4255 atomic_set(&vdec_core->vdec_nr, 0);
4256 sema_init(&vdec_core->sem, 1);
4257
4258 r = class_register(&vdec_class);
4259 if (r) {
4260 pr_info("vdec class create fail.\n");
4261 return r;
4262 }
4263
4264 vdec_core->vdec_core_platform_device = pdev;
4265
4266 platform_set_drvdata(pdev, vdec_core);
4267
4268 for (i = 0; i < VDEC_IRQ_MAX; i++) {
4269 vdec_core->isr_context[i].index = i;
4270 vdec_core->isr_context[i].irq = -1;
4271 }
4272
a6c89e96
NQ
4273 r = vdec_request_threaded_irq(VDEC_IRQ_0, NULL, NULL,
4274 IRQF_ONESHOT, "vdec-0", NULL);
4275 if (r < 0) {
4276 pr_err("vdec interrupt request failed\n");
4277 return r;
4278 }
4279
b9164398
NQ
4280 r = vdec_request_threaded_irq(VDEC_IRQ_1, NULL, NULL,
4281 IRQF_ONESHOT, "vdec-1", NULL);
4282 if (r < 0) {
4283 pr_err("vdec interrupt request failed\n");
4284 return r;
4285 }
a6c89e96 4286#if 0
df841122 4287 if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) {
a6c89e96
NQ
4288 r = vdec_request_threaded_irq(VDEC_IRQ_HEVC_BACK, NULL, NULL,
4289 IRQF_ONESHOT, "vdec-hevc_back", NULL);
4290 if (r < 0) {
4291 pr_err("vdec interrupt request failed\n");
4292 return r;
4293 }
4294 }
4295#endif
b9164398
NQ
4296 r = of_reserved_mem_device_init(&pdev->dev);
4297 if (r == 0)
4298 pr_info("vdec_probe done\n");
4299
4300 vdec_core->cma_dev = &pdev->dev;
4301
63e810c0 4302 if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_M8) {
b9164398
NQ
4303 /* default to 250MHz */
4304 vdec_clock_hi_enable();
4305 }
4306
63e810c0 4307 if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_GXBB) {
b9164398
NQ
4308 /* set vdec dmc request to urgent */
4309 WRITE_DMCREG(DMC_AM5_CHAN_CTRL, 0x3f203cf);
4310 }
b9164398
NQ
4311 INIT_LIST_HEAD(&vdec_core->connected_vdec_list);
4312 spin_lock_init(&vdec_core->lock);
05afa03d 4313 spin_lock_init(&vdec_core->canvas_lock);
97fe3d16 4314 spin_lock_init(&vdec_core->fps_lock);
fe96802b 4315 ida_init(&vdec_core->ida);
b9164398
NQ
4316 vdec_core->thread = kthread_run(vdec_core_thread, vdec_core,
4317 "vdec-core");
4318
158de7c4
HZ
4319 vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",__WQ_LEGACY |
4320 WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work");
4321 /*work queue priority lower than vdec-core.*/
b9164398
NQ
4322 return 0;
4323}
4324
4325static int vdec_remove(struct platform_device *pdev)
4326{
4327 int i;
4328
4329 for (i = 0; i < VDEC_IRQ_MAX; i++) {
4330 if (vdec_core->isr_context[i].irq >= 0) {
4331 free_irq(vdec_core->isr_context[i].irq,
4332 &vdec_core->isr_context[i]);
4333 vdec_core->isr_context[i].irq = -1;
4334 vdec_core->isr_context[i].dev_isr = NULL;
4335 vdec_core->isr_context[i].dev_threaded_isr = NULL;
4336 vdec_core->isr_context[i].dev_id = NULL;
4337 }
4338 }
4339
4340 kthread_stop(vdec_core->thread);
4341
fe96802b 4342 destroy_workqueue(vdec_core->vdec_core_wq);
b9164398
NQ
4343 class_unregister(&vdec_class);
4344
4345 return 0;
4346}
4347
4348static const struct of_device_id amlogic_vdec_dt_match[] = {
4349 {
4350 .compatible = "amlogic, vdec",
4351 },
4352 {},
4353};
4354
fe96802b 4355static struct mconfig vdec_configs[] = {
fe96802b
NQ
4356 MC_PU32("debug_trace_num", &debug_trace_num),
4357 MC_PI32("hevc_max_reset_count", &hevc_max_reset_count),
4358 MC_PU32("clk_config", &clk_config),
4359 MC_PI32("step_mode", &step_mode),
4360 MC_PI32("poweron_clock_level", &poweron_clock_level),
4361};
4362static struct mconfig_node vdec_node;
4363
b9164398
NQ
4364static struct platform_driver vdec_driver = {
4365 .probe = vdec_probe,
4366 .remove = vdec_remove,
4367 .driver = {
4368 .name = "vdec",
4369 .of_match_table = amlogic_vdec_dt_match,
4370 }
4371};
4372
f811c57d
TG
4373static struct codec_profile_t amvdec_input_profile = {
4374 .name = "vdec_input",
4375 .profile = "drm_framemode"
4376};
4377
b9164398
NQ
4378int vdec_module_init(void)
4379{
4380 if (platform_driver_register(&vdec_driver)) {
4381 pr_info("failed to register vdec module\n");
4382 return -ENODEV;
4383 }
fe96802b
NQ
4384 INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node,
4385 "vdec", vdec_configs, CONFIG_FOR_RW);
f811c57d 4386 vcodec_profile_register(&amvdec_input_profile);
b9164398
NQ
4387 return 0;
4388}
4389EXPORT_SYMBOL(vdec_module_init);
4390
4391void vdec_module_exit(void)
4392{
4393 platform_driver_unregister(&vdec_driver);
4394}
4395EXPORT_SYMBOL(vdec_module_exit);
4396
4397#if 0
4398static int __init vdec_module_init(void)
4399{
4400 if (platform_driver_register(&vdec_driver)) {
4401 pr_info("failed to register vdec module\n");
4402 return -ENODEV;
4403 }
fe96802b
NQ
4404 INIT_REG_NODE_CONFIGS("media.decoder", &vdec_node,
4405 "vdec", vdec_configs, CONFIG_FOR_RW);
b9164398
NQ
4406 return 0;
4407}
4408
4409static void __exit vdec_module_exit(void)
4410{
4411 platform_driver_unregister(&vdec_driver);
4412}
4413#endif
4414
4415static int vdec_mem_device_init(struct reserved_mem *rmem, struct device *dev)
4416{
b9164398
NQ
4417 vdec_core->cma_dev = dev;
4418
4419 return 0;
4420}
4421
4422static const struct reserved_mem_ops rmem_vdec_ops = {
4423 .device_init = vdec_mem_device_init,
4424};
4425
4426static int __init vdec_mem_setup(struct reserved_mem *rmem)
4427{
4428 rmem->ops = &rmem_vdec_ops;
4429 pr_info("vdec: reserved mem setup\n");
4430
4431 return 0;
4432}
4433
4434RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup);
a6c89e96
NQ
4435/*
4436uint force_hevc_clock_cntl;
4437EXPORT_SYMBOL(force_hevc_clock_cntl);
4438
4439module_param(force_hevc_clock_cntl, uint, 0664);
4440*/
158de7c4 4441module_param(debug, uint, 0664);
b9164398
NQ
4442module_param(debug_trace_num, uint, 0664);
4443module_param(hevc_max_reset_count, int, 0664);
4444module_param(clk_config, uint, 0664);
4445module_param(step_mode, int, 0664);
a6c89e96 4446module_param(debugflags, int, 0664);
05afa03d 4447module_param(parallel_decode, int, 0664);
97fe3d16
PY
4448module_param(fps_detection, int, 0664);
4449module_param(fps_clear, int, 0664);
fe96802b 4450
b9164398
NQ
4451/*
4452*module_init(vdec_module_init);
4453*module_exit(vdec_module_exit);
4454*/
fe96802b
NQ
4455#define CREATE_TRACE_POINTS
4456#include "vdec_trace.h"
b9164398
NQ
4457MODULE_DESCRIPTION("AMLOGIC vdec driver");
4458MODULE_LICENSE("GPL");
4459MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");