blob: 7fcb5224c9340dd1071d768bc8da087f8a398e9f [file] [log] [blame]
Vinay Kalia3766b1e2012-01-11 18:58:41 -08001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/slab.h>
15#include <media/msm_vidc.h>
16#include "msm_vidc_internal.h"
17#include "msm_vdec.h"
18#include "msm_venc.h"
19#include "msm_vidc_common.h"
20#include "msm_smem.h"
21
22int msm_vidc_poll(void *instance, struct file *filp,
23 struct poll_table_struct *wait)
24{
25 int rc = 0;
26 struct msm_vidc_inst *inst = instance;
27 struct vb2_queue *outq = &inst->vb2_bufq[OUTPUT_PORT];
28 struct vb2_queue *capq = &inst->vb2_bufq[CAPTURE_PORT];
29 struct vb2_buffer *out_vb = NULL;
30 struct vb2_buffer *cap_vb = NULL;
31 unsigned long flags;
32 if (!outq->streaming && !capq->streaming) {
33 pr_err("Returning POLLERR from here: %d, %d\n",
34 outq->streaming, capq->streaming);
35 return POLLERR;
36 }
37 poll_wait(filp, &capq->done_wq, wait);
38 poll_wait(filp, &outq->done_wq, wait);
39 spin_lock_irqsave(&capq->done_lock, flags);
40 if (!list_empty(&capq->done_list))
41 cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer,
42 done_entry);
43 if (cap_vb && (cap_vb->state == VB2_BUF_STATE_DONE
44 || cap_vb->state == VB2_BUF_STATE_ERROR))
45 rc |= POLLIN | POLLRDNORM;
46 spin_unlock_irqrestore(&capq->done_lock, flags);
47 spin_lock_irqsave(&outq->done_lock, flags);
48 if (!list_empty(&outq->done_list))
49 out_vb = list_first_entry(&outq->done_list, struct vb2_buffer,
50 done_entry);
51 if (out_vb && (out_vb->state == VB2_BUF_STATE_DONE
52 || out_vb->state == VB2_BUF_STATE_ERROR))
53 rc |= POLLOUT | POLLWRNORM;
54 spin_unlock_irqrestore(&outq->done_lock, flags);
55 return rc;
56}
57
58int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
59{
60 struct msm_vidc_inst *inst = instance;
61 if (inst->session_type == MSM_VIDC_DECODER)
62 return msm_vdec_querycap(instance, cap);
63 else if (inst->session_type == MSM_VIDC_ENCODER)
64 return msm_venc_querycap(instance, cap);
65 return -EINVAL;
66}
67int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
68{
69 struct msm_vidc_inst *inst = instance;
70 if (inst->session_type == MSM_VIDC_DECODER)
71 return msm_vdec_enum_fmt(instance, f);
72 else if (inst->session_type == MSM_VIDC_ENCODER)
73 return msm_venc_enum_fmt(instance, f);
74 return -EINVAL;
75}
76int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
77{
78 struct msm_vidc_inst *inst = instance;
79 if (inst->session_type == MSM_VIDC_DECODER)
80 return msm_vdec_s_fmt(instance, f);
81 if (inst->session_type == MSM_VIDC_ENCODER)
82 return msm_venc_s_fmt(instance, f);
83 return -EINVAL;
84}
85int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
86{
87 struct msm_vidc_inst *inst = instance;
88 if (inst->session_type == MSM_VIDC_DECODER)
89 return msm_vdec_g_fmt(instance, f);
90 else if (inst->session_type == MSM_VIDC_ENCODER)
91 return msm_venc_g_fmt(instance, f);
92 return -EINVAL;
93}
94int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
95{
96 struct msm_vidc_inst *inst = instance;
97 if (inst->session_type == MSM_VIDC_DECODER)
98 return msm_vdec_s_ctrl(instance, control);
Ashray Kulkarnid2ab0e32012-04-03 18:40:29 -070099 if (inst->session_type == MSM_VIDC_ENCODER)
100 return msm_venc_s_ctrl(instance, control);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800101 return -EINVAL;
102}
103int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
104{
105 struct msm_vidc_inst *inst = instance;
106 if (inst->session_type == MSM_VIDC_DECODER)
107 return msm_vdec_g_ctrl(instance, control);
Ashray Kulkarnid2ab0e32012-04-03 18:40:29 -0700108 if (inst->session_type == MSM_VIDC_ENCODER)
109 return msm_venc_g_ctrl(instance, control);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800110 return -EINVAL;
111}
112int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
113{
114 struct msm_vidc_inst *inst = instance;
115 if (inst->session_type == MSM_VIDC_DECODER)
116 return msm_vdec_reqbufs(instance, b);
117 if (inst->session_type == MSM_VIDC_ENCODER)
118 return msm_venc_reqbufs(instance, b);
119 return -EINVAL;
120}
121
122int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b)
123{
124 struct msm_vidc_inst *inst = instance;
125 if (inst->session_type == MSM_VIDC_DECODER)
126 return msm_vdec_prepare_buf(instance, b);
127 if (inst->session_type == MSM_VIDC_ENCODER)
128 return msm_venc_prepare_buf(instance, b);
129 return -EINVAL;
130}
131
132int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
133{
134 struct msm_vidc_inst *inst = instance;
135 if (inst->session_type == MSM_VIDC_DECODER)
136 return msm_vdec_qbuf(instance, b);
137 if (inst->session_type == MSM_VIDC_ENCODER)
138 return msm_venc_qbuf(instance, b);
139 return -EINVAL;
140}
141
142int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
143{
144 struct msm_vidc_inst *inst = instance;
145 if (inst->session_type == MSM_VIDC_DECODER)
146 return msm_vdec_dqbuf(instance, b);
147 if (inst->session_type == MSM_VIDC_ENCODER)
148 return msm_venc_dqbuf(instance, b);
149 return -EINVAL;
150}
151
152int msm_vidc_streamon(void *instance, enum v4l2_buf_type i)
153{
154 struct msm_vidc_inst *inst = instance;
155 if (inst->session_type == MSM_VIDC_DECODER)
156 return msm_vdec_streamon(instance, i);
157 if (inst->session_type == MSM_VIDC_ENCODER)
158 return msm_venc_streamon(instance, i);
159 return -EINVAL;
160}
161
162int msm_vidc_streamoff(void *instance, enum v4l2_buf_type i)
163{
164 struct msm_vidc_inst *inst = instance;
165 if (inst->session_type == MSM_VIDC_DECODER)
166 return msm_vdec_streamoff(instance, i);
167 if (inst->session_type == MSM_VIDC_ENCODER)
168 return msm_venc_streamoff(instance, i);
169 return -EINVAL;
170}
171
172void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
173 unsigned long size, int write)
174{
175 return NULL;
176}
177
178void vidc_put_userptr(void *buf_priv)
179{
180}
181
182static const struct vb2_mem_ops msm_vidc_vb2_mem_ops = {
183 .get_userptr = vidc_get_userptr,
184 .put_userptr = vidc_put_userptr,
185};
186
187static inline int vb2_bufq_init(struct msm_vidc_inst *inst,
188 enum v4l2_buf_type type, enum session_type sess)
189{
190 struct vb2_queue *q = NULL;
191 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
192 q = &inst->vb2_bufq[CAPTURE_PORT];
193 } else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
194 q = &inst->vb2_bufq[OUTPUT_PORT];
195 } else {
196 pr_err("buf_type = %d not recognised\n", type);
197 return -EINVAL;
198 }
199 q->type = type;
200 q->io_modes = VB2_MMAP | VB2_USERPTR;
201 q->io_flags = 0;
202 if (sess == MSM_VIDC_DECODER)
203 q->ops = msm_vdec_get_vb2q_ops();
204 else if (sess == MSM_VIDC_ENCODER)
205 q->ops = msm_venc_get_vb2q_ops();
206 q->mem_ops = &msm_vidc_vb2_mem_ops;
207 q->drv_priv = inst;
208 return vb2_queue_init(q);
209}
210
211void *msm_vidc_open(int core_id, int session_type)
212{
213 struct msm_vidc_inst *inst = NULL;
214 struct msm_vidc_core *core = NULL;
215 unsigned long flags;
216 int rc = 0;
217 int i = 0;
218 if (core_id >= MSM_VIDC_CORES_MAX ||
219 session_type >= MSM_VIDC_MAX_DEVICES) {
220 pr_err("Invalid input, core_id = %d, session = %d\n",
221 core_id, session_type);
222 goto err_invalid_core;
223 }
224 core = get_vidc_core(core_id);
225 if (!core) {
226 pr_err("Failed to find core for core_id = %d\n", core_id);
227 goto err_invalid_core;
228 }
229
230 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
231 if (!inst) {
232 pr_err("Unable to allocate video instance\n");
233 goto err_no_mem;
234 }
235 mutex_init(&inst->sync_lock);
236 spin_lock_init(&inst->lock);
237 inst->session_type = session_type;
238 INIT_LIST_HEAD(&inst->pendingq);
239 INIT_LIST_HEAD(&inst->internalbufs);
240 INIT_LIST_HEAD(&inst->extradatabufs);
241 inst->state = MSM_VIDC_CORE_UNINIT_DONE;
242 inst->core = core;
243 for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
244 i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) {
245 init_completion(&inst->completions[i]);
246 }
247 inst->mem_client = msm_smem_new_client(SMEM_ION);
248 if (!inst->mem_client) {
249 pr_err("Failed to create memory client\n");
250 goto fail_mem_client;
251 }
252 if (session_type == MSM_VIDC_DECODER) {
253 msm_vdec_inst_init(inst);
254 msm_vdec_ctrl_init(inst);
255 } else if (session_type == MSM_VIDC_ENCODER) {
256 msm_venc_inst_init(inst);
257 }
258 rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
259 session_type);
260 if (rc) {
261 pr_err("Failed to initialize vb2 queue on capture port\n");
262 goto fail_init;
263 }
264 rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
265 session_type);
266 if (rc) {
267 pr_err("Failed to initialize vb2 queue on capture port\n");
268 goto fail_init;
269 }
270 rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT);
271 if (rc) {
272 pr_err("Failed to move video instance to init state\n");
273 goto fail_init;
274 }
275 spin_lock_irqsave(&core->lock, flags);
276 list_add_tail(&inst->list, &core->instances);
277 spin_unlock_irqrestore(&core->lock, flags);
278 return inst;
279fail_init:
280 msm_smem_delete_client(inst->mem_client);
281fail_mem_client:
282 kfree(inst);
283 inst = NULL;
284err_no_mem:
285err_invalid_core:
286 return inst;
287}
288
289static void cleanup_instance(struct msm_vidc_inst *inst)
290{
291 unsigned long flags;
292 struct list_head *ptr, *next;
293 struct vb2_buf_entry *entry;
294 struct internal_buf *buf;
295 struct extradata_buf *ebuf;
296 if (inst) {
297 spin_lock_irqsave(&inst->lock, flags);
298 list_for_each_safe(ptr, next, &inst->pendingq) {
299 entry = list_entry(ptr, struct vb2_buf_entry, list);
300 list_del(&entry->list);
301 kfree(entry);
302 }
303 list_for_each_safe(ptr, next, &inst->internalbufs) {
304 buf = list_entry(ptr, struct internal_buf, list);
305 list_del(&buf->list);
306 msm_smem_free(inst->mem_client, buf->handle);
307 kfree(buf);
308 }
309 list_for_each_safe(ptr, next, &inst->extradatabufs) {
310 ebuf = list_entry(ptr, struct extradata_buf, list);
311 list_del(&ebuf->list);
312 msm_smem_free(inst->mem_client, ebuf->handle);
313 kfree(ebuf);
314 }
315 spin_unlock_irqrestore(&inst->lock, flags);
316 msm_smem_delete_client(inst->mem_client);
317 }
318}
319
320int msm_vidc_close(void *instance)
321{
322 struct msm_vidc_inst *inst = instance;
323 struct msm_vidc_inst *temp;
324 struct msm_vidc_core *core;
325 struct list_head *ptr, *next;
326 int rc = 0;
327 core = inst->core;
328 mutex_lock(&core->sync_lock);
329 list_for_each_safe(ptr, next, &core->instances) {
330 temp = list_entry(ptr, struct msm_vidc_inst, list);
331 if (temp == inst) {
332 list_del(&inst->list);
333 kfree(inst);
334 }
335 }
336 mutex_unlock(&core->sync_lock);
337 rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
338 if (rc)
339 pr_err("Failed to move video instance to init state\n");
340 cleanup_instance(inst);
341 pr_debug("Closed the instance\n");
342 return 0;
343}