1 /*
2 * drivers/amlogic/media/stream_input/parser/stream_buffer_base.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 *
16 */
17 #define DEBUG
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/errno.h>
21 #include <linux/interrupt.h>
22 #include <linux/wait.h>
23 #include <linux/sched.h>
24 #include <linux/fs.h>
25 #include <linux/mutex.h>
26 #include <linux/slab.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/uaccess.h>
29 #include <linux/atomic.h>
30 #include <linux/delay.h>
31 #include <linux/amlogic/media/codec_mm/codec_mm.h>
32 #include "../../frame_provider/decoder/utils/vdec.h"
33 #include "amports_priv.h"
34 #include "stream_buffer_base.h"
35 #include "thread_rw.h"
36
37 #define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3)
38 #define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6)
39 #define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10)
40 #define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15)
41
42 static struct stream_buf_s vdec_buf_def = {
43 .reg_base = VLD_MEM_VIFIFO_REG_BASE,
44 .type = BUF_TYPE_VIDEO,
45 .buf_start = 0,
46 .buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
47 .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
48 .first_tstamp = INVALID_PTS
49 };
50
51 static struct stream_buf_s hevc_buf_def = {
52 .reg_base = HEVC_STREAM_REG_BASE,
53 .type = BUF_TYPE_HEVC,
54 .buf_start = 0,
55 .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
56 .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
57 .first_tstamp = INVALID_PTS
58 };
59
get_def_parms(int f)60 static struct stream_buf_s *get_def_parms(int f)
61 {
62 switch (f) {
63 case VFORMAT_HEVC:
64 case VFORMAT_AVS2:
65 case VFORMAT_AV1:
66 case VFORMAT_VP9:
67 return &hevc_buf_def;
68 default:
69 return &vdec_buf_def;
70 }
71 }
72
stream_buffer_base_init(struct stream_buf_s * stbuf,struct stream_buf_ops * ops,struct parser_args * pars)73 int stream_buffer_base_init(struct stream_buf_s *stbuf,
74 struct stream_buf_ops *ops,
75 struct parser_args *pars)
76 {
77 struct vdec_s *vdec =
78 container_of(stbuf, struct vdec_s, vbuf);
79 struct stream_port_s *port = NULL;
80 u32 format, width, height;
81
82 /* sanity check. */
83 if (WARN_ON(!stbuf) || WARN_ON(!ops))
84 return -EINVAL;
85
86 port = vdec->port;
87 format = vdec->port->vformat;
88 width = vdec->sys_info->width;
89 height = vdec->sys_info->height;
90
91 memcpy(stbuf, get_def_parms(format),
92 sizeof(*stbuf));
93
94 stbuf->id = vdec->id;
95 stbuf->is_hevc = ((format == VFORMAT_HEVC) ||
96 (format == VFORMAT_AVS2) ||
97 (format == VFORMAT_AV1) ||
98 (format == VFORMAT_VP9));
99 stbuf->for_4k = ((width * height) >
100 (1920 * 1088)) ? 1 : 0;
101 stbuf->is_multi_inst = !vdec_single(vdec);
102 memcpy(&stbuf->pars, pars, sizeof(*pars));
103
104 /* register ops func. */
105 stbuf->ops = ops;
106
107 return 0;
108 }
109 EXPORT_SYMBOL(stream_buffer_base_init);
110
stream_buffer_set_ext_buf(struct stream_buf_s * stbuf,ulong addr,u32 size)111 void stream_buffer_set_ext_buf(struct stream_buf_s *stbuf,
112 ulong addr,
113 u32 size)
114 {
115 stbuf->ext_buf_addr = addr;
116 stbuf->buf_size = size;
117 }
118 EXPORT_SYMBOL(stream_buffer_set_ext_buf);
119
stream_buffer_write_ex(struct file * file,struct stream_buf_s * stbuf,const char __user * buf,size_t count,int flags)120 ssize_t stream_buffer_write_ex(struct file *file,
121 struct stream_buf_s *stbuf,
122 const char __user *buf,
123 size_t count, int flags)
124 {
125 int r;
126 u32 len = count;
127
128 if (buf == NULL || count == 0)
129 return -EINVAL;
130
131 if (stbuf_space(stbuf) < count) {
132 if ((flags & 2) || ((file != NULL) &&
133 (file->f_flags & O_NONBLOCK))) {
134 len = stbuf_space(stbuf);
135 if (len < 256) /* <1k.do eagain, */
136 return -EAGAIN;
137 } else {
138 len = min(stbuf_canusesize(stbuf) / 8, len);
139 if (stbuf_space(stbuf) < len) {
140 r = stbuf_wait_space(stbuf, len);
141 if (r < 0)
142 return r;
143 }
144 }
145 }
146
147 stbuf->last_write_jiffies64 = jiffies_64;
148 stbuf->is_phybuf = (flags & 1);
149
150 len = min_t(u32, len, count);
151
152 r = stbuf->ops->write(stbuf, buf, len);
153
154 return r;
155 }
156 EXPORT_SYMBOL(stream_buffer_write_ex);
157
stream_buffer_write(struct file * file,struct stream_buf_s * stbuf,const char * buf,size_t count)158 int stream_buffer_write(struct file *file,
159 struct stream_buf_s *stbuf,
160 const char *buf,
161 size_t count)
162 {
163 if (stbuf->write_thread)
164 return threadrw_write(file, stbuf, buf, count);
165 else
166 return stream_buffer_write_ex(file, stbuf, buf, count, 0);
167 }
168 EXPORT_SYMBOL(stream_buffer_write);
169
170