summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/aml_vcodec_vfm.c (plain)
blob: 62896ea0e6a5d4ea92be40c1790dd980ef003d23
1/*
2* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12* more details.
13*
14* You should have received a copy of the GNU General Public License along
15* with this program; if not, write to the Free Software Foundation, Inc.,
16* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*
18* Description:
19*/
20#include "aml_vcodec_vfm.h"
21#include "aml_vcodec_vfq.h"
22#include "aml_vcodec_util.h"
23#include "aml_vcodec_adapt.h"
24#include <media/v4l2-mem2mem.h>
25
26#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO_COMPOSER
27#include <trace/events/meson_atrace.h>
28
29#define RECEIVER_NAME "v4l2-video"
30#define PROVIDER_NAME "v4l2-video"
31
32static struct vframe_s *vdec_vf_peek(void *op_arg)
33{
34 struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
35
36 return vfq_peek(&vfm->vf_que);
37}
38
39static struct vframe_s *vdec_vf_get(void *op_arg)
40{
41 struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
42
43 return vfq_pop(&vfm->vf_que);
44}
45
46static void vdec_vf_put(struct vframe_s *vf, void *op_arg)
47{
48 struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
49
50 /* If the video frame from amvide that means */
51 /* the data has been processed and finished, */
52 /* then push back to VDA. thus we don't put the */
53 /* buffer to the decoder directly.*/
54
55 //vf_put(vf, vfm->recv_name);
56 //vf_notify_provider(vfm->recv_name, VFRAME_EVENT_RECEIVER_PUT, NULL);
57
58 if (vfq_level(&vfm->vf_que_recycle) > POOL_SIZE - 1) {
59 v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_ERROR, "vfq full.\n");
60 return;
61 }
62
63 atomic_set(&vf->use_cnt, 1);
64
65 vfq_push(&vfm->vf_que_recycle, vf);
66
67 /* schedule capture work. */
68 vdec_device_vf_run(vfm->ctx);
69}
70
71static int vdec_event_cb(int type, void *data, void *private_data)
72{
73
74 if (type & VFRAME_EVENT_RECEIVER_PUT) {
75 } else if (type & VFRAME_EVENT_RECEIVER_GET) {
76 } else if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) {
77 }
78 return 0;
79}
80
81static int vdec_vf_states(struct vframe_states *states, void *op_arg)
82{
83 struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
84
85 states->vf_pool_size = POOL_SIZE;
86 states->buf_recycle_num = 0;
87 states->buf_free_num = POOL_SIZE - vfq_level(&vfm->vf_que);
88 states->buf_avail_num = vfq_level(&vfm->vf_que);
89
90 return 0;
91}
92
93void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id)
94{
95 struct vframe_provider_s *vfp = vf_get_provider(receiver);
96 struct vframe_s *vf = (struct vframe_s *)fb->vf_handle;
97
98 ATRACE_COUNTER("v4l2_to", vf->index_disp);
99
100 v4l_dbg(0, V4L_DEBUG_CODEC_OUTPUT,
101 "[%d]: TO (%s) vf: %p, idx: %d, "
102 "Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n",
103 id, vfp->name, vf, vf->index,
104 fb->m.mem[0].addr, fb->m.mem[0].size,
105 fb->m.mem[1].addr, fb->m.mem[1].size,
106 fb->m.mem[2].addr, fb->m.mem[2].size);
107
108 if (vfp && vf && atomic_dec_and_test(&vf->use_cnt))
109 vf_put(vf, receiver);
110}
111
112static const struct vframe_operations_s vf_provider = {
113 .peek = vdec_vf_peek,
114 .get = vdec_vf_get,
115 .put = vdec_vf_put,
116 .event_cb = vdec_event_cb,
117 .vf_states = vdec_vf_states,
118};
119
120static int video_receiver_event_fun(int type, void *data, void *private_data)
121{
122 int ret = 0;
123 struct vframe_states states;
124 struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data;
125
126 switch (type) {
127 case VFRAME_EVENT_PROVIDER_UNREG: {
128 if (vf_get_receiver(vfm->prov_name)) {
129 v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
130 "unreg %s provider.\n",
131 vfm->prov_name);
132 vf_unreg_provider(&vfm->vf_prov);
133 }
134
135 break;
136 }
137
138 case VFRAME_EVENT_PROVIDER_START: {
139 if (vf_get_receiver(vfm->prov_name)) {
140 v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
141 "reg %s provider.\n",
142 vfm->prov_name);
143 vf_provider_init(&vfm->vf_prov, vfm->prov_name,
144 &vf_provider, vfm);
145 vf_reg_provider(&vfm->vf_prov);
146 vf_notify_receiver(vfm->prov_name,
147 VFRAME_EVENT_PROVIDER_START, NULL);
148 }
149
150 vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]);
151 vfq_init(&vfm->vf_que_recycle, POOL_SIZE + 1, &vfm->pool_recycle[0]);
152
153 break;
154 }
155
156 case VFRAME_EVENT_PROVIDER_QUREY_STATE: {
157 vdec_vf_states(&states, vfm);
158 if (states.buf_avail_num > 0)
159 ret = RECEIVER_ACTIVE;
160 break;
161 }
162
163 case VFRAME_EVENT_PROVIDER_VFRAME_READY: {
164 if (vfq_level(&vfm->vf_que) > POOL_SIZE - 1)
165 ret = -1;
166
167 if (!vf_peek(vfm->recv_name))
168 ret = -1;
169
170 vfm->vf = vf_get(vfm->recv_name);
171 if (!vfm->vf)
172 ret = -1;
173
174 if (ret < 0) {
175 v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_ERROR, "receiver vf err.\n");
176 break;
177 }
178
179 vfq_push(&vfm->vf_que, vfm->vf);
180
181 if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO) {
182 vf_notify_receiver(vfm->prov_name,
183 VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
184 break;
185 }
186
187 /* schedule capture work. */
188 vdec_device_vf_run(vfm->ctx);
189
190 break;
191 }
192
193 default:
194 v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
195 "the vf event is %d", type);
196 }
197
198 return ret;
199}
200
201static const struct vframe_receiver_op_s vf_receiver = {
202 .event_cb = video_receiver_event_fun
203};
204
205struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm)
206{
207 if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO)
208 return vfq_peek(&vfm->vf_que_recycle);
209 else
210 return vfq_peek(&vfm->vf_que);
211}
212
213struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm)
214{
215 if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO)
216 return vfq_pop(&vfm->vf_que_recycle);
217 else
218 return vfq_pop(&vfm->vf_que);
219}
220
221int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
222{
223 int ret;
224
225 snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d",
226 RECEIVER_NAME, vfm->ctx->id);
227 snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d",
228 PROVIDER_NAME, vfm->ctx->id);
229
230 vfm->ada_ctx->recv_name = vfm->recv_name;
231
232 vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm);
233 ret = vf_reg_receiver(&vfm->vf_recv);
234
235 vfm->vfm_initialized = ret ? false : true;
236
237 return ret;
238}
239
240void vcodec_vfm_release(struct vcodec_vfm_s *vfm)
241{
242 if (vfm->vfm_initialized)
243 vf_unreg_receiver(&vfm->vf_recv);
244}
245
246