• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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