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