blob: eafb812213e9fd3d547915c9333820b5eb59b328 [file] [log] [blame]
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001/* Copyright (c) 2012-2017, The Linux Foundation. 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/dma-direction.h>
15#include <linux/sched.h>
16#include <linux/slab.h>
17#include <media/msm_vidc.h>
18#include "msm_vidc_internal.h"
19#include "msm_vidc_debug.h"
20#include "msm_vdec.h"
21#include "msm_venc.h"
22#include "msm_vidc_common.h"
23#include <linux/delay.h>
24#include "vidc_hfi_api.h"
25#include "msm_vidc_clocks.h"
26
27#define MAX_EVENTS 30
28
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -070029static int try_get_ctrl(struct msm_vidc_inst *inst,
30 struct v4l2_ctrl *ctrl);
Praneeth Paladugu13c90962017-04-24 13:15:28 -070031static int msm_vidc_get_count(struct msm_vidc_inst *inst,
32 struct v4l2_ctrl *ctrl);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -070033
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080034static int get_poll_flags(void *instance)
35{
36 struct msm_vidc_inst *inst = instance;
37 struct vb2_queue *outq = &inst->bufq[OUTPUT_PORT].vb2_bufq;
38 struct vb2_queue *capq = &inst->bufq[CAPTURE_PORT].vb2_bufq;
39 struct vb2_buffer *out_vb = NULL;
40 struct vb2_buffer *cap_vb = NULL;
41 unsigned long flags;
42 int rc = 0;
43
44 if (v4l2_event_pending(&inst->event_handler))
45 rc |= POLLPRI;
46
47 spin_lock_irqsave(&capq->done_lock, flags);
48 if (!list_empty(&capq->done_list))
49 cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer,
50 done_entry);
51 if (cap_vb && (cap_vb->state == VB2_BUF_STATE_DONE
52 || cap_vb->state == VB2_BUF_STATE_ERROR))
53 rc |= POLLIN | POLLRDNORM;
54 spin_unlock_irqrestore(&capq->done_lock, flags);
55
56 spin_lock_irqsave(&outq->done_lock, flags);
57 if (!list_empty(&outq->done_list))
58 out_vb = list_first_entry(&outq->done_list, struct vb2_buffer,
59 done_entry);
60 if (out_vb && (out_vb->state == VB2_BUF_STATE_DONE
61 || out_vb->state == VB2_BUF_STATE_ERROR))
62 rc |= POLLOUT | POLLWRNORM;
63 spin_unlock_irqrestore(&outq->done_lock, flags);
64
65 return rc;
66}
67
68int msm_vidc_poll(void *instance, struct file *filp,
69 struct poll_table_struct *wait)
70{
71 struct msm_vidc_inst *inst = instance;
72 struct vb2_queue *outq = NULL;
73 struct vb2_queue *capq = NULL;
74
75 if (!inst)
76 return -EINVAL;
77
78 outq = &inst->bufq[OUTPUT_PORT].vb2_bufq;
79 capq = &inst->bufq[CAPTURE_PORT].vb2_bufq;
80
81 poll_wait(filp, &inst->event_handler.wait, wait);
82 poll_wait(filp, &capq->done_wq, wait);
83 poll_wait(filp, &outq->done_wq, wait);
84 return get_poll_flags(inst);
85}
86EXPORT_SYMBOL(msm_vidc_poll);
87
88int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
89{
90 struct msm_vidc_inst *inst = instance;
91
92 if (!inst || !cap)
93 return -EINVAL;
94
Praneeth Paladugube42cb22016-04-12 22:34:39 -070095 strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
96 cap->bus_info[0] = 0;
97 cap->version = MSM_VIDC_VERSION;
98 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
99 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
100 V4L2_CAP_STREAMING;
101 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
102
103 memset(cap->reserved, 0, sizeof(cap->reserved));
104
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800105 if (inst->session_type == MSM_VIDC_DECODER)
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700106 strlcpy(cap->card, MSM_VDEC_DVC_NAME, sizeof(cap->card));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800107 else if (inst->session_type == MSM_VIDC_ENCODER)
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700108 strlcpy(cap->card, MSM_VENC_DVC_NAME, sizeof(cap->card));
109 else
110 return -EINVAL;
111
112 return 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800113}
114EXPORT_SYMBOL(msm_vidc_querycap);
115
116int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
117{
118 struct msm_vidc_inst *inst = instance;
119
120 if (!inst || !f)
121 return -EINVAL;
122
123 if (inst->session_type == MSM_VIDC_DECODER)
124 return msm_vdec_enum_fmt(instance, f);
125 else if (inst->session_type == MSM_VIDC_ENCODER)
126 return msm_venc_enum_fmt(instance, f);
127 return -EINVAL;
128}
129EXPORT_SYMBOL(msm_vidc_enum_fmt);
130
Praneeth Paladugue1679112017-01-27 10:07:15 -0800131static void msm_vidc_ctrl_get_range(struct v4l2_queryctrl *ctrl,
132 struct hal_capability_supported *capability)
133
134{
135 ctrl->maximum = capability->max;
136 ctrl->minimum = capability->min;
137}
138
139int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *ctrl)
140{
141 struct msm_vidc_inst *inst = instance;
142 int rc = 0;
143
144 if (!inst || !ctrl)
145 return -EINVAL;
146
147 switch (ctrl->id) {
148 case V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE:
149 msm_vidc_ctrl_get_range(ctrl,
150 &inst->capability.hier_p_hybrid);
151 break;
152 case V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS:
153 msm_vidc_ctrl_get_range(ctrl, &inst->capability.hier_b);
154 break;
155 case V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS:
156 msm_vidc_ctrl_get_range(ctrl, &inst->capability.hier_p);
157 break;
Vaibhav Deshu Venkatesh2c072532017-04-07 17:50:18 -0700158 case V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE:
Praneeth Paladugue1679112017-01-27 10:07:15 -0800159 case V4L2_CID_MPEG_VIDEO_BITRATE:
160 msm_vidc_ctrl_get_range(ctrl, &inst->capability.bitrate);
161 break;
162 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
163 msm_vidc_ctrl_get_range(ctrl, &inst->capability.peakbitrate);
164 break;
165 case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH:
166 msm_vidc_ctrl_get_range(ctrl, &inst->capability.blur_width);
167 break;
168 case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT:
169 msm_vidc_ctrl_get_range(ctrl, &inst->capability.blur_height);
170 break;
171 default:
172 rc = -EINVAL;
173 }
174 return rc;
175}
176EXPORT_SYMBOL(msm_vidc_query_ctrl);
177
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800178int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
179{
180 struct msm_vidc_inst *inst = instance;
181
182 if (!inst || !f)
183 return -EINVAL;
184
185 if (inst->session_type == MSM_VIDC_DECODER)
186 return msm_vdec_s_fmt(instance, f);
187 if (inst->session_type == MSM_VIDC_ENCODER)
188 return msm_venc_s_fmt(instance, f);
189 return -EINVAL;
190}
191EXPORT_SYMBOL(msm_vidc_s_fmt);
192
193int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
194{
195 struct msm_vidc_inst *inst = instance;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800196 int i, rc = 0, color_format = 0;
197 enum vidc_ports port;
198 u32 num_planes;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800199
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800200 if (!inst || !f) {
201 dprintk(VIDC_ERR,
202 "Invalid input, inst = %pK, format = %pK\n", inst, f);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800203 return -EINVAL;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800204 }
205 if (inst->in_reconfig) {
206 inst->prop.height[OUTPUT_PORT] = inst->reconfig_height;
207 inst->prop.width[OUTPUT_PORT] = inst->reconfig_width;
208 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800209
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800210 port = f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
211 OUTPUT_PORT : CAPTURE_PORT;
212
213 f->fmt.pix_mp.pixelformat = inst->fmts[port].fourcc;
214 f->fmt.pix_mp.height = inst->prop.height[port];
215 f->fmt.pix_mp.width = inst->prop.width[port];
216 num_planes = f->fmt.pix_mp.num_planes = inst->bufq[port].num_planes;
217 for (i = 0; i < num_planes; ++i)
218 f->fmt.pix_mp.plane_fmt[i].sizeimage =
219 inst->bufq[port].plane_sizes[i];
220 switch (inst->fmts[port].fourcc) {
221 case V4L2_PIX_FMT_NV12:
222 color_format = COLOR_FMT_NV12;
223 break;
224 case V4L2_PIX_FMT_NV12_UBWC:
225 color_format = COLOR_FMT_NV12_UBWC;
226 break;
227 case V4L2_PIX_FMT_NV12_TP10_UBWC:
228 color_format = COLOR_FMT_NV12_BPP10_UBWC;
229 break;
230 default:
231 dprintk(VIDC_DBG,
232 "Invalid : g_fmt called on %s port with Invalid fourcc 0x%x\n",
233 port == OUTPUT_PORT ? "OUTPUT" : "CAPTURE",
234 inst->fmts[port].fourcc);
235 goto exit;
236 }
237
238 f->fmt.pix_mp.plane_fmt[0].bytesperline = VENUS_Y_STRIDE(color_format,
239 inst->prop.width[port]);
240 f->fmt.pix_mp.plane_fmt[0].reserved[0] = VENUS_Y_SCANLINES(color_format,
241 inst->prop.height[port]);
242
243exit:
244 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800245}
246EXPORT_SYMBOL(msm_vidc_g_fmt);
247
248int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
249{
250 struct msm_vidc_inst *inst = instance;
251
252 if (!inst || !control)
253 return -EINVAL;
254
255 return msm_comm_s_ctrl(instance, control);
256}
257EXPORT_SYMBOL(msm_vidc_s_ctrl);
258
259int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
260{
261 struct msm_vidc_inst *inst = instance;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700262 struct v4l2_ctrl *ctrl = NULL;
263 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800264
265 if (!inst || !control)
266 return -EINVAL;
267
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700268 ctrl = v4l2_ctrl_find(&inst->ctrl_handler, control->id);
269 if (ctrl) {
270 rc = try_get_ctrl(inst, ctrl);
271 if (!rc)
272 control->value = ctrl->val;
273 }
274
275 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800276}
277EXPORT_SYMBOL(msm_vidc_g_ctrl);
278
Praneeth Paladugu13c90962017-04-24 13:15:28 -0700279int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
280{
281 struct msm_vidc_inst *inst = instance;
282 struct v4l2_ext_control *ext_control;
283 struct v4l2_ctrl ctrl;
284 int i = 0, rc = 0;
285
286 if (!inst || !control)
287 return -EINVAL;
288
289 ext_control = control->controls;
290
291 for (i = 0; i < control->count; i++) {
292 switch (ext_control[i].id) {
293 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
294 case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
295 ctrl.id = ext_control[i].id;
296 ctrl.val = ext_control[i].value;
297
298 msm_vidc_get_count(inst, &ctrl);
299 ext_control->value = ctrl.val;
300 break;
301 default:
302 dprintk(VIDC_ERR,
303 "This control %x is not supported yet\n",
304 ext_control[i].id);
305 rc = -EINVAL;
306 break;
307 }
308 }
309 return rc;
310}
311EXPORT_SYMBOL(msm_vidc_g_ext_ctrl);
312
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800313int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
314{
315 struct msm_vidc_inst *inst = instance;
316
317 if (!inst || !control)
318 return -EINVAL;
319
320 if (inst->session_type == MSM_VIDC_DECODER)
321 return msm_vdec_s_ext_ctrl(instance, control);
322 if (inst->session_type == MSM_VIDC_ENCODER)
323 return msm_venc_s_ext_ctrl(instance, control);
324 return -EINVAL;
325}
326EXPORT_SYMBOL(msm_vidc_s_ext_ctrl);
327
328int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
329{
330 struct msm_vidc_inst *inst = instance;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700331 struct buf_queue *q = NULL;
332 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800333
334 if (!inst || !b)
335 return -EINVAL;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700336 q = msm_comm_get_vb2q(inst, b->type);
337 if (!q) {
338 dprintk(VIDC_ERR,
339 "Failed to find buffer queue for type = %d\n",
340 b->type);
341 return -EINVAL;
342 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800343
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700344 mutex_lock(&q->lock);
345 rc = vb2_reqbufs(&q->vb2_bufq, b);
346 mutex_unlock(&q->lock);
347
348 if (rc)
349 dprintk(VIDC_ERR, "Failed to get reqbufs, %d\n", rc);
350 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800351}
352EXPORT_SYMBOL(msm_vidc_reqbufs);
353
354struct buffer_info *get_registered_buf(struct msm_vidc_inst *inst,
355 struct v4l2_buffer *b, int idx, int *plane)
356{
357 struct buffer_info *temp;
358 struct buffer_info *ret = NULL;
359 int i;
360 int fd = b->m.planes[idx].reserved[0];
361 u32 buff_off = b->m.planes[idx].reserved[1];
362 u32 size = b->m.planes[idx].length;
363 ion_phys_addr_t device_addr = b->m.planes[idx].m.userptr;
364
365 if (fd < 0 || !plane) {
366 dprintk(VIDC_ERR, "Invalid input\n");
367 goto err_invalid_input;
368 }
369
370 WARN(!mutex_is_locked(&inst->registeredbufs.lock),
371 "Registered buf lock is not acquired for %s", __func__);
372
373 *plane = 0;
374 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
375 for (i = 0; i < min(temp->num_planes, VIDEO_MAX_PLANES); i++) {
376 bool ion_hndl_matches = temp->handle[i] ?
377 msm_smem_compare_buffers(inst->mem_client, fd,
378 temp->handle[i]->smem_priv) : false;
379 bool device_addr_matches = device_addr ==
380 temp->device_addr[i];
381 bool contains_within = CONTAINS(temp->buff_off[i],
382 temp->size[i], buff_off) ||
383 CONTAINS(buff_off, size, temp->buff_off[i]);
384 bool overlaps = OVERLAPS(buff_off, size,
385 temp->buff_off[i], temp->size[i]);
386
387 if (!temp->inactive &&
388 (ion_hndl_matches || device_addr_matches) &&
389 (contains_within || overlaps)) {
390 dprintk(VIDC_DBG,
391 "This memory region is already mapped\n");
392 ret = temp;
393 *plane = i;
394 break;
395 }
396 }
397 if (ret)
398 break;
399 }
400
401err_invalid_input:
402 return ret;
403}
404
405static struct msm_smem *get_same_fd_buffer(struct msm_vidc_inst *inst, int fd)
406{
407 struct buffer_info *temp;
408 struct msm_smem *same_fd_handle = NULL;
409 int i;
410
411 if (!fd)
412 return NULL;
413
414 if (!inst || fd < 0) {
415 dprintk(VIDC_ERR, "%s: Invalid input\n", __func__);
416 goto err_invalid_input;
417 }
418
419 mutex_lock(&inst->registeredbufs.lock);
420 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
421 for (i = 0; i < min(temp->num_planes, VIDEO_MAX_PLANES); i++) {
422 bool ion_hndl_matches = temp->handle[i] ?
423 msm_smem_compare_buffers(inst->mem_client, fd,
424 temp->handle[i]->smem_priv) : false;
425 if (ion_hndl_matches && temp->mapped[i]) {
426 temp->same_fd_ref[i]++;
427 dprintk(VIDC_INFO,
428 "Found same fd buffer\n");
429 same_fd_handle = temp->handle[i];
430 break;
431 }
432 }
433 if (same_fd_handle)
434 break;
435 }
436 mutex_unlock(&inst->registeredbufs.lock);
437
438err_invalid_input:
439 return same_fd_handle;
440}
441
442struct buffer_info *device_to_uvaddr(struct msm_vidc_list *buf_list,
443 ion_phys_addr_t device_addr)
444{
445 struct buffer_info *temp = NULL;
446 bool found = false;
447 int i;
448
449 if (!buf_list || !device_addr) {
450 dprintk(VIDC_ERR,
451 "Invalid input- device_addr: %pa buf_list: %pK\n",
452 &device_addr, buf_list);
453 goto err_invalid_input;
454 }
455
456 mutex_lock(&buf_list->lock);
457 list_for_each_entry(temp, &buf_list->list, list) {
458 for (i = 0; i < min(temp->num_planes, VIDEO_MAX_PLANES); i++) {
459 if (!temp->inactive &&
460 temp->device_addr[i] == device_addr) {
461 dprintk(VIDC_INFO,
462 "Found same fd buffer\n");
463 found = true;
464 break;
465 }
466 }
467
468 if (found)
469 break;
470 }
471 mutex_unlock(&buf_list->lock);
472
473err_invalid_input:
474 return temp;
475}
476
477static inline void populate_buf_info(struct buffer_info *binfo,
478 struct v4l2_buffer *b, u32 i)
479{
480 if (i >= VIDEO_MAX_PLANES) {
481 dprintk(VIDC_ERR, "%s: Invalid input\n", __func__);
482 return;
483 }
484 binfo->type = b->type;
485 binfo->fd[i] = b->m.planes[i].reserved[0];
486 binfo->buff_off[i] = b->m.planes[i].reserved[1];
487 binfo->size[i] = b->m.planes[i].length;
488 binfo->uvaddr[i] = b->m.planes[i].m.userptr;
489 binfo->num_planes = b->length;
490 binfo->memory = b->memory;
491 binfo->v4l2_index = b->index;
492 binfo->timestamp.tv_sec = b->timestamp.tv_sec;
493 binfo->timestamp.tv_usec = b->timestamp.tv_usec;
494 dprintk(VIDC_DBG, "%s: fd[%d] = %d b->index = %d",
495 __func__, i, binfo->fd[i], b->index);
496}
497
498static inline void repopulate_v4l2_buffer(struct v4l2_buffer *b,
499 struct buffer_info *binfo)
500{
501 int i = 0;
502
503 b->type = binfo->type;
504 b->length = binfo->num_planes;
505 b->memory = binfo->memory;
506 b->index = binfo->v4l2_index;
507 b->timestamp.tv_sec = binfo->timestamp.tv_sec;
508 b->timestamp.tv_usec = binfo->timestamp.tv_usec;
509 binfo->dequeued = false;
510 for (i = 0; i < binfo->num_planes; ++i) {
511 b->m.planes[i].reserved[0] = binfo->fd[i];
512 b->m.planes[i].reserved[1] = binfo->buff_off[i];
513 b->m.planes[i].length = binfo->size[i];
514 b->m.planes[i].m.userptr = binfo->device_addr[i];
515 dprintk(VIDC_DBG, "%s %d %d %d %pa\n", __func__, binfo->fd[i],
516 binfo->buff_off[i], binfo->size[i],
517 &binfo->device_addr[i]);
518 }
519}
520
521static struct msm_smem *map_buffer(struct msm_vidc_inst *inst,
522 struct v4l2_plane *p, enum hal_buffer buffer_type)
523{
524 struct msm_smem *handle = NULL;
525
526 handle = msm_comm_smem_user_to_kernel(inst,
527 p->reserved[0],
528 p->reserved[1],
529 buffer_type);
530 if (!handle) {
531 dprintk(VIDC_ERR,
532 "%s: Failed to get device buffer address\n", __func__);
533 return NULL;
534 }
535 return handle;
536}
537
538static inline enum hal_buffer get_hal_buffer_type(
539 struct msm_vidc_inst *inst, struct v4l2_buffer *b)
540{
541 if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
542 return HAL_BUFFER_INPUT;
543 else if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
544 return HAL_BUFFER_OUTPUT;
545 else
546 return -EINVAL;
547}
548
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800549static inline bool is_dynamic_buffer_mode(struct v4l2_buffer *b,
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800550 struct msm_vidc_inst *inst)
551{
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800552 enum vidc_ports port = b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
553 OUTPUT_PORT : CAPTURE_PORT;
554 return inst->buffer_mode_set[port] == HAL_BUFFER_MODE_DYNAMIC;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800555}
556
557
558static inline void save_v4l2_buffer(struct v4l2_buffer *b,
559 struct buffer_info *binfo)
560{
561 int i = 0;
562
563 for (i = 0; i < b->length; ++i) {
564 if (EXTRADATA_IDX(b->length) &&
565 (i == EXTRADATA_IDX(b->length)) &&
566 !b->m.planes[i].length) {
567 continue;
568 }
569 populate_buf_info(binfo, b, i);
570 }
571}
572
573int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
574{
575 struct buffer_info *binfo = NULL;
576 struct buffer_info *temp = NULL, *iterator = NULL;
577 int plane = 0;
578 int i = 0, rc = 0;
579 struct msm_smem *same_fd_handle = NULL;
580
581 if (!b || !inst) {
582 dprintk(VIDC_ERR, "%s: invalid input\n", __func__);
583 return -EINVAL;
584 }
585
586 binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
587 if (!binfo) {
588 dprintk(VIDC_ERR, "Out of memory\n");
589 rc = -ENOMEM;
590 goto exit;
591 }
592 if (b->length > VIDEO_MAX_PLANES) {
593 dprintk(VIDC_ERR, "Num planes exceeds max: %d, %d\n",
594 b->length, VIDEO_MAX_PLANES);
595 rc = -EINVAL;
596 goto exit;
597 }
598
599 dprintk(VIDC_DBG, "[MAP] Create binfo = %pK fd = %d type = %d\n",
600 binfo, b->m.planes[0].reserved[0], b->type);
601
602 for (i = 0; i < b->length; ++i) {
603 rc = 0;
604 if (EXTRADATA_IDX(b->length) &&
605 (i == EXTRADATA_IDX(b->length)) &&
606 !b->m.planes[i].length) {
607 continue;
608 }
609 mutex_lock(&inst->registeredbufs.lock);
610 temp = get_registered_buf(inst, b, i, &plane);
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800611 if (temp && !is_dynamic_buffer_mode(b, inst)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800612 dprintk(VIDC_DBG,
613 "This memory region has already been prepared\n");
614 rc = 0;
615 mutex_unlock(&inst->registeredbufs.lock);
616 goto exit;
617 }
618
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800619 if (temp && is_dynamic_buffer_mode(b, inst) && !i) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800620 /*
621 * Buffer is already present in registered list
622 * increment ref_count, populate new values of v4l2
623 * buffer in existing buffer_info struct.
624 *
625 * We will use the saved buffer info and queue it when
626 * we receive RELEASE_BUFFER_REFERENCE EVENT from f/w.
627 */
628 dprintk(VIDC_DBG, "[MAP] Buffer already prepared\n");
629 temp->inactive = false;
630 list_for_each_entry(iterator,
631 &inst->registeredbufs.list, list) {
632 if (iterator == temp) {
633 rc = buf_ref_get(inst, temp);
634 save_v4l2_buffer(b, temp);
635 break;
636 }
637 }
638 }
639 mutex_unlock(&inst->registeredbufs.lock);
640 /*
641 * rc == 1,
642 * buffer is mapped, fw has released all reference, so skip
643 * mapping and queue it immediately.
644 *
645 * rc == 2,
646 * buffer is mapped and fw is holding a reference, hold it in
647 * the driver and queue it later when fw has released
648 */
649 if (rc == 1) {
650 rc = 0;
651 goto exit;
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800652 } else if (rc >= 2) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800653 rc = -EEXIST;
654 goto exit;
655 }
656
657 same_fd_handle = get_same_fd_buffer(
658 inst, b->m.planes[i].reserved[0]);
659
660 populate_buf_info(binfo, b, i);
661 if (same_fd_handle) {
662 binfo->device_addr[i] =
663 same_fd_handle->device_addr + binfo->buff_off[i];
664 b->m.planes[i].m.userptr = binfo->device_addr[i];
665 binfo->mapped[i] = false;
666 binfo->handle[i] = same_fd_handle;
667 } else {
668 binfo->handle[i] = map_buffer(inst, &b->m.planes[i],
669 get_hal_buffer_type(inst, b));
670 if (!binfo->handle[i]) {
671 rc = -EINVAL;
672 goto exit;
673 }
674
675 binfo->mapped[i] = true;
676 binfo->device_addr[i] = binfo->handle[i]->device_addr +
677 binfo->buff_off[i];
678 b->m.planes[i].m.userptr = binfo->device_addr[i];
679 }
680
681 /* We maintain one ref count for all planes*/
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800682 if (!i && is_dynamic_buffer_mode(b, inst)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800683 rc = buf_ref_get(inst, binfo);
684 if (rc < 0)
685 goto exit;
686 }
687 dprintk(VIDC_DBG,
688 "%s: [MAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n",
689 __func__, binfo, i, binfo->handle[i],
690 &binfo->device_addr[i], binfo->fd[i],
691 binfo->buff_off[i], binfo->mapped[i]);
692 }
693
694 mutex_lock(&inst->registeredbufs.lock);
695 list_add_tail(&binfo->list, &inst->registeredbufs.list);
696 mutex_unlock(&inst->registeredbufs.lock);
697 return 0;
698
699exit:
700 kfree(binfo);
701 return rc;
702}
703int unmap_and_deregister_buf(struct msm_vidc_inst *inst,
704 struct buffer_info *binfo)
705{
706 int i = 0;
707 struct buffer_info *temp = NULL;
708 bool found = false, keep_node = false;
709
710 if (!inst || !binfo) {
711 dprintk(VIDC_ERR, "%s invalid param: %pK %pK\n",
712 __func__, inst, binfo);
713 return -EINVAL;
714 }
715
716 WARN(!mutex_is_locked(&inst->registeredbufs.lock),
717 "Registered buf lock is not acquired for %s", __func__);
718
719 /*
720 * Make sure the buffer to be unmapped and deleted
721 * from the registered list is present in the list.
722 */
723 list_for_each_entry(temp, &inst->registeredbufs.list, list) {
724 if (temp == binfo) {
725 found = true;
726 break;
727 }
728 }
729
730 /*
731 * Free the buffer info only if
732 * - buffer info has not been deleted from registered list
733 * - vidc client has called dqbuf on the buffer
734 * - no references are held on the buffer
735 */
736 if (!found || !temp || !temp->pending_deletion || !temp->dequeued)
737 goto exit;
738
739 for (i = 0; i < temp->num_planes; i++) {
740 dprintk(VIDC_DBG,
741 "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n",
742 __func__, temp, i, temp->handle[i],
743 &temp->device_addr[i], temp->fd[i],
744 temp->buff_off[i], temp->mapped[i]);
745 /*
746 * Unmap the handle only if the buffer has been mapped and no
747 * other buffer has a reference to this buffer.
748 * In case of buffers with same fd, we will map the buffer only
749 * once and subsequent buffers will refer to the mapped buffer's
750 * device address.
751 * For buffers which share the same fd, do not unmap and keep
752 * the buffer info in registered list.
753 */
754 if (temp->handle[i] && temp->mapped[i] &&
755 !temp->same_fd_ref[i]) {
756 msm_comm_smem_free(inst,
757 temp->handle[i]);
758 }
759
760 if (temp->same_fd_ref[i])
761 keep_node = true;
762 else {
763 temp->fd[i] = 0;
764 temp->handle[i] = 0;
765 temp->device_addr[i] = 0;
766 temp->uvaddr[i] = 0;
767 }
768 }
769 if (!keep_node) {
770 dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %pK\n", temp);
771 list_del(&temp->list);
772 kfree(temp);
773 } else {
774 temp->inactive = true;
775 dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %pK\n", temp);
776 }
777exit:
778 return 0;
779}
780
781
782int qbuf_dynamic_buf(struct msm_vidc_inst *inst,
783 struct buffer_info *binfo)
784{
785 struct v4l2_buffer b = {0};
786 struct v4l2_plane plane[VIDEO_MAX_PLANES] = { {0} };
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700787 struct buf_queue *q = NULL;
788 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800789
790 if (!binfo) {
791 dprintk(VIDC_ERR, "%s invalid param: %pK\n", __func__, binfo);
792 return -EINVAL;
793 }
794 dprintk(VIDC_DBG, "%s fd[0] = %d\n", __func__, binfo->fd[0]);
795
796 b.m.planes = plane;
797 repopulate_v4l2_buffer(&b, binfo);
798
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700799 q = msm_comm_get_vb2q(inst, (&b)->type);
800 if (!q) {
801 dprintk(VIDC_ERR, "Failed to find buffer queue for type = %d\n"
802 , (&b)->type);
803 return -EINVAL;
804 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800805
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700806 mutex_lock(&q->lock);
807 rc = vb2_qbuf(&q->vb2_bufq, &b);
808 mutex_unlock(&q->lock);
809
810 if (rc)
811 dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
812 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800813}
814
815int output_buffer_cache_invalidate(struct msm_vidc_inst *inst,
816 struct buffer_info *binfo)
817{
818 int i = 0;
819 int rc = 0;
820
821 if (!inst) {
822 dprintk(VIDC_ERR, "%s: invalid inst: %pK\n", __func__, inst);
823 return -EINVAL;
824 }
825
826 if (!binfo) {
827 dprintk(VIDC_ERR, "%s: invalid buffer info: %pK\n",
828 __func__, inst);
829 return -EINVAL;
830 }
831
832 for (i = 0; i < binfo->num_planes; i++) {
833 if (binfo->handle[i]) {
834 struct msm_smem smem = *binfo->handle[i];
835
836 smem.offset = (unsigned int)(binfo->buff_off[i]);
837 smem.size = binfo->size[i];
838 rc = msm_comm_smem_cache_operations(inst,
839 &smem, SMEM_CACHE_INVALIDATE);
840 if (rc) {
841 dprintk(VIDC_ERR,
842 "%s: Failed to clean caches: %d\n",
843 __func__, rc);
844 return -EINVAL;
845 }
846 } else
847 dprintk(VIDC_DBG, "%s: NULL handle for plane %d\n",
848 __func__, i);
849 }
850 return 0;
851}
852
853static bool valid_v4l2_buffer(struct v4l2_buffer *b,
854 struct msm_vidc_inst *inst) {
855 enum vidc_ports port =
856 !V4L2_TYPE_IS_MULTIPLANAR(b->type) ? MAX_PORT_NUM :
857 b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ? CAPTURE_PORT :
858 b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? OUTPUT_PORT :
859 MAX_PORT_NUM;
860
861 return port != MAX_PORT_NUM &&
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800862 inst->bufq[port].num_planes == b->length;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800863}
864
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800865int msm_vidc_release_buffer(void *instance, int buffer_type,
866 unsigned int buffer_index)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800867{
868 struct msm_vidc_inst *inst = instance;
869 struct buffer_info *bi, *dummy;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800870 int i, rc = 0;
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800871 int found_buf = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800872
873 if (!inst)
874 return -EINVAL;
875
876 if (!inst->in_reconfig &&
877 inst->state > MSM_VIDC_LOAD_RESOURCES &&
878 inst->state < MSM_VIDC_RELEASE_RESOURCES_DONE) {
879 rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
880 if (rc) {
881 dprintk(VIDC_ERR,
882 "Failed to move inst: %pK to release res done\n",
883 inst);
884 }
885 }
886
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800887 mutex_lock(&inst->registeredbufs.lock);
888 list_for_each_entry_safe(bi, dummy, &inst->registeredbufs.list, list) {
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800889 if (bi->type == buffer_type && bi->v4l2_index == buffer_index) {
890 found_buf = 1;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800891 list_del(&bi->list);
892 for (i = 0; i < bi->num_planes; i++) {
893 if (bi->handle[i] && bi->mapped[i]) {
894 dprintk(VIDC_DBG,
895 "%s: [UNMAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n",
896 __func__, bi, i, bi->handle[i],
897 &bi->device_addr[i], bi->fd[i],
898 bi->buff_off[i], bi->mapped[i]);
899 msm_comm_smem_free(inst,
900 bi->handle[i]);
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800901 found_buf = 2;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800902 }
903 }
904 kfree(bi);
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800905 break;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800906 }
907 }
908 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800909
910 switch (found_buf) {
911 case 0:
912 dprintk(VIDC_WARN,
913 "%s: No buffer(type: %d) found for index %d\n",
914 __func__, buffer_type, buffer_index);
915 break;
916 case 1:
917 dprintk(VIDC_WARN,
918 "%s: Buffer(type: %d) found for index %d.",
919 __func__, buffer_type, buffer_index);
920 dprintk(VIDC_WARN, "zero planes mapped.\n");
921 break;
922 case 2:
923 dprintk(VIDC_DBG,
924 "%s: Released buffer(type: %d) for index %d\n",
925 __func__, buffer_type, buffer_index);
926 break;
927 default:
928 break;
929 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800930 return rc;
931}
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800932EXPORT_SYMBOL(msm_vidc_release_buffer);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800933
934int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
935{
936 struct msm_vidc_inst *inst = instance;
937 struct buffer_info *binfo;
938 int plane = 0;
939 int rc = 0;
940 int i;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700941 struct buf_queue *q = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800942
943 if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst))
944 return -EINVAL;
945
946 if (inst->state == MSM_VIDC_CORE_INVALID ||
947 inst->core->state == VIDC_CORE_INVALID)
948 return -EINVAL;
949
950 rc = map_and_register_buf(inst, b);
951 if (rc == -EEXIST) {
952 if (atomic_read(&inst->in_flush) &&
Praneeth Paladuguf4223b72016-12-22 11:36:50 -0800953 is_dynamic_buffer_mode(b, inst)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800954 dprintk(VIDC_ERR,
955 "Flush in progress, do not hold any buffers in driver\n");
956 msm_comm_flush_dynamic_buffers(inst);
957 }
958 return 0;
959 }
960 if (rc)
961 return rc;
962
963 for (i = 0; i < b->length; ++i) {
964 if (EXTRADATA_IDX(b->length) &&
965 (i == EXTRADATA_IDX(b->length)) &&
966 !b->m.planes[i].length) {
967 b->m.planes[i].m.userptr = 0;
968 continue;
969 }
970 mutex_lock(&inst->registeredbufs.lock);
971 binfo = get_registered_buf(inst, b, i, &plane);
972 mutex_unlock(&inst->registeredbufs.lock);
973 if (!binfo) {
974 dprintk(VIDC_ERR,
975 "This buffer is not registered: %d, %d, %d\n",
976 b->m.planes[i].reserved[0],
977 b->m.planes[i].reserved[1],
978 b->m.planes[i].length);
979 goto err_invalid_buff;
980 }
981 b->m.planes[i].m.userptr = binfo->device_addr[i];
982 dprintk(VIDC_DBG, "Queueing device address = %pa\n",
983 &binfo->device_addr[i]);
984
985 if (binfo->handle[i] &&
986 (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
987 rc = msm_comm_smem_cache_operations(inst,
988 binfo->handle[i], SMEM_CACHE_CLEAN);
989 if (rc) {
990 dprintk(VIDC_ERR,
991 "Failed to clean caches: %d\n", rc);
992 goto err_invalid_buff;
993 }
994 }
995 }
996
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700997 q = msm_comm_get_vb2q(inst, b->type);
998 if (!q) {
999 dprintk(VIDC_ERR,
1000 "Failed to find buffer queue for type = %d\n", b->type);
1001 return -EINVAL;
1002 }
1003 mutex_lock(&q->lock);
1004 rc = vb2_qbuf(&q->vb2_bufq, b);
1005 mutex_unlock(&q->lock);
1006 if (rc)
1007 dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
1008 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001009
1010err_invalid_buff:
1011 return -EINVAL;
1012}
1013EXPORT_SYMBOL(msm_vidc_qbuf);
1014
1015int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
1016{
1017 struct msm_vidc_inst *inst = instance;
1018 struct buffer_info *buffer_info = NULL;
1019 int i = 0, rc = 0;
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001020 struct buf_queue *q = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001021
1022 if (!inst || !b || !valid_v4l2_buffer(b, inst))
1023 return -EINVAL;
1024
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001025 q = msm_comm_get_vb2q(inst, b->type);
1026 if (!q) {
1027 dprintk(VIDC_ERR,
1028 "Failed to find buffer queue for type = %d\n", b->type);
1029 return -EINVAL;
1030 }
1031 mutex_lock(&q->lock);
1032 rc = vb2_dqbuf(&q->vb2_bufq, b, true);
1033 mutex_unlock(&q->lock);
1034 if (rc) {
1035 dprintk(VIDC_DBG, "Failed to dqbuf, %d\n", rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001036 return rc;
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001037 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001038
1039 for (i = 0; i < b->length; i++) {
1040 if (EXTRADATA_IDX(b->length) &&
1041 i == EXTRADATA_IDX(b->length)) {
1042 continue;
1043 }
1044 buffer_info = device_to_uvaddr(&inst->registeredbufs,
1045 b->m.planes[i].m.userptr);
1046
1047 if (!buffer_info) {
1048 dprintk(VIDC_ERR,
1049 "%s no buffer info registered for buffer addr: %#lx\n",
1050 __func__, b->m.planes[i].m.userptr);
1051 return -EINVAL;
1052 }
1053
1054 b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
1055 b->m.planes[i].reserved[0] = buffer_info->fd[i];
1056 b->m.planes[i].reserved[1] = buffer_info->buff_off[i];
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001057 }
1058
1059 if (!buffer_info) {
1060 dprintk(VIDC_ERR,
1061 "%s: error - no buffer info found in registered list\n",
1062 __func__);
1063 return -EINVAL;
1064 }
1065
1066 rc = output_buffer_cache_invalidate(inst, buffer_info);
1067 if (rc)
1068 return rc;
1069
1070
Praneeth Paladuguf4223b72016-12-22 11:36:50 -08001071 if (is_dynamic_buffer_mode(b, inst)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001072 buffer_info->dequeued = true;
1073
1074 dprintk(VIDC_DBG, "[DEQUEUED]: fd[0] = %d\n",
1075 buffer_info->fd[0]);
1076 mutex_lock(&inst->registeredbufs.lock);
1077 rc = unmap_and_deregister_buf(inst, buffer_info);
1078 mutex_unlock(&inst->registeredbufs.lock);
1079 }
1080
1081 return rc;
1082}
1083EXPORT_SYMBOL(msm_vidc_dqbuf);
1084
1085int msm_vidc_streamon(void *instance, enum v4l2_buf_type i)
1086{
1087 struct msm_vidc_inst *inst = instance;
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001088 int rc = 0;
1089 struct buf_queue *q;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001090
1091 if (!inst)
1092 return -EINVAL;
1093
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001094 q = msm_comm_get_vb2q(inst, i);
1095 if (!q) {
1096 dprintk(VIDC_ERR,
1097 "Failed to find buffer queue for type = %d\n", i);
1098 return -EINVAL;
1099 }
1100 dprintk(VIDC_DBG, "Calling streamon\n");
1101 mutex_lock(&q->lock);
1102 rc = vb2_streamon(&q->vb2_bufq, i);
1103 mutex_unlock(&q->lock);
1104 if (rc)
1105 dprintk(VIDC_ERR, "streamon failed on port: %d\n", i);
1106 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001107}
1108EXPORT_SYMBOL(msm_vidc_streamon);
1109
1110int msm_vidc_streamoff(void *instance, enum v4l2_buf_type i)
1111{
1112 struct msm_vidc_inst *inst = instance;
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001113 int rc = 0;
1114 struct buf_queue *q;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001115
1116 if (!inst)
1117 return -EINVAL;
1118
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001119 q = msm_comm_get_vb2q(inst, i);
1120 if (!q) {
1121 dprintk(VIDC_ERR,
1122 "Failed to find buffer queue for type = %d\n", i);
1123 return -EINVAL;
1124 }
1125 dprintk(VIDC_DBG, "Calling streamoff\n");
1126 mutex_lock(&q->lock);
1127 rc = vb2_streamoff(&q->vb2_bufq, i);
1128 mutex_unlock(&q->lock);
1129 if (rc)
1130 dprintk(VIDC_ERR, "streamoff failed on port: %d\n", i);
1131 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001132}
1133EXPORT_SYMBOL(msm_vidc_streamoff);
1134
1135int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize)
1136{
1137 struct msm_vidc_inst *inst = instance;
1138 struct msm_vidc_capability *capability = NULL;
1139
1140 if (!inst || !fsize) {
1141 dprintk(VIDC_ERR, "%s: invalid parameter: %pK %pK\n",
1142 __func__, inst, fsize);
1143 return -EINVAL;
1144 }
1145 if (!inst->core)
1146 return -EINVAL;
1147
1148 capability = &inst->capability;
1149 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1150 fsize->stepwise.min_width = capability->width.min;
1151 fsize->stepwise.max_width = capability->width.max;
1152 fsize->stepwise.step_width = capability->width.step_size;
1153 fsize->stepwise.min_height = capability->height.min;
1154 fsize->stepwise.max_height = capability->height.max;
1155 fsize->stepwise.step_height = capability->height.step_size;
1156 return 0;
1157}
1158EXPORT_SYMBOL(msm_vidc_enum_framesizes);
1159
1160static void *vidc_get_userptr(struct device *dev, unsigned long vaddr,
1161 unsigned long size, enum dma_data_direction dma_dir)
1162{
1163 return (void *)0xdeadbeef;
1164}
1165
1166static void vidc_put_userptr(void *buf_priv)
1167{
1168}
1169
1170static const struct vb2_mem_ops msm_vidc_vb2_mem_ops = {
1171 .get_userptr = vidc_get_userptr,
1172 .put_userptr = vidc_put_userptr,
1173};
1174
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001175static void msm_vidc_cleanup_buffer(struct vb2_buffer *vb)
1176{
1177 int rc = 0;
1178 struct buf_queue *q = NULL;
1179 struct msm_vidc_inst *inst = NULL;
1180
1181 if (!vb) {
1182 dprintk(VIDC_ERR, "%s : Invalid vb pointer %pK",
1183 __func__, vb);
1184 return;
1185 }
1186
1187 inst = vb2_get_drv_priv(vb->vb2_queue);
1188 if (!inst) {
1189 dprintk(VIDC_ERR, "%s : Invalid inst pointer",
1190 __func__);
1191 return;
1192 }
1193
1194 q = msm_comm_get_vb2q(inst, vb->type);
1195 if (!q) {
1196 dprintk(VIDC_ERR,
1197 "%s : Failed to find buffer queue for type = %d\n",
1198 __func__, vb->type);
1199 return;
1200 }
1201
1202 if (q->vb2_bufq.streaming) {
1203 dprintk(VIDC_DBG, "%d PORT is streaming\n",
1204 vb->type);
1205 return;
1206 }
1207
Praneeth Paladuguceec6d82016-12-21 15:09:57 -08001208 rc = msm_vidc_release_buffer(inst, vb->type, vb->index);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001209 if (rc)
1210 dprintk(VIDC_ERR, "%s : Failed to release buffers : %d\n",
1211 __func__, rc);
1212}
1213
1214static int set_buffer_count(struct msm_vidc_inst *inst,
1215 int host_count, int act_count, enum hal_buffer type)
1216{
1217 int rc = 0;
1218 struct hfi_device *hdev;
1219 struct hal_buffer_count_actual buf_count;
1220
1221 hdev = inst->core->device;
1222
1223 buf_count.buffer_type = type;
1224 buf_count.buffer_count_actual = act_count;
1225 buf_count.buffer_count_min_host = host_count;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001226 dprintk(VIDC_DBG, "%s : Act count = %d Host count = %d\n",
1227 __func__, act_count, host_count);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001228 rc = call_hfi_op(hdev, session_set_property,
1229 inst->session, HAL_PARAM_BUFFER_COUNT_ACTUAL, &buf_count);
1230 if (rc)
1231 dprintk(VIDC_ERR,
1232 "Failed to set actual buffer count %d for buffer type %d\n",
1233 act_count, type);
1234 return rc;
1235}
1236
1237static int msm_vidc_queue_setup(struct vb2_queue *q,
1238 unsigned int *num_buffers, unsigned int *num_planes,
1239 unsigned int sizes[], struct device *alloc_devs[])
1240{
1241 struct msm_vidc_inst *inst;
1242 int i, rc = 0;
1243 struct hal_buffer_requirements *bufreq;
1244 enum hal_buffer buffer_type;
1245
1246 if (!q || !num_buffers || !num_planes
1247 || !sizes || !q->drv_priv) {
1248 dprintk(VIDC_ERR, "Invalid input, q = %pK, %pK, %pK\n",
1249 q, num_buffers, num_planes);
1250 return -EINVAL;
1251 }
1252 inst = q->drv_priv;
1253
1254 if (!inst || !inst->core || !inst->core->device) {
1255 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
1256 return -EINVAL;
1257 }
1258
1259 switch (q->type) {
1260 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: {
1261 bufreq = get_buff_req_buffer(inst,
1262 HAL_BUFFER_INPUT);
1263 if (!bufreq) {
1264 dprintk(VIDC_ERR,
1265 "Failed : No buffer requirements : %x\n",
1266 HAL_BUFFER_INPUT);
1267 return -EINVAL;
1268 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001269 if (*num_buffers < bufreq->buffer_count_min_host) {
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001270 dprintk(VIDC_ERR,
1271 "Invalid parameters : Req = %d Act = %d\n",
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001272 *num_buffers, bufreq->buffer_count_min_host);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001273 return -EINVAL;
1274 }
1275 *num_planes = inst->bufq[OUTPUT_PORT].num_planes;
1276 if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS ||
1277 *num_buffers > MAX_NUM_OUTPUT_BUFFERS)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001278 bufreq->buffer_count_actual = *num_buffers =
1279 MIN_NUM_OUTPUT_BUFFERS;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001280 for (i = 0; i < *num_planes; i++)
1281 sizes[i] = inst->bufq[OUTPUT_PORT].plane_sizes[i];
1282
1283 bufreq->buffer_count_actual = *num_buffers;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001284 rc = set_buffer_count(inst, bufreq->buffer_count_actual,
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001285 *num_buffers, HAL_BUFFER_INPUT);
1286 }
1287
1288 break;
1289 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: {
1290 buffer_type = msm_comm_get_hal_output_buffer(inst);
1291 bufreq = get_buff_req_buffer(inst,
1292 buffer_type);
1293 if (!bufreq) {
1294 dprintk(VIDC_ERR,
1295 "Failed : No buffer requirements : %x\n",
1296 buffer_type);
1297 return -EINVAL;
1298 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001299 if (inst->session_type != MSM_VIDC_DECODER &&
1300 inst->state > MSM_VIDC_LOAD_RESOURCES_DONE) {
1301 if (*num_buffers < bufreq->buffer_count_min_host) {
1302 dprintk(VIDC_ERR,
1303 "Invalid parameters : Req = %d Act = %d\n",
1304 *num_buffers,
1305 bufreq->buffer_count_min_host);
1306 return -EINVAL;
1307 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001308 }
1309 *num_planes = inst->bufq[CAPTURE_PORT].num_planes;
1310 if (*num_buffers < MIN_NUM_CAPTURE_BUFFERS ||
1311 *num_buffers > MAX_NUM_CAPTURE_BUFFERS)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001312 bufreq->buffer_count_actual = *num_buffers =
1313 MIN_NUM_CAPTURE_BUFFERS;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001314
1315 for (i = 0; i < *num_planes; i++)
1316 sizes[i] = inst->bufq[CAPTURE_PORT].plane_sizes[i];
1317
1318 bufreq->buffer_count_actual = *num_buffers;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001319 rc = set_buffer_count(inst, bufreq->buffer_count_actual,
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001320 *num_buffers, buffer_type);
1321 }
1322 break;
1323 default:
1324 dprintk(VIDC_ERR, "Invalid q type = %d\n", q->type);
1325 rc = -EINVAL;
1326 break;
1327 }
1328 return rc;
1329}
1330
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001331static inline int msm_vidc_verify_buffer_counts(struct msm_vidc_inst *inst)
1332{
1333 int rc = 0, i = 0;
1334
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001335 /* For decoder No need to sanity till LOAD_RESOURCES */
1336 if (inst->session_type == MSM_VIDC_DECODER &&
1337 inst->state < MSM_VIDC_LOAD_RESOURCES_DONE) {
1338 dprintk(VIDC_DBG,
1339 "No need to verify buffer counts : %pK\n", inst);
1340 return 0;
1341 }
1342
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001343 for (i = 0; i < HAL_BUFFER_MAX; i++) {
1344 struct hal_buffer_requirements *req = &inst->buff_req.buffer[i];
1345
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001346 if (req && (msm_comm_get_hal_output_buffer(inst) ==
1347 req->buffer_type)) {
1348 dprintk(VIDC_DBG, "Verifying Buffer : %d\n",
1349 req->buffer_type);
1350 if (req->buffer_count_actual <
1351 req->buffer_count_min_host ||
1352 req->buffer_count_min_host <
1353 req->buffer_count_min) {
1354
1355 dprintk(VIDC_ERR,
1356 "Invalid data : Counts mismatch\n");
1357 dprintk(VIDC_ERR,
1358 "Min Count = %d ",
1359 req->buffer_count_min);
1360 dprintk(VIDC_ERR,
1361 "Min Host Count = %d ",
1362 req->buffer_count_min_host);
1363 dprintk(VIDC_ERR,
1364 "Min Actual Count = %d\n",
1365 req->buffer_count_actual);
1366 rc = -EINVAL;
1367 break;
1368 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001369 }
1370 }
1371 return rc;
1372}
1373
1374static inline int start_streaming(struct msm_vidc_inst *inst)
1375{
1376 int rc = 0;
1377 struct hfi_device *hdev;
1378 struct hal_buffer_size_minimum b;
1379 struct vb2_buf_entry *temp, *next;
1380
1381 hdev = inst->core->device;
1382
1383 /* Check if current session is under HW capability */
1384 rc = msm_vidc_check_session_supported(inst);
1385 if (rc) {
1386 dprintk(VIDC_ERR,
1387 "This session is not supported %pK\n", inst);
1388 goto fail_start;
1389 }
1390
Praneeth Paladugu238977b2016-12-06 12:51:26 -08001391 /* Decide work mode for current session */
1392 rc = msm_vidc_decide_work_mode(inst);
1393 if (rc) {
1394 dprintk(VIDC_ERR,
1395 "Failed to decide work mode for session %pK\n", inst);
1396 goto fail_start;
1397 }
1398
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001399 /* Assign Core and LP mode for current session */
1400 rc = msm_vidc_decide_core_and_power_mode(inst);
1401 if (rc) {
1402 dprintk(VIDC_ERR,
Praneeth Paladugu238977b2016-12-06 12:51:26 -08001403 "This session can't be submitted to HW %pK\n", inst);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001404 goto fail_start;
1405 }
1406
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001407 if (msm_comm_get_stream_output_mode(inst) ==
1408 HAL_VIDEO_DECODER_SECONDARY) {
1409 b.buffer_type = HAL_BUFFER_OUTPUT2;
1410 } else {
1411 b.buffer_type = HAL_BUFFER_OUTPUT;
1412 }
1413
1414 b.buffer_size = inst->bufq[CAPTURE_PORT].plane_sizes[0];
1415 rc = call_hfi_op(hdev, session_set_property,
1416 inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
1417 &b);
1418
1419 rc = msm_comm_try_get_bufreqs(inst);
1420
Praneeth Paladugu238977b2016-12-06 12:51:26 -08001421 /* Verify if buffer counts are correct */
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001422 rc = msm_vidc_verify_buffer_counts(inst);
1423 if (rc) {
1424 dprintk(VIDC_ERR,
1425 "This session has mis-match buffer counts%pK\n", inst);
1426 goto fail_start;
1427 }
1428
1429 rc = msm_comm_set_scratch_buffers(inst);
1430 if (rc) {
1431 dprintk(VIDC_ERR,
1432 "Failed to set scratch buffers: %d\n", rc);
1433 goto fail_start;
1434 }
1435 rc = msm_comm_set_persist_buffers(inst);
1436 if (rc) {
1437 dprintk(VIDC_ERR,
1438 "Failed to set persist buffers: %d\n", rc);
1439 goto fail_start;
1440 }
1441
1442 if (msm_comm_get_stream_output_mode(inst) ==
1443 HAL_VIDEO_DECODER_SECONDARY) {
1444 rc = msm_comm_set_output_buffers(inst);
1445 if (rc) {
1446 dprintk(VIDC_ERR,
1447 "Failed to set output buffers: %d\n", rc);
1448 goto fail_start;
1449 }
1450 }
1451
Shivendra Kakraniac1f60e02017-04-13 00:07:26 -07001452 msm_comm_set_use_sys_cache(inst);
1453
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001454 /*
1455 * For seq_changed_insufficient, driver should set session_continue
1456 * to firmware after the following sequence
1457 * - driver raises insufficient event to v4l2 client
1458 * - all output buffers have been flushed and freed
1459 * - v4l2 client queries buffer requirements and splits/combines OPB-DPB
1460 * - v4l2 client sets new set of buffers to firmware
1461 * - v4l2 client issues CONTINUE to firmware to resume decoding of
1462 * submitted ETBs.
1463 */
Umesh Pandeybb3fad02017-03-31 16:49:42 -07001464 rc = msm_comm_session_continue(inst);
1465 if (rc)
1466 goto fail_start;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001467
1468 msm_comm_scale_clocks_and_bus(inst);
1469
1470 rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
1471 if (rc) {
1472 dprintk(VIDC_ERR,
1473 "Failed to move inst: %pK to start done state\n", inst);
1474 goto fail_start;
1475 }
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07001476
1477 msm_clock_data_reset(inst);
1478
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001479 if (msm_comm_get_stream_output_mode(inst) ==
1480 HAL_VIDEO_DECODER_SECONDARY) {
1481 rc = msm_comm_queue_output_buffers(inst);
1482 if (rc) {
1483 dprintk(VIDC_ERR,
1484 "Failed to queue output buffers: %d\n", rc);
1485 goto fail_start;
1486 }
1487 }
1488
1489fail_start:
1490 if (rc) {
1491 mutex_lock(&inst->pendingq.lock);
1492 list_for_each_entry_safe(temp, next, &inst->pendingq.list,
1493 list) {
1494 vb2_buffer_done(temp->vb,
1495 VB2_BUF_STATE_QUEUED);
1496 list_del(&temp->list);
1497 kfree(temp);
1498 }
1499 mutex_unlock(&inst->pendingq.lock);
1500 }
1501 return rc;
1502}
1503
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001504static int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
1505{
1506 struct msm_vidc_inst *inst;
1507 int rc = 0;
1508 struct hfi_device *hdev;
1509
1510 if (!q || !q->drv_priv) {
1511 dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q);
1512 return -EINVAL;
1513 }
1514 inst = q->drv_priv;
1515 if (!inst || !inst->core || !inst->core->device) {
1516 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
1517 return -EINVAL;
1518 }
1519 hdev = inst->core->device;
1520 dprintk(VIDC_DBG, "Streamon called on: %d capability for inst: %pK\n",
1521 q->type, inst);
1522 switch (q->type) {
1523 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1524 if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
1525 rc = start_streaming(inst);
1526 break;
1527 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1528 if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
1529 rc = start_streaming(inst);
1530 break;
1531 default:
1532 dprintk(VIDC_ERR, "Queue type is not supported: %d\n", q->type);
1533 rc = -EINVAL;
1534 goto stream_start_failed;
1535 }
1536 if (rc) {
1537 dprintk(VIDC_ERR,
1538 "Streamon failed on: %d capability for inst: %pK\n",
1539 q->type, inst);
1540 goto stream_start_failed;
1541 }
1542
1543 rc = msm_comm_qbuf(inst, NULL);
1544 if (rc) {
1545 dprintk(VIDC_ERR,
1546 "Failed to commit buffers queued before STREAM_ON to hardware: %d\n",
1547 rc);
1548 goto stream_start_failed;
1549 }
1550
1551stream_start_failed:
1552 return rc;
1553}
1554
1555static inline int stop_streaming(struct msm_vidc_inst *inst)
1556{
1557 int rc = 0;
1558
1559 rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
1560 if (rc)
1561 dprintk(VIDC_ERR,
1562 "Failed to move inst: %pK to state %d\n",
1563 inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07001564
1565 msm_clock_data_reset(inst);
1566
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001567 return rc;
1568}
1569
1570static void msm_vidc_stop_streaming(struct vb2_queue *q)
1571{
1572 struct msm_vidc_inst *inst;
1573 int rc = 0;
1574
1575 if (!q || !q->drv_priv) {
1576 dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q);
1577 return;
1578 }
1579
1580 inst = q->drv_priv;
1581 dprintk(VIDC_DBG, "Streamoff called on: %d capability\n", q->type);
1582 switch (q->type) {
1583 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1584 if (!inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
1585 rc = stop_streaming(inst);
1586 break;
1587 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1588 if (!inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
1589 rc = stop_streaming(inst);
1590 break;
1591 default:
1592 dprintk(VIDC_ERR,
1593 "Q-type is not supported: %d\n", q->type);
1594 rc = -EINVAL;
1595 break;
1596 }
1597
1598 msm_comm_scale_clocks_and_bus(inst);
1599
1600 if (rc)
1601 dprintk(VIDC_ERR,
1602 "Failed STOP Streaming inst = %pK on cap = %d\n",
1603 inst, q->type);
1604}
1605
1606static void msm_vidc_buf_queue(struct vb2_buffer *vb)
1607{
1608 int rc = msm_comm_qbuf(vb2_get_drv_priv(vb->vb2_queue), vb);
1609
1610 if (rc)
1611 dprintk(VIDC_ERR, "Failed to queue buffer: %d\n", rc);
1612}
1613
1614static const struct vb2_ops msm_vidc_vb2q_ops = {
1615 .queue_setup = msm_vidc_queue_setup,
1616 .start_streaming = msm_vidc_start_streaming,
1617 .buf_queue = msm_vidc_buf_queue,
1618 .buf_cleanup = msm_vidc_cleanup_buffer,
1619 .stop_streaming = msm_vidc_stop_streaming,
1620};
1621
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001622static inline int vb2_bufq_init(struct msm_vidc_inst *inst,
1623 enum v4l2_buf_type type, enum session_type sess)
1624{
1625 struct vb2_queue *q = NULL;
1626
1627 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1628 q = &inst->bufq[CAPTURE_PORT].vb2_bufq;
1629 } else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1630 q = &inst->bufq[OUTPUT_PORT].vb2_bufq;
1631 } else {
1632 dprintk(VIDC_ERR, "buf_type = %d not recognised\n", type);
1633 return -EINVAL;
1634 }
1635
1636 q->type = type;
1637 q->io_modes = VB2_MMAP | VB2_USERPTR;
1638 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001639 q->ops = &msm_vidc_vb2q_ops;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001640
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001641 q->mem_ops = &msm_vidc_vb2_mem_ops;
1642 q->drv_priv = inst;
1643 q->allow_zero_bytesused = 1;
Vaibhav Deshu Venkatesh362d0922017-03-02 14:16:11 -08001644 q->copy_timestamp = 1;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001645 return vb2_queue_init(q);
1646}
1647
1648static int setup_event_queue(void *inst,
1649 struct video_device *pvdev)
1650{
1651 int rc = 0;
1652 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1653
1654 v4l2_fh_init(&vidc_inst->event_handler, pvdev);
1655 v4l2_fh_add(&vidc_inst->event_handler);
1656
1657 return rc;
1658}
1659
1660int msm_vidc_subscribe_event(void *inst,
1661 const struct v4l2_event_subscription *sub)
1662{
1663 int rc = 0;
1664 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1665
1666 if (!inst || !sub)
1667 return -EINVAL;
1668
1669 rc = v4l2_event_subscribe(&vidc_inst->event_handler,
1670 sub, MAX_EVENTS, NULL);
1671 return rc;
1672}
1673EXPORT_SYMBOL(msm_vidc_subscribe_event);
1674
1675int msm_vidc_unsubscribe_event(void *inst,
1676 const struct v4l2_event_subscription *sub)
1677{
1678 int rc = 0;
1679 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1680
1681 if (!inst || !sub)
1682 return -EINVAL;
1683
1684 rc = v4l2_event_unsubscribe(&vidc_inst->event_handler, sub);
1685 return rc;
1686}
1687EXPORT_SYMBOL(msm_vidc_unsubscribe_event);
1688
1689int msm_vidc_dqevent(void *inst, struct v4l2_event *event)
1690{
1691 int rc = 0;
1692 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1693
1694 if (!inst || !event)
1695 return -EINVAL;
1696
1697 rc = v4l2_event_dequeue(&vidc_inst->event_handler, event, false);
1698 return rc;
1699}
1700EXPORT_SYMBOL(msm_vidc_dqevent);
1701
1702static bool msm_vidc_check_for_inst_overload(struct msm_vidc_core *core)
1703{
1704 u32 instance_count = 0;
1705 u32 secure_instance_count = 0;
1706 struct msm_vidc_inst *inst = NULL;
1707 bool overload = false;
1708
1709 mutex_lock(&core->lock);
1710 list_for_each_entry(inst, &core->instances, list) {
1711 instance_count++;
1712 /* This flag is not updated yet for the current instance */
1713 if (inst->flags & VIDC_SECURE)
1714 secure_instance_count++;
1715 }
1716 mutex_unlock(&core->lock);
1717
1718 /* Instance count includes current instance as well. */
1719
1720 if ((instance_count > core->resources.max_inst_count) ||
1721 (secure_instance_count > core->resources.max_secure_inst_count))
1722 overload = true;
1723 return overload;
1724}
1725
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001726static int msm_vidc_try_set_ctrl(void *instance, struct v4l2_ctrl *ctrl)
1727{
1728 struct msm_vidc_inst *inst = instance;
1729
1730 if (inst->session_type == MSM_VIDC_DECODER)
1731 return msm_vdec_s_ctrl(instance, ctrl);
1732 else if (inst->session_type == MSM_VIDC_ENCODER)
1733 return msm_venc_s_ctrl(instance, ctrl);
1734 return -EINVAL;
1735}
1736
1737static int msm_vidc_op_s_ctrl(struct v4l2_ctrl *ctrl)
1738{
1739
1740 int rc = 0, c = 0;
1741 struct msm_vidc_inst *inst;
1742
1743 if (!ctrl) {
1744 dprintk(VIDC_ERR, "%s invalid parameters for ctrl\n", __func__);
1745 return -EINVAL;
1746 }
1747
1748 inst = container_of(ctrl->handler,
1749 struct msm_vidc_inst, ctrl_handler);
1750 if (!inst) {
1751 dprintk(VIDC_ERR, "%s invalid parameters for inst\n", __func__);
1752 return -EINVAL;
1753 }
1754
1755 for (c = 0; c < ctrl->ncontrols; ++c) {
1756 if (ctrl->cluster[c]->is_new) {
1757 rc = msm_vidc_try_set_ctrl(inst, ctrl->cluster[c]);
1758 if (rc) {
1759 dprintk(VIDC_ERR, "Failed setting %x\n",
1760 ctrl->cluster[c]->id);
1761 break;
1762 }
1763 }
1764 }
1765 if (rc)
1766 dprintk(VIDC_ERR, "Failed setting control: Inst = %pK (%s)\n",
1767 inst, v4l2_ctrl_get_name(ctrl->id));
1768 return rc;
1769}
1770
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001771static int set_actual_buffer_count(struct msm_vidc_inst *inst,
1772 int count, enum hal_buffer type)
1773{
1774 int rc = 0;
1775 struct hfi_device *hdev;
1776 struct hal_buffer_count_actual buf_count;
1777
1778 hdev = inst->core->device;
1779
1780 buf_count.buffer_type = type;
1781 buf_count.buffer_count_min_host = count;
1782 buf_count.buffer_count_actual = count;
1783 rc = call_hfi_op(hdev, session_set_property,
1784 inst->session, HAL_PARAM_BUFFER_COUNT_ACTUAL,
1785 &buf_count);
1786 if (rc)
1787 dprintk(VIDC_ERR,
1788 "Failed to set actual count %d for buffer type %d\n",
1789 count, type);
1790 return rc;
1791}
1792
1793
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001794static int msm_vidc_get_count(struct msm_vidc_inst *inst,
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001795 struct v4l2_ctrl *ctrl)
1796{
1797 int rc = 0;
1798 struct hal_buffer_requirements *bufreq, *newreq;
1799 enum hal_buffer buffer_type;
1800
1801 if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_OUTPUT) {
1802 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT);
1803 if (!bufreq) {
1804 dprintk(VIDC_ERR,
1805 "Failed to find bufreqs for buffer type = %d\n",
1806 HAL_BUFFER_INPUT);
1807 return 0;
1808 }
1809 if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming) {
1810 ctrl->val = bufreq->buffer_count_min_host;
1811 return 0;
1812 }
1813 if (ctrl->val > bufreq->buffer_count_min_host) {
1814 dprintk(VIDC_DBG,
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001815 "Buffer count Host changed from %d to %d\n",
1816 bufreq->buffer_count_min_host,
1817 ctrl->val);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001818 bufreq->buffer_count_min_host = ctrl->val;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001819 } else {
1820 ctrl->val = bufreq->buffer_count_min_host;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001821 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001822 rc = set_actual_buffer_count(inst,
1823 bufreq->buffer_count_min_host,
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001824 HAL_BUFFER_INPUT);
1825 return rc;
1826
1827 } else if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) {
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001828
1829 buffer_type = msm_comm_get_hal_output_buffer(inst);
1830 bufreq = get_buff_req_buffer(inst,
1831 buffer_type);
1832 if (!bufreq) {
1833 dprintk(VIDC_ERR,
1834 "Failed to find bufreqs for buffer type = %d\n",
1835 buffer_type);
1836 return 0;
1837 }
1838 if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming) {
1839 if (ctrl->val != bufreq->buffer_count_min_host)
1840 return -EINVAL;
1841 else
1842 return 0;
1843 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001844
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001845
1846 if (inst->in_reconfig) {
1847 rc = msm_comm_try_get_bufreqs(inst);
1848 newreq = get_buff_req_buffer(inst,
1849 buffer_type);
1850 if (!newreq) {
1851 dprintk(VIDC_ERR,
1852 "Failed to find new bufreqs = %d\n",
1853 buffer_type);
1854 return 0;
1855 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001856 ctrl->val = newreq->buffer_count_min;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001857 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001858 if (inst->session_type == MSM_VIDC_DECODER &&
1859 !inst->in_reconfig &&
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001860 inst->state < MSM_VIDC_LOAD_RESOURCES_DONE) {
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001861 dprintk(VIDC_DBG,
1862 "Clients updates Buffer count from %d to %d\n",
1863 bufreq->buffer_count_min_host, ctrl->val);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001864 bufreq->buffer_count_min_host = ctrl->val;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001865 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001866 if (ctrl->val > bufreq->buffer_count_min_host) {
1867 dprintk(VIDC_DBG,
1868 "Buffer count Host changed from %d to %d\n",
1869 bufreq->buffer_count_min_host,
1870 ctrl->val);
1871 bufreq->buffer_count_min_host = ctrl->val;
1872 } else {
1873 ctrl->val = bufreq->buffer_count_min_host;
1874 }
1875 rc = set_actual_buffer_count(inst,
1876 bufreq->buffer_count_min_host,
1877 HAL_BUFFER_OUTPUT);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001878
1879 return rc;
1880 }
1881 return -EINVAL;
1882}
1883
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001884static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
1885{
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001886 int rc = 0;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001887 struct hal_buffer_requirements *bufreq = NULL;
1888 enum hal_buffer buffer_type;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001889
1890 switch (ctrl->id) {
1891
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001892 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001893 case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE:
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001894 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001895 ctrl->val = inst->profile;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001896 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001897
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001898 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
Chinmay Sawarkar7f1cc152017-05-05 18:16:36 -07001899 case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001900 case V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL:
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001901 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001902 ctrl->val = inst->level;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001903 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001904
1905 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
1906 ctrl->val = inst->entropy_mode;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001907 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001908
1909 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001910 if (inst->in_reconfig)
1911 msm_comm_try_get_bufreqs(inst);
1912
1913 buffer_type = msm_comm_get_hal_output_buffer(inst);
1914 bufreq = get_buff_req_buffer(inst,
1915 buffer_type);
1916 if (!bufreq) {
1917 dprintk(VIDC_ERR,
1918 "Failed to find bufreqs for buffer type = %d\n",
1919 buffer_type);
1920 return -EINVAL;
1921 }
1922 ctrl->val = bufreq->buffer_count_min_host;
1923 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001924 case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001925 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT);
1926 if (!bufreq) {
1927 dprintk(VIDC_ERR,
1928 "Failed to find bufreqs for buffer type = %d\n",
1929 HAL_BUFFER_INPUT);
1930 return -EINVAL;
1931 }
1932 ctrl->val = bufreq->buffer_count_min_host;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001933 break;
1934 default:
1935 /*
1936 * Other controls aren't really volatile, shouldn't need to
1937 * modify ctrl->value
1938 */
1939 break;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001940 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001941
1942 return rc;
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001943}
1944
1945static int msm_vidc_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1946{
1947 int rc = 0, c = 0;
1948 struct msm_vidc_inst *inst;
1949 struct v4l2_ctrl *master;
1950
1951 if (!ctrl) {
1952 dprintk(VIDC_ERR, "%s invalid parameters for ctrl\n", __func__);
1953 return -EINVAL;
1954 }
1955
1956 inst = container_of(ctrl->handler,
1957 struct msm_vidc_inst, ctrl_handler);
1958 if (!inst) {
1959 dprintk(VIDC_ERR, "%s invalid parameters for inst\n", __func__);
1960 return -EINVAL;
1961 }
1962 master = ctrl->cluster[0];
1963 if (!master) {
1964 dprintk(VIDC_ERR, "%s invalid parameters for master\n",
1965 __func__);
1966 return -EINVAL;
1967 }
1968
1969 for (c = 0; c < master->ncontrols; ++c) {
1970 if (master->cluster[c]->flags & V4L2_CTRL_FLAG_VOLATILE) {
1971 rc = try_get_ctrl(inst, master->cluster[c]);
1972 if (rc) {
1973 dprintk(VIDC_ERR, "Failed getting %x\n",
1974 master->cluster[c]->id);
1975 return rc;
1976 }
1977 }
1978 }
1979 if (rc)
1980 dprintk(VIDC_ERR, "Failed getting control: Inst = %pK (%s)\n",
1981 inst, v4l2_ctrl_get_name(ctrl->id));
1982 return rc;
1983}
1984
1985static const struct v4l2_ctrl_ops msm_vidc_ctrl_ops = {
1986
1987 .s_ctrl = msm_vidc_op_s_ctrl,
1988 .g_volatile_ctrl = msm_vidc_op_g_volatile_ctrl,
1989};
1990
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001991void *msm_vidc_open(int core_id, int session_type)
1992{
1993 struct msm_vidc_inst *inst = NULL;
1994 struct msm_vidc_core *core = NULL;
1995 int rc = 0;
1996 int i = 0;
1997
1998 if (core_id >= MSM_VIDC_CORES_MAX ||
1999 session_type >= MSM_VIDC_MAX_DEVICES) {
2000 dprintk(VIDC_ERR, "Invalid input, core_id = %d, session = %d\n",
2001 core_id, session_type);
2002 goto err_invalid_core;
2003 }
2004 core = get_vidc_core(core_id);
2005 if (!core) {
2006 dprintk(VIDC_ERR,
2007 "Failed to find core for core_id = %d\n", core_id);
2008 goto err_invalid_core;
2009 }
2010
2011 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
2012 if (!inst) {
2013 dprintk(VIDC_ERR, "Failed to allocate memory\n");
2014 rc = -ENOMEM;
2015 goto err_invalid_core;
2016 }
2017
2018 pr_info(VIDC_DBG_TAG "Opening video instance: %pK, %d\n",
2019 VIDC_MSG_PRIO2STRING(VIDC_INFO), inst, session_type);
2020 mutex_init(&inst->sync_lock);
2021 mutex_init(&inst->bufq[CAPTURE_PORT].lock);
2022 mutex_init(&inst->bufq[OUTPUT_PORT].lock);
2023 mutex_init(&inst->lock);
2024
2025 INIT_MSM_VIDC_LIST(&inst->pendingq);
2026 INIT_MSM_VIDC_LIST(&inst->scratchbufs);
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002027 INIT_MSM_VIDC_LIST(&inst->freqs);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002028 INIT_MSM_VIDC_LIST(&inst->persistbufs);
2029 INIT_MSM_VIDC_LIST(&inst->pending_getpropq);
2030 INIT_MSM_VIDC_LIST(&inst->outputbufs);
2031 INIT_MSM_VIDC_LIST(&inst->registeredbufs);
2032
2033 kref_init(&inst->kref);
2034
2035 inst->session_type = session_type;
2036 inst->state = MSM_VIDC_CORE_UNINIT_DONE;
2037 inst->core = core;
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07002038 inst->clk_data.min_freq = 0;
2039 inst->clk_data.curr_freq = 0;
2040 inst->clk_data.bitrate = 0;
2041 inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002042 inst->bit_depth = MSM_VIDC_BIT_DEPTH_8;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002043 inst->pic_struct = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
2044 inst->colour_space = MSM_VIDC_BT601_6_525;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -08002045 inst->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
2046 inst->level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
2047 inst->entropy_mode = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002048
2049 for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
2050 i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) {
2051 init_completion(&inst->completions[i]);
2052 }
2053 inst->mem_client = msm_smem_new_client(SMEM_ION,
2054 &inst->core->resources, session_type);
2055 if (!inst->mem_client) {
2056 dprintk(VIDC_ERR, "Failed to create memory client\n");
2057 goto fail_mem_client;
2058 }
Praneeth Paladugube42cb22016-04-12 22:34:39 -07002059
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002060 if (session_type == MSM_VIDC_DECODER) {
2061 msm_vdec_inst_init(inst);
Praneeth Paladugube42cb22016-04-12 22:34:39 -07002062 rc = msm_vdec_ctrl_init(inst, &msm_vidc_ctrl_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002063 } else if (session_type == MSM_VIDC_ENCODER) {
2064 msm_venc_inst_init(inst);
Praneeth Paladugube42cb22016-04-12 22:34:39 -07002065 rc = msm_venc_ctrl_init(inst, &msm_vidc_ctrl_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002066 }
2067
2068 if (rc)
2069 goto fail_bufq_capture;
2070
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002071 rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
2072 session_type);
2073 if (rc) {
2074 dprintk(VIDC_ERR,
2075 "Failed to initialize vb2 queue on capture port\n");
2076 goto fail_bufq_capture;
2077 }
2078 rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
2079 session_type);
2080 if (rc) {
2081 dprintk(VIDC_ERR,
2082 "Failed to initialize vb2 queue on capture port\n");
2083 goto fail_bufq_output;
2084 }
2085
2086 setup_event_queue(inst, &core->vdev[session_type].vdev);
2087
2088 mutex_lock(&core->lock);
2089 list_add_tail(&inst->list, &core->instances);
2090 mutex_unlock(&core->lock);
2091
2092 rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT_DONE);
2093 if (rc) {
2094 dprintk(VIDC_ERR,
2095 "Failed to move video instance to init state\n");
2096 goto fail_init;
2097 }
2098
Praneeth Paladugu13c90962017-04-24 13:15:28 -07002099 msm_dcvs_try_enable(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002100 if (msm_vidc_check_for_inst_overload(core)) {
2101 dprintk(VIDC_ERR,
2102 "Instance count reached Max limit, rejecting session");
2103 goto fail_init;
2104 }
2105
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07002106 msm_comm_scale_clocks_and_bus(inst);
2107
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002108 inst->debugfs_root =
2109 msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
2110
2111 return inst;
2112fail_init:
2113 mutex_lock(&core->lock);
2114 list_del(&inst->list);
2115 mutex_unlock(&core->lock);
2116
2117 v4l2_fh_del(&inst->event_handler);
2118 v4l2_fh_exit(&inst->event_handler);
2119 vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
2120fail_bufq_output:
2121 vb2_queue_release(&inst->bufq[CAPTURE_PORT].vb2_bufq);
2122fail_bufq_capture:
2123 msm_comm_ctrl_deinit(inst);
2124 msm_smem_delete_client(inst->mem_client);
2125fail_mem_client:
2126 mutex_destroy(&inst->sync_lock);
2127 mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
2128 mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
2129 mutex_destroy(&inst->lock);
2130
2131 DEINIT_MSM_VIDC_LIST(&inst->pendingq);
2132 DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
2133 DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
2134 DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
2135 DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
2136 DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
2137
2138 kfree(inst);
2139 inst = NULL;
2140err_invalid_core:
2141 return inst;
2142}
2143EXPORT_SYMBOL(msm_vidc_open);
2144
2145static void cleanup_instance(struct msm_vidc_inst *inst)
2146{
2147 struct vb2_buf_entry *entry, *dummy;
2148
2149 if (inst) {
2150
2151 mutex_lock(&inst->pendingq.lock);
2152 list_for_each_entry_safe(entry, dummy, &inst->pendingq.list,
2153 list) {
2154 list_del(&entry->list);
2155 kfree(entry);
2156 }
2157 mutex_unlock(&inst->pendingq.lock);
2158
Praneeth Paladugub71968b2015-08-19 20:47:57 -07002159 msm_comm_free_freq_table(inst);
2160
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002161 if (msm_comm_release_scratch_buffers(inst, false)) {
2162 dprintk(VIDC_ERR,
2163 "Failed to release scratch buffers\n");
2164 }
2165
2166 if (msm_comm_release_persist_buffers(inst)) {
2167 dprintk(VIDC_ERR,
2168 "Failed to release persist buffers\n");
2169 }
2170
Vaibhav Deshu Venkatesh8c9b6db2017-02-08 11:22:36 -08002171 /*
2172 * At this point all buffes should be with driver
2173 * irrespective of scenario
2174 */
2175 msm_comm_validate_output_buffers(inst);
2176
2177 if (msm_comm_release_output_buffers(inst, true)) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002178 dprintk(VIDC_ERR,
2179 "Failed to release output buffers\n");
2180 }
2181
2182 if (inst->extradata_handle)
2183 msm_comm_smem_free(inst, inst->extradata_handle);
2184
2185 debugfs_remove_recursive(inst->debugfs_root);
2186
2187 mutex_lock(&inst->pending_getpropq.lock);
2188 WARN_ON(!list_empty(&inst->pending_getpropq.list));
2189 mutex_unlock(&inst->pending_getpropq.lock);
2190 }
2191}
2192
2193int msm_vidc_destroy(struct msm_vidc_inst *inst)
2194{
2195 struct msm_vidc_core *core;
2196 int i = 0;
2197
2198 if (!inst || !inst->core)
2199 return -EINVAL;
2200
2201 core = inst->core;
2202
2203 mutex_lock(&core->lock);
2204 /* inst->list lives in core->instances */
2205 list_del(&inst->list);
2206 mutex_unlock(&core->lock);
2207
2208 msm_comm_ctrl_deinit(inst);
2209
2210 DEINIT_MSM_VIDC_LIST(&inst->pendingq);
2211 DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
2212 DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
2213 DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
2214 DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
2215 DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
2216
2217 v4l2_fh_del(&inst->event_handler);
2218 v4l2_fh_exit(&inst->event_handler);
2219
2220 for (i = 0; i < MAX_PORT_NUM; i++)
2221 vb2_queue_release(&inst->bufq[i].vb2_bufq);
2222
2223 mutex_destroy(&inst->sync_lock);
2224 mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
2225 mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
2226 mutex_destroy(&inst->lock);
2227
2228 pr_info(VIDC_DBG_TAG "Closed video instance: %pK\n",
2229 VIDC_MSG_PRIO2STRING(VIDC_INFO), inst);
2230 kfree(inst);
2231 return 0;
2232}
2233
2234int msm_vidc_close(void *instance)
2235{
2236 void close_helper(struct kref *kref)
2237 {
2238 struct msm_vidc_inst *inst = container_of(kref,
2239 struct msm_vidc_inst, kref);
2240
2241 msm_vidc_destroy(inst);
2242 }
2243
2244 struct msm_vidc_inst *inst = instance;
2245 struct buffer_info *bi, *dummy;
2246 int rc = 0;
2247
2248 if (!inst || !inst->core)
2249 return -EINVAL;
2250
Praneeth Paladuguceec6d82016-12-21 15:09:57 -08002251 /*
2252 * Make sure that HW stop working on these buffers that
2253 * we are going to free.
2254 */
2255 if (inst->state != MSM_VIDC_CORE_INVALID &&
2256 inst->core->state != VIDC_CORE_INVALID)
2257 rc = msm_comm_try_state(inst,
2258 MSM_VIDC_RELEASE_RESOURCES_DONE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002259
2260 mutex_lock(&inst->registeredbufs.lock);
2261 list_for_each_entry_safe(bi, dummy, &inst->registeredbufs.list, list) {
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002262 int i = 0;
2263
2264 list_del(&bi->list);
2265
2266 for (i = 0; i < min(bi->num_planes, VIDEO_MAX_PLANES);
2267 i++) {
2268 if (bi->handle[i] && bi->mapped[i])
2269 msm_comm_smem_free(inst, bi->handle[i]);
2270 }
2271
2272 kfree(bi);
2273 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08002274 mutex_unlock(&inst->registeredbufs.lock);
2275
2276 cleanup_instance(inst);
2277 if (inst->state != MSM_VIDC_CORE_INVALID &&
2278 inst->core->state != VIDC_CORE_INVALID)
2279 rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
2280 else
2281 rc = msm_comm_force_cleanup(inst);
2282 if (rc)
2283 dprintk(VIDC_ERR,
2284 "Failed to move video instance to uninit state\n");
2285
2286 msm_comm_session_clean(inst);
2287 msm_smem_delete_client(inst->mem_client);
2288
2289 kref_put(&inst->kref, close_helper);
2290 return 0;
2291}
2292EXPORT_SYMBOL(msm_vidc_close);
2293
2294int msm_vidc_suspend(int core_id)
2295{
2296 return msm_comm_suspend(core_id);
2297}
2298EXPORT_SYMBOL(msm_vidc_suspend);
2299