blob: 6c327d1ee9f4c84b2557353c96b00343dab94b20 [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"
Maheshwar Ajjac6407c02017-06-09 18:53:20 -070026#include <linux/dma-buf.h>
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080027
28#define MAX_EVENTS 30
29
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -070030static int try_get_ctrl(struct msm_vidc_inst *inst,
31 struct v4l2_ctrl *ctrl);
Praneeth Paladugu13c90962017-04-24 13:15:28 -070032static int msm_vidc_get_count(struct msm_vidc_inst *inst,
33 struct v4l2_ctrl *ctrl);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -070034
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -080035static int get_poll_flags(void *instance)
36{
37 struct msm_vidc_inst *inst = instance;
38 struct vb2_queue *outq = &inst->bufq[OUTPUT_PORT].vb2_bufq;
39 struct vb2_queue *capq = &inst->bufq[CAPTURE_PORT].vb2_bufq;
40 struct vb2_buffer *out_vb = NULL;
41 struct vb2_buffer *cap_vb = NULL;
42 unsigned long flags;
43 int rc = 0;
44
45 if (v4l2_event_pending(&inst->event_handler))
46 rc |= POLLPRI;
47
48 spin_lock_irqsave(&capq->done_lock, flags);
49 if (!list_empty(&capq->done_list))
50 cap_vb = list_first_entry(&capq->done_list, struct vb2_buffer,
51 done_entry);
52 if (cap_vb && (cap_vb->state == VB2_BUF_STATE_DONE
53 || cap_vb->state == VB2_BUF_STATE_ERROR))
54 rc |= POLLIN | POLLRDNORM;
55 spin_unlock_irqrestore(&capq->done_lock, flags);
56
57 spin_lock_irqsave(&outq->done_lock, flags);
58 if (!list_empty(&outq->done_list))
59 out_vb = list_first_entry(&outq->done_list, struct vb2_buffer,
60 done_entry);
61 if (out_vb && (out_vb->state == VB2_BUF_STATE_DONE
62 || out_vb->state == VB2_BUF_STATE_ERROR))
63 rc |= POLLOUT | POLLWRNORM;
64 spin_unlock_irqrestore(&outq->done_lock, flags);
65
66 return rc;
67}
68
69int msm_vidc_poll(void *instance, struct file *filp,
70 struct poll_table_struct *wait)
71{
72 struct msm_vidc_inst *inst = instance;
73 struct vb2_queue *outq = NULL;
74 struct vb2_queue *capq = NULL;
75
76 if (!inst)
77 return -EINVAL;
78
79 outq = &inst->bufq[OUTPUT_PORT].vb2_bufq;
80 capq = &inst->bufq[CAPTURE_PORT].vb2_bufq;
81
82 poll_wait(filp, &inst->event_handler.wait, wait);
83 poll_wait(filp, &capq->done_wq, wait);
84 poll_wait(filp, &outq->done_wq, wait);
85 return get_poll_flags(inst);
86}
87EXPORT_SYMBOL(msm_vidc_poll);
88
89int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
90{
91 struct msm_vidc_inst *inst = instance;
92
93 if (!inst || !cap)
94 return -EINVAL;
95
Praneeth Paladugube42cb22016-04-12 22:34:39 -070096 strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
97 cap->bus_info[0] = 0;
98 cap->version = MSM_VIDC_VERSION;
99 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
100 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
101 V4L2_CAP_STREAMING;
102 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
103
104 memset(cap->reserved, 0, sizeof(cap->reserved));
105
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800106 if (inst->session_type == MSM_VIDC_DECODER)
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700107 strlcpy(cap->card, MSM_VDEC_DVC_NAME, sizeof(cap->card));
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800108 else if (inst->session_type == MSM_VIDC_ENCODER)
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700109 strlcpy(cap->card, MSM_VENC_DVC_NAME, sizeof(cap->card));
110 else
111 return -EINVAL;
112
113 return 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800114}
115EXPORT_SYMBOL(msm_vidc_querycap);
116
117int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
118{
119 struct msm_vidc_inst *inst = instance;
120
121 if (!inst || !f)
122 return -EINVAL;
123
124 if (inst->session_type == MSM_VIDC_DECODER)
125 return msm_vdec_enum_fmt(instance, f);
126 else if (inst->session_type == MSM_VIDC_ENCODER)
127 return msm_venc_enum_fmt(instance, f);
128 return -EINVAL;
129}
130EXPORT_SYMBOL(msm_vidc_enum_fmt);
131
Praneeth Paladugue1679112017-01-27 10:07:15 -0800132static void msm_vidc_ctrl_get_range(struct v4l2_queryctrl *ctrl,
133 struct hal_capability_supported *capability)
134
135{
136 ctrl->maximum = capability->max;
137 ctrl->minimum = capability->min;
138}
139
140int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *ctrl)
141{
142 struct msm_vidc_inst *inst = instance;
143 int rc = 0;
144
145 if (!inst || !ctrl)
146 return -EINVAL;
147
148 switch (ctrl->id) {
149 case V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE:
150 msm_vidc_ctrl_get_range(ctrl,
151 &inst->capability.hier_p_hybrid);
152 break;
153 case V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS:
154 msm_vidc_ctrl_get_range(ctrl, &inst->capability.hier_b);
155 break;
156 case V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS:
157 msm_vidc_ctrl_get_range(ctrl, &inst->capability.hier_p);
158 break;
Vaibhav Deshu Venkatesh2c072532017-04-07 17:50:18 -0700159 case V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE:
Praneeth Paladugue1679112017-01-27 10:07:15 -0800160 case V4L2_CID_MPEG_VIDEO_BITRATE:
161 msm_vidc_ctrl_get_range(ctrl, &inst->capability.bitrate);
162 break;
163 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
164 msm_vidc_ctrl_get_range(ctrl, &inst->capability.peakbitrate);
165 break;
166 case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH:
167 msm_vidc_ctrl_get_range(ctrl, &inst->capability.blur_width);
168 break;
169 case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT:
170 msm_vidc_ctrl_get_range(ctrl, &inst->capability.blur_height);
171 break;
Saurabh Kothawadeb11d81c2017-05-18 19:07:17 -0700172 case V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES:
173 msm_vidc_ctrl_get_range(ctrl, &inst->capability.bframe);
174 break;
Saurabh Kothawade0425f242017-05-25 11:19:30 -0700175 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
176 msm_vidc_ctrl_get_range(ctrl, &inst->capability.slice_mbs);
177 break;
178 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
179 msm_vidc_ctrl_get_range(ctrl, &inst->capability.slice_bytes);
180 break;
Praneeth Paladugue1679112017-01-27 10:07:15 -0800181 default:
182 rc = -EINVAL;
183 }
184 return rc;
185}
186EXPORT_SYMBOL(msm_vidc_query_ctrl);
187
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800188int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
189{
190 struct msm_vidc_inst *inst = instance;
191
192 if (!inst || !f)
193 return -EINVAL;
194
195 if (inst->session_type == MSM_VIDC_DECODER)
196 return msm_vdec_s_fmt(instance, f);
197 if (inst->session_type == MSM_VIDC_ENCODER)
198 return msm_venc_s_fmt(instance, f);
199 return -EINVAL;
200}
201EXPORT_SYMBOL(msm_vidc_s_fmt);
202
203int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
204{
205 struct msm_vidc_inst *inst = instance;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800206 int i, rc = 0, color_format = 0;
207 enum vidc_ports port;
208 u32 num_planes;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800209
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800210 if (!inst || !f) {
211 dprintk(VIDC_ERR,
212 "Invalid input, inst = %pK, format = %pK\n", inst, f);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800213 return -EINVAL;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800214 }
215 if (inst->in_reconfig) {
216 inst->prop.height[OUTPUT_PORT] = inst->reconfig_height;
217 inst->prop.width[OUTPUT_PORT] = inst->reconfig_width;
218 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800219
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800220 port = f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
221 OUTPUT_PORT : CAPTURE_PORT;
222
223 f->fmt.pix_mp.pixelformat = inst->fmts[port].fourcc;
224 f->fmt.pix_mp.height = inst->prop.height[port];
225 f->fmt.pix_mp.width = inst->prop.width[port];
226 num_planes = f->fmt.pix_mp.num_planes = inst->bufq[port].num_planes;
227 for (i = 0; i < num_planes; ++i)
228 f->fmt.pix_mp.plane_fmt[i].sizeimage =
229 inst->bufq[port].plane_sizes[i];
230 switch (inst->fmts[port].fourcc) {
231 case V4L2_PIX_FMT_NV12:
232 color_format = COLOR_FMT_NV12;
233 break;
234 case V4L2_PIX_FMT_NV12_UBWC:
235 color_format = COLOR_FMT_NV12_UBWC;
236 break;
237 case V4L2_PIX_FMT_NV12_TP10_UBWC:
238 color_format = COLOR_FMT_NV12_BPP10_UBWC;
Zhongbo Shi6bd5f5f2017-08-16 17:20:08 +0800239 case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010:
240 color_format = COLOR_FMT_P010;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800241 break;
242 default:
243 dprintk(VIDC_DBG,
244 "Invalid : g_fmt called on %s port with Invalid fourcc 0x%x\n",
245 port == OUTPUT_PORT ? "OUTPUT" : "CAPTURE",
246 inst->fmts[port].fourcc);
247 goto exit;
248 }
249
250 f->fmt.pix_mp.plane_fmt[0].bytesperline = VENUS_Y_STRIDE(color_format,
251 inst->prop.width[port]);
252 f->fmt.pix_mp.plane_fmt[0].reserved[0] = VENUS_Y_SCANLINES(color_format,
253 inst->prop.height[port]);
254
255exit:
256 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800257}
258EXPORT_SYMBOL(msm_vidc_g_fmt);
259
260int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
261{
262 struct msm_vidc_inst *inst = instance;
263
264 if (!inst || !control)
265 return -EINVAL;
266
267 return msm_comm_s_ctrl(instance, control);
268}
269EXPORT_SYMBOL(msm_vidc_s_ctrl);
270
Praneeth Paladugu72fa67b2017-05-30 11:20:01 -0700271int msm_vidc_g_crop(void *instance, struct v4l2_crop *crop)
272{
273 struct msm_vidc_inst *inst = instance;
274
275 if (!inst || !crop)
276 return -EINVAL;
277
278 if (inst->session_type == MSM_VIDC_ENCODER) {
279 dprintk(VIDC_ERR,
280 "Session = %pK : Encoder Crop is not implemented yet\n",
281 inst);
282 return -EPERM;
283 }
284
285 crop->c.left = inst->prop.crop_info.left;
286 crop->c.top = inst->prop.crop_info.top;
287 crop->c.width = inst->prop.crop_info.width;
288 crop->c.height = inst->prop.crop_info.height;
289
290 return 0;
291}
292EXPORT_SYMBOL(msm_vidc_g_crop);
293
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800294int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
295{
296 struct msm_vidc_inst *inst = instance;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700297 struct v4l2_ctrl *ctrl = NULL;
298 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800299
300 if (!inst || !control)
301 return -EINVAL;
302
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700303 ctrl = v4l2_ctrl_find(&inst->ctrl_handler, control->id);
304 if (ctrl) {
305 rc = try_get_ctrl(inst, ctrl);
306 if (!rc)
307 control->value = ctrl->val;
308 }
309
310 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800311}
312EXPORT_SYMBOL(msm_vidc_g_ctrl);
313
Praneeth Paladugu13c90962017-04-24 13:15:28 -0700314int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
315{
316 struct msm_vidc_inst *inst = instance;
317 struct v4l2_ext_control *ext_control;
318 struct v4l2_ctrl ctrl;
319 int i = 0, rc = 0;
320
321 if (!inst || !control)
322 return -EINVAL;
323
324 ext_control = control->controls;
325
326 for (i = 0; i < control->count; i++) {
327 switch (ext_control[i].id) {
328 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
329 case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
330 ctrl.id = ext_control[i].id;
331 ctrl.val = ext_control[i].value;
332
333 msm_vidc_get_count(inst, &ctrl);
334 ext_control->value = ctrl.val;
335 break;
336 default:
337 dprintk(VIDC_ERR,
338 "This control %x is not supported yet\n",
339 ext_control[i].id);
340 rc = -EINVAL;
341 break;
342 }
343 }
344 return rc;
345}
346EXPORT_SYMBOL(msm_vidc_g_ext_ctrl);
347
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800348int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
349{
350 struct msm_vidc_inst *inst = instance;
351
352 if (!inst || !control)
353 return -EINVAL;
354
355 if (inst->session_type == MSM_VIDC_DECODER)
356 return msm_vdec_s_ext_ctrl(instance, control);
357 if (inst->session_type == MSM_VIDC_ENCODER)
358 return msm_venc_s_ext_ctrl(instance, control);
359 return -EINVAL;
360}
361EXPORT_SYMBOL(msm_vidc_s_ext_ctrl);
362
363int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
364{
365 struct msm_vidc_inst *inst = instance;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700366 struct buf_queue *q = NULL;
367 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800368
369 if (!inst || !b)
370 return -EINVAL;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700371 q = msm_comm_get_vb2q(inst, b->type);
372 if (!q) {
373 dprintk(VIDC_ERR,
374 "Failed to find buffer queue for type = %d\n",
375 b->type);
376 return -EINVAL;
377 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800378
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700379 mutex_lock(&q->lock);
380 rc = vb2_reqbufs(&q->vb2_bufq, b);
381 mutex_unlock(&q->lock);
382
383 if (rc)
384 dprintk(VIDC_ERR, "Failed to get reqbufs, %d\n", rc);
385 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800386}
387EXPORT_SYMBOL(msm_vidc_reqbufs);
388
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800389static bool valid_v4l2_buffer(struct v4l2_buffer *b,
390 struct msm_vidc_inst *inst) {
391 enum vidc_ports port =
392 !V4L2_TYPE_IS_MULTIPLANAR(b->type) ? MAX_PORT_NUM :
393 b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ? CAPTURE_PORT :
394 b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? OUTPUT_PORT :
395 MAX_PORT_NUM;
396
397 return port != MAX_PORT_NUM &&
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800398 inst->bufq[port].num_planes == b->length;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800399}
400
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700401int msm_vidc_release_buffer(void *instance, int type, unsigned int index)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800402{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700403 int rc = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800404 struct msm_vidc_inst *inst = instance;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700405 struct msm_vidc_buffer *mbuf, *dummy;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800406
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700407 if (!inst) {
408 dprintk(VIDC_ERR, "%s: invalid inst\n", __func__);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800409 return -EINVAL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700410 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800411
412 if (!inst->in_reconfig &&
413 inst->state > MSM_VIDC_LOAD_RESOURCES &&
414 inst->state < MSM_VIDC_RELEASE_RESOURCES_DONE) {
415 rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
416 if (rc) {
417 dprintk(VIDC_ERR,
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700418 "%s: Failed to move inst: %pK to release res done\n",
419 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800420 }
421 }
422
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800423 mutex_lock(&inst->registeredbufs.lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700424 list_for_each_entry_safe(mbuf, dummy, &inst->registeredbufs.list,
425 list) {
426 struct vb2_buffer *vb2 = &mbuf->vvb.vb2_buf;
427
428 if (vb2->type != type || vb2->index != index)
429 continue;
430
431 print_vidc_buffer(VIDC_DBG, "release buf", inst, mbuf);
432 msm_comm_unmap_vidc_buffer(inst, mbuf);
433 list_del(&mbuf->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -0700434 kref_put_mbuf(mbuf);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800435 }
436 mutex_unlock(&inst->registeredbufs.lock);
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800437
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800438 return rc;
439}
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800440EXPORT_SYMBOL(msm_vidc_release_buffer);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800441
442int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
443{
444 struct msm_vidc_inst *inst = instance;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700445 int rc = 0, i = 0;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700446 struct buf_queue *q = NULL;
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -0700447 u32 cr = 0;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800448
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700449 if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
450 dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
451 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800452 return -EINVAL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800453 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800454
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700455 for (i = 0; i < b->length; i++) {
456 b->m.planes[i].m.fd = b->m.planes[i].reserved[0];
457 b->m.planes[i].data_offset = b->m.planes[i].reserved[1];
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800458 }
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -0700459
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700460 msm_comm_qbuf_cache_operations(inst, b);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800461
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -0700462 /* Compression ratio is valid only for Encoder YUV buffers. */
463 if (inst->session_type == MSM_VIDC_ENCODER &&
464 b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
465 cr = b->m.planes[0].reserved[2];
466 msm_comm_update_input_cr(inst, b->index, cr);
467 }
468
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700469 q = msm_comm_get_vb2q(inst, b->type);
470 if (!q) {
471 dprintk(VIDC_ERR,
472 "Failed to find buffer queue for type = %d\n", b->type);
473 return -EINVAL;
474 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700475
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700476 mutex_lock(&q->lock);
477 rc = vb2_qbuf(&q->vb2_bufq, b);
478 mutex_unlock(&q->lock);
479 if (rc)
480 dprintk(VIDC_ERR, "Failed to qbuf, %d\n", rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800481
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700482 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800483}
484EXPORT_SYMBOL(msm_vidc_qbuf);
485
486int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
487{
488 struct msm_vidc_inst *inst = instance;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700489 int rc = 0, i = 0;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700490 struct buf_queue *q = NULL;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800491
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700492 if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
493 dprintk(VIDC_ERR, "%s: invalid params, inst %pK\n",
494 __func__, inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800495 return -EINVAL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700496 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800497
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700498 q = msm_comm_get_vb2q(inst, b->type);
499 if (!q) {
500 dprintk(VIDC_ERR,
501 "Failed to find buffer queue for type = %d\n", b->type);
502 return -EINVAL;
503 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700504
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700505 mutex_lock(&q->lock);
506 rc = vb2_dqbuf(&q->vb2_bufq, b, true);
507 mutex_unlock(&q->lock);
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700508 if (rc == -EAGAIN) {
509 return rc;
510 } else if (rc) {
511 dprintk(VIDC_ERR, "Failed to dqbuf, %d\n", rc);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800512 return rc;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700513 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800514
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700515 msm_comm_dqbuf_cache_operations(inst, b);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800516 for (i = 0; i < b->length; i++) {
Maheshwar Ajjac6407c02017-06-09 18:53:20 -0700517 b->m.planes[i].reserved[0] = b->m.planes[i].m.fd;
518 b->m.planes[i].reserved[1] = b->m.planes[i].data_offset;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800519 }
520
521 return rc;
522}
523EXPORT_SYMBOL(msm_vidc_dqbuf);
524
525int msm_vidc_streamon(void *instance, enum v4l2_buf_type i)
526{
527 struct msm_vidc_inst *inst = instance;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700528 int rc = 0;
529 struct buf_queue *q;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800530
531 if (!inst)
532 return -EINVAL;
533
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700534 q = msm_comm_get_vb2q(inst, i);
535 if (!q) {
536 dprintk(VIDC_ERR,
537 "Failed to find buffer queue for type = %d\n", i);
538 return -EINVAL;
539 }
540 dprintk(VIDC_DBG, "Calling streamon\n");
541 mutex_lock(&q->lock);
542 rc = vb2_streamon(&q->vb2_bufq, i);
543 mutex_unlock(&q->lock);
544 if (rc)
545 dprintk(VIDC_ERR, "streamon failed on port: %d\n", i);
546 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800547}
548EXPORT_SYMBOL(msm_vidc_streamon);
549
550int msm_vidc_streamoff(void *instance, enum v4l2_buf_type i)
551{
552 struct msm_vidc_inst *inst = instance;
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700553 int rc = 0;
554 struct buf_queue *q;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800555
556 if (!inst)
557 return -EINVAL;
558
Praneeth Paladugube42cb22016-04-12 22:34:39 -0700559 q = msm_comm_get_vb2q(inst, i);
560 if (!q) {
561 dprintk(VIDC_ERR,
562 "Failed to find buffer queue for type = %d\n", i);
563 return -EINVAL;
564 }
565 dprintk(VIDC_DBG, "Calling streamoff\n");
566 mutex_lock(&q->lock);
567 rc = vb2_streamoff(&q->vb2_bufq, i);
568 mutex_unlock(&q->lock);
569 if (rc)
570 dprintk(VIDC_ERR, "streamoff failed on port: %d\n", i);
571 return rc;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -0800572}
573EXPORT_SYMBOL(msm_vidc_streamoff);
574
575int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize)
576{
577 struct msm_vidc_inst *inst = instance;
578 struct msm_vidc_capability *capability = NULL;
579
580 if (!inst || !fsize) {
581 dprintk(VIDC_ERR, "%s: invalid parameter: %pK %pK\n",
582 __func__, inst, fsize);
583 return -EINVAL;
584 }
585 if (!inst->core)
586 return -EINVAL;
587
588 capability = &inst->capability;
589 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
590 fsize->stepwise.min_width = capability->width.min;
591 fsize->stepwise.max_width = capability->width.max;
592 fsize->stepwise.step_width = capability->width.step_size;
593 fsize->stepwise.min_height = capability->height.min;
594 fsize->stepwise.max_height = capability->height.max;
595 fsize->stepwise.step_height = capability->height.step_size;
596 return 0;
597}
598EXPORT_SYMBOL(msm_vidc_enum_framesizes);
599
600static void *vidc_get_userptr(struct device *dev, unsigned long vaddr,
601 unsigned long size, enum dma_data_direction dma_dir)
602{
603 return (void *)0xdeadbeef;
604}
605
606static void vidc_put_userptr(void *buf_priv)
607{
608}
609
610static const struct vb2_mem_ops msm_vidc_vb2_mem_ops = {
611 .get_userptr = vidc_get_userptr,
612 .put_userptr = vidc_put_userptr,
613};
614
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800615static void msm_vidc_cleanup_buffer(struct vb2_buffer *vb)
616{
617 int rc = 0;
618 struct buf_queue *q = NULL;
619 struct msm_vidc_inst *inst = NULL;
620
621 if (!vb) {
622 dprintk(VIDC_ERR, "%s : Invalid vb pointer %pK",
623 __func__, vb);
624 return;
625 }
626
627 inst = vb2_get_drv_priv(vb->vb2_queue);
628 if (!inst) {
629 dprintk(VIDC_ERR, "%s : Invalid inst pointer",
630 __func__);
631 return;
632 }
633
634 q = msm_comm_get_vb2q(inst, vb->type);
635 if (!q) {
636 dprintk(VIDC_ERR,
637 "%s : Failed to find buffer queue for type = %d\n",
638 __func__, vb->type);
639 return;
640 }
641
642 if (q->vb2_bufq.streaming) {
643 dprintk(VIDC_DBG, "%d PORT is streaming\n",
644 vb->type);
645 return;
646 }
647
Praneeth Paladuguceec6d82016-12-21 15:09:57 -0800648 rc = msm_vidc_release_buffer(inst, vb->type, vb->index);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800649 if (rc)
650 dprintk(VIDC_ERR, "%s : Failed to release buffers : %d\n",
651 __func__, rc);
652}
653
654static int set_buffer_count(struct msm_vidc_inst *inst,
655 int host_count, int act_count, enum hal_buffer type)
656{
657 int rc = 0;
658 struct hfi_device *hdev;
659 struct hal_buffer_count_actual buf_count;
660
661 hdev = inst->core->device;
662
663 buf_count.buffer_type = type;
664 buf_count.buffer_count_actual = act_count;
665 buf_count.buffer_count_min_host = host_count;
Praneeth Paladugu13c90962017-04-24 13:15:28 -0700666 dprintk(VIDC_DBG, "%s : Act count = %d Host count = %d\n",
667 __func__, act_count, host_count);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800668 rc = call_hfi_op(hdev, session_set_property,
669 inst->session, HAL_PARAM_BUFFER_COUNT_ACTUAL, &buf_count);
670 if (rc)
671 dprintk(VIDC_ERR,
672 "Failed to set actual buffer count %d for buffer type %d\n",
673 act_count, type);
674 return rc;
675}
676
677static int msm_vidc_queue_setup(struct vb2_queue *q,
678 unsigned int *num_buffers, unsigned int *num_planes,
679 unsigned int sizes[], struct device *alloc_devs[])
680{
681 struct msm_vidc_inst *inst;
682 int i, rc = 0;
683 struct hal_buffer_requirements *bufreq;
684 enum hal_buffer buffer_type;
685
686 if (!q || !num_buffers || !num_planes
687 || !sizes || !q->drv_priv) {
688 dprintk(VIDC_ERR, "Invalid input, q = %pK, %pK, %pK\n",
689 q, num_buffers, num_planes);
690 return -EINVAL;
691 }
692 inst = q->drv_priv;
693
694 if (!inst || !inst->core || !inst->core->device) {
695 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
696 return -EINVAL;
697 }
698
699 switch (q->type) {
700 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: {
701 bufreq = get_buff_req_buffer(inst,
702 HAL_BUFFER_INPUT);
703 if (!bufreq) {
704 dprintk(VIDC_ERR,
705 "Failed : No buffer requirements : %x\n",
706 HAL_BUFFER_INPUT);
707 return -EINVAL;
708 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700709 if (*num_buffers < bufreq->buffer_count_min_host) {
Maheshwar Ajja78e4cd32017-05-19 17:39:51 -0700710 dprintk(VIDC_DBG,
711 "Client passed num buffers %d less than the min_host count %d\n",
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700712 *num_buffers, bufreq->buffer_count_min_host);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800713 }
714 *num_planes = inst->bufq[OUTPUT_PORT].num_planes;
715 if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS ||
716 *num_buffers > MAX_NUM_OUTPUT_BUFFERS)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700717 bufreq->buffer_count_actual = *num_buffers =
718 MIN_NUM_OUTPUT_BUFFERS;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800719 for (i = 0; i < *num_planes; i++)
720 sizes[i] = inst->bufq[OUTPUT_PORT].plane_sizes[i];
721
722 bufreq->buffer_count_actual = *num_buffers;
Praneeth Paladuguf4b15822017-06-27 15:39:24 -0700723 rc = set_buffer_count(inst, bufreq->buffer_count_min_host,
Maheshwar Ajjaec382932017-06-30 13:47:01 -0700724 bufreq->buffer_count_actual, HAL_BUFFER_INPUT);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800725 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800726 break;
727 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: {
728 buffer_type = msm_comm_get_hal_output_buffer(inst);
729 bufreq = get_buff_req_buffer(inst,
730 buffer_type);
731 if (!bufreq) {
732 dprintk(VIDC_ERR,
733 "Failed : No buffer requirements : %x\n",
734 buffer_type);
735 return -EINVAL;
736 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700737 if (inst->session_type != MSM_VIDC_DECODER &&
738 inst->state > MSM_VIDC_LOAD_RESOURCES_DONE) {
739 if (*num_buffers < bufreq->buffer_count_min_host) {
Maheshwar Ajja78e4cd32017-05-19 17:39:51 -0700740 dprintk(VIDC_DBG,
741 "Client passed num buffers %d less than the min_host count %d\n",
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700742 *num_buffers,
743 bufreq->buffer_count_min_host);
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700744 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800745 }
746 *num_planes = inst->bufq[CAPTURE_PORT].num_planes;
747 if (*num_buffers < MIN_NUM_CAPTURE_BUFFERS ||
748 *num_buffers > MAX_NUM_CAPTURE_BUFFERS)
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700749 bufreq->buffer_count_actual = *num_buffers =
750 MIN_NUM_CAPTURE_BUFFERS;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800751
752 for (i = 0; i < *num_planes; i++)
753 sizes[i] = inst->bufq[CAPTURE_PORT].plane_sizes[i];
754
755 bufreq->buffer_count_actual = *num_buffers;
Praneeth Paladuguf4b15822017-06-27 15:39:24 -0700756 rc = set_buffer_count(inst, bufreq->buffer_count_min_host,
Maheshwar Ajjaec382932017-06-30 13:47:01 -0700757 bufreq->buffer_count_actual, buffer_type);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800758 }
759 break;
760 default:
761 dprintk(VIDC_ERR, "Invalid q type = %d\n", q->type);
762 rc = -EINVAL;
763 break;
764 }
765 return rc;
766}
767
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800768static inline int msm_vidc_verify_buffer_counts(struct msm_vidc_inst *inst)
769{
770 int rc = 0, i = 0;
771
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700772 /* For decoder No need to sanity till LOAD_RESOURCES */
773 if (inst->session_type == MSM_VIDC_DECODER &&
774 inst->state < MSM_VIDC_LOAD_RESOURCES_DONE) {
775 dprintk(VIDC_DBG,
776 "No need to verify buffer counts : %pK\n", inst);
777 return 0;
778 }
779
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800780 for (i = 0; i < HAL_BUFFER_MAX; i++) {
781 struct hal_buffer_requirements *req = &inst->buff_req.buffer[i];
782
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -0700783 if (req && (msm_comm_get_hal_output_buffer(inst) ==
784 req->buffer_type)) {
785 dprintk(VIDC_DBG, "Verifying Buffer : %d\n",
786 req->buffer_type);
787 if (req->buffer_count_actual <
788 req->buffer_count_min_host ||
789 req->buffer_count_min_host <
790 req->buffer_count_min) {
791
792 dprintk(VIDC_ERR,
793 "Invalid data : Counts mismatch\n");
794 dprintk(VIDC_ERR,
795 "Min Count = %d ",
796 req->buffer_count_min);
797 dprintk(VIDC_ERR,
798 "Min Host Count = %d ",
799 req->buffer_count_min_host);
800 dprintk(VIDC_ERR,
801 "Min Actual Count = %d\n",
802 req->buffer_count_actual);
803 rc = -EINVAL;
804 break;
805 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800806 }
807 }
808 return rc;
809}
810
811static inline int start_streaming(struct msm_vidc_inst *inst)
812{
813 int rc = 0;
814 struct hfi_device *hdev;
815 struct hal_buffer_size_minimum b;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800816
817 hdev = inst->core->device;
818
819 /* Check if current session is under HW capability */
820 rc = msm_vidc_check_session_supported(inst);
821 if (rc) {
822 dprintk(VIDC_ERR,
823 "This session is not supported %pK\n", inst);
824 goto fail_start;
825 }
826
Praneeth Paladugu238977b2016-12-06 12:51:26 -0800827 /* Decide work mode for current session */
828 rc = msm_vidc_decide_work_mode(inst);
829 if (rc) {
830 dprintk(VIDC_ERR,
831 "Failed to decide work mode for session %pK\n", inst);
832 goto fail_start;
833 }
834
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800835 /* Assign Core and LP mode for current session */
836 rc = msm_vidc_decide_core_and_power_mode(inst);
837 if (rc) {
838 dprintk(VIDC_ERR,
Praneeth Paladugu238977b2016-12-06 12:51:26 -0800839 "This session can't be submitted to HW %pK\n", inst);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800840 goto fail_start;
841 }
842
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800843 if (msm_comm_get_stream_output_mode(inst) ==
844 HAL_VIDEO_DECODER_SECONDARY) {
845 b.buffer_type = HAL_BUFFER_OUTPUT2;
846 } else {
847 b.buffer_type = HAL_BUFFER_OUTPUT;
848 }
849
Chinmay Sawarkar02f8f852017-06-26 12:05:38 -0700850 rc = msm_comm_try_get_bufreqs(inst);
851
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800852 b.buffer_size = inst->bufq[CAPTURE_PORT].plane_sizes[0];
853 rc = call_hfi_op(hdev, session_set_property,
854 inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
855 &b);
856
Praneeth Paladugu238977b2016-12-06 12:51:26 -0800857 /* Verify if buffer counts are correct */
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800858 rc = msm_vidc_verify_buffer_counts(inst);
859 if (rc) {
860 dprintk(VIDC_ERR,
861 "This session has mis-match buffer counts%pK\n", inst);
862 goto fail_start;
863 }
864
865 rc = msm_comm_set_scratch_buffers(inst);
866 if (rc) {
867 dprintk(VIDC_ERR,
868 "Failed to set scratch buffers: %d\n", rc);
869 goto fail_start;
870 }
871 rc = msm_comm_set_persist_buffers(inst);
872 if (rc) {
873 dprintk(VIDC_ERR,
874 "Failed to set persist buffers: %d\n", rc);
875 goto fail_start;
876 }
877
Praneeth Paladugu319e7922017-03-16 11:09:06 -0700878 rc = msm_comm_set_recon_buffers(inst);
879 if (rc) {
880 dprintk(VIDC_ERR,
881 "Failed to set recon buffers: %d\n", rc);
882 goto fail_start;
883 }
884
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800885 if (msm_comm_get_stream_output_mode(inst) ==
886 HAL_VIDEO_DECODER_SECONDARY) {
887 rc = msm_comm_set_output_buffers(inst);
888 if (rc) {
889 dprintk(VIDC_ERR,
890 "Failed to set output buffers: %d\n", rc);
891 goto fail_start;
892 }
893 }
894
895 /*
896 * For seq_changed_insufficient, driver should set session_continue
897 * to firmware after the following sequence
898 * - driver raises insufficient event to v4l2 client
899 * - all output buffers have been flushed and freed
900 * - v4l2 client queries buffer requirements and splits/combines OPB-DPB
901 * - v4l2 client sets new set of buffers to firmware
902 * - v4l2 client issues CONTINUE to firmware to resume decoding of
903 * submitted ETBs.
904 */
Umesh Pandeybb3fad02017-03-31 16:49:42 -0700905 rc = msm_comm_session_continue(inst);
906 if (rc)
907 goto fail_start;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800908
909 msm_comm_scale_clocks_and_bus(inst);
910
911 rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
912 if (rc) {
913 dprintk(VIDC_ERR,
914 "Failed to move inst: %pK to start done state\n", inst);
915 goto fail_start;
916 }
Praneeth Paladugue5fd0872017-04-19 11:24:28 -0700917
918 msm_clock_data_reset(inst);
919
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800920 if (msm_comm_get_stream_output_mode(inst) ==
921 HAL_VIDEO_DECODER_SECONDARY) {
922 rc = msm_comm_queue_output_buffers(inst);
923 if (rc) {
924 dprintk(VIDC_ERR,
925 "Failed to queue output buffers: %d\n", rc);
926 goto fail_start;
927 }
928 }
929
930fail_start:
Maheshwar Ajja99422322017-07-07 17:31:15 -0700931 if (rc) {
932 dprintk(VIDC_ERR, "%s: kill session %pK\n", __func__, inst);
933 msm_comm_kill_session(inst);
934 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800935 return rc;
936}
937
Praneeth Paladugudefea4e2017-02-09 23:44:08 -0800938static int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
939{
940 struct msm_vidc_inst *inst;
941 int rc = 0;
942 struct hfi_device *hdev;
943
944 if (!q || !q->drv_priv) {
945 dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q);
946 return -EINVAL;
947 }
948 inst = q->drv_priv;
949 if (!inst || !inst->core || !inst->core->device) {
950 dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
951 return -EINVAL;
952 }
953 hdev = inst->core->device;
954 dprintk(VIDC_DBG, "Streamon called on: %d capability for inst: %pK\n",
955 q->type, inst);
956 switch (q->type) {
957 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
958 if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
959 rc = start_streaming(inst);
960 break;
961 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
962 if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
963 rc = start_streaming(inst);
964 break;
965 default:
966 dprintk(VIDC_ERR, "Queue type is not supported: %d\n", q->type);
967 rc = -EINVAL;
968 goto stream_start_failed;
969 }
970 if (rc) {
971 dprintk(VIDC_ERR,
972 "Streamon failed on: %d capability for inst: %pK\n",
973 q->type, inst);
974 goto stream_start_failed;
975 }
976
977 rc = msm_comm_qbuf(inst, NULL);
978 if (rc) {
979 dprintk(VIDC_ERR,
980 "Failed to commit buffers queued before STREAM_ON to hardware: %d\n",
981 rc);
982 goto stream_start_failed;
983 }
984
985stream_start_failed:
Maheshwar Ajja884259c2017-06-28 11:22:54 -0700986 if (rc) {
987 struct msm_vidc_buffer *temp, *next;
988 struct vb2_buffer *vb;
989
990 mutex_lock(&inst->registeredbufs.lock);
991 list_for_each_entry_safe(temp, next, &inst->registeredbufs.list,
992 list) {
993 if (temp->vvb.vb2_buf.type != q->type)
994 continue;
995 /*
996 * queued_list lock is already acquired before
997 * vb2_stream so no need to acquire it again.
998 */
999 list_for_each_entry(vb, &q->queued_list, queued_entry) {
1000 if (msm_comm_compare_vb2_planes(inst, temp,
1001 vb)) {
1002 print_vb2_buffer(VIDC_ERR, "return vb",
1003 inst, vb);
1004 vb2_buffer_done(vb,
1005 VB2_BUF_STATE_QUEUED);
1006 break;
1007 }
1008 }
1009 msm_comm_unmap_vidc_buffer(inst, temp);
1010 list_del(&temp->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001011 kref_put_mbuf(temp);
Maheshwar Ajja884259c2017-06-28 11:22:54 -07001012 }
1013 mutex_unlock(&inst->registeredbufs.lock);
1014 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001015 return rc;
1016}
1017
1018static inline int stop_streaming(struct msm_vidc_inst *inst)
1019{
1020 int rc = 0;
1021
1022 rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
1023 if (rc)
1024 dprintk(VIDC_ERR,
1025 "Failed to move inst: %pK to state %d\n",
1026 inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07001027
1028 msm_clock_data_reset(inst);
1029
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001030 return rc;
1031}
1032
1033static void msm_vidc_stop_streaming(struct vb2_queue *q)
1034{
1035 struct msm_vidc_inst *inst;
1036 int rc = 0;
1037
1038 if (!q || !q->drv_priv) {
1039 dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q);
1040 return;
1041 }
1042
1043 inst = q->drv_priv;
1044 dprintk(VIDC_DBG, "Streamoff called on: %d capability\n", q->type);
1045 switch (q->type) {
1046 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1047 if (!inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
1048 rc = stop_streaming(inst);
1049 break;
1050 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1051 if (!inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
1052 rc = stop_streaming(inst);
1053 break;
1054 default:
1055 dprintk(VIDC_ERR,
1056 "Q-type is not supported: %d\n", q->type);
1057 rc = -EINVAL;
1058 break;
1059 }
1060
1061 msm_comm_scale_clocks_and_bus(inst);
1062
1063 if (rc)
1064 dprintk(VIDC_ERR,
1065 "Failed STOP Streaming inst = %pK on cap = %d\n",
1066 inst, q->type);
1067}
1068
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001069static void msm_vidc_buf_queue(struct vb2_buffer *vb2)
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001070{
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001071 int rc = 0;
1072 struct msm_vidc_inst *inst = NULL;
1073 struct msm_vidc_buffer *mbuf = NULL;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001074
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001075 inst = vb2_get_drv_priv(vb2->vb2_queue);
1076 if (!inst) {
1077 dprintk(VIDC_ERR, "%s: invalid inst\n", __func__);
1078 return;
1079 }
1080
1081 mbuf = msm_comm_get_vidc_buffer(inst, vb2);
1082 if (IS_ERR_OR_NULL(mbuf)) {
1083 if (PTR_ERR(mbuf) != -EEXIST)
1084 print_vb2_buffer(VIDC_ERR, "failed to get vidc-buf",
1085 inst, vb2);
1086 return;
1087 }
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001088 if (!kref_get_mbuf(inst, mbuf)) {
1089 dprintk(VIDC_ERR, "%s: mbuf not found\n", __func__);
1090 return;
1091 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001092
1093 rc = msm_comm_qbuf(inst, mbuf);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001094 if (rc)
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001095 print_vidc_buffer(VIDC_ERR, "failed qbuf", inst, mbuf);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001096
1097 kref_put_mbuf(mbuf);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001098}
1099
1100static const struct vb2_ops msm_vidc_vb2q_ops = {
1101 .queue_setup = msm_vidc_queue_setup,
1102 .start_streaming = msm_vidc_start_streaming,
1103 .buf_queue = msm_vidc_buf_queue,
1104 .buf_cleanup = msm_vidc_cleanup_buffer,
1105 .stop_streaming = msm_vidc_stop_streaming,
1106};
1107
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001108static inline int vb2_bufq_init(struct msm_vidc_inst *inst,
1109 enum v4l2_buf_type type, enum session_type sess)
1110{
1111 struct vb2_queue *q = NULL;
1112
1113 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1114 q = &inst->bufq[CAPTURE_PORT].vb2_bufq;
1115 } else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
1116 q = &inst->bufq[OUTPUT_PORT].vb2_bufq;
1117 } else {
1118 dprintk(VIDC_ERR, "buf_type = %d not recognised\n", type);
1119 return -EINVAL;
1120 }
1121
1122 q->type = type;
1123 q->io_modes = VB2_MMAP | VB2_USERPTR;
1124 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001125 q->ops = &msm_vidc_vb2q_ops;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001126
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001127 q->mem_ops = &msm_vidc_vb2_mem_ops;
1128 q->drv_priv = inst;
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07001129 q->allow_zero_bytesused = !V4L2_TYPE_IS_OUTPUT(type);
Vaibhav Deshu Venkatesh362d0922017-03-02 14:16:11 -08001130 q->copy_timestamp = 1;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001131 return vb2_queue_init(q);
1132}
1133
1134static int setup_event_queue(void *inst,
1135 struct video_device *pvdev)
1136{
1137 int rc = 0;
1138 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1139
1140 v4l2_fh_init(&vidc_inst->event_handler, pvdev);
1141 v4l2_fh_add(&vidc_inst->event_handler);
1142
1143 return rc;
1144}
1145
1146int msm_vidc_subscribe_event(void *inst,
1147 const struct v4l2_event_subscription *sub)
1148{
1149 int rc = 0;
1150 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1151
1152 if (!inst || !sub)
1153 return -EINVAL;
1154
1155 rc = v4l2_event_subscribe(&vidc_inst->event_handler,
1156 sub, MAX_EVENTS, NULL);
1157 return rc;
1158}
1159EXPORT_SYMBOL(msm_vidc_subscribe_event);
1160
1161int msm_vidc_unsubscribe_event(void *inst,
1162 const struct v4l2_event_subscription *sub)
1163{
1164 int rc = 0;
1165 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1166
1167 if (!inst || !sub)
1168 return -EINVAL;
1169
1170 rc = v4l2_event_unsubscribe(&vidc_inst->event_handler, sub);
1171 return rc;
1172}
1173EXPORT_SYMBOL(msm_vidc_unsubscribe_event);
1174
1175int msm_vidc_dqevent(void *inst, struct v4l2_event *event)
1176{
1177 int rc = 0;
1178 struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
1179
1180 if (!inst || !event)
1181 return -EINVAL;
1182
1183 rc = v4l2_event_dequeue(&vidc_inst->event_handler, event, false);
1184 return rc;
1185}
1186EXPORT_SYMBOL(msm_vidc_dqevent);
1187
1188static bool msm_vidc_check_for_inst_overload(struct msm_vidc_core *core)
1189{
1190 u32 instance_count = 0;
1191 u32 secure_instance_count = 0;
1192 struct msm_vidc_inst *inst = NULL;
1193 bool overload = false;
1194
1195 mutex_lock(&core->lock);
1196 list_for_each_entry(inst, &core->instances, list) {
1197 instance_count++;
1198 /* This flag is not updated yet for the current instance */
1199 if (inst->flags & VIDC_SECURE)
1200 secure_instance_count++;
1201 }
1202 mutex_unlock(&core->lock);
1203
1204 /* Instance count includes current instance as well. */
1205
1206 if ((instance_count > core->resources.max_inst_count) ||
1207 (secure_instance_count > core->resources.max_secure_inst_count))
1208 overload = true;
1209 return overload;
1210}
1211
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001212static int msm_vidc_try_set_ctrl(void *instance, struct v4l2_ctrl *ctrl)
1213{
1214 struct msm_vidc_inst *inst = instance;
1215
1216 if (inst->session_type == MSM_VIDC_DECODER)
1217 return msm_vdec_s_ctrl(instance, ctrl);
1218 else if (inst->session_type == MSM_VIDC_ENCODER)
1219 return msm_venc_s_ctrl(instance, ctrl);
1220 return -EINVAL;
1221}
1222
1223static int msm_vidc_op_s_ctrl(struct v4l2_ctrl *ctrl)
1224{
1225
1226 int rc = 0, c = 0;
1227 struct msm_vidc_inst *inst;
1228
1229 if (!ctrl) {
1230 dprintk(VIDC_ERR, "%s invalid parameters for ctrl\n", __func__);
1231 return -EINVAL;
1232 }
1233
1234 inst = container_of(ctrl->handler,
1235 struct msm_vidc_inst, ctrl_handler);
1236 if (!inst) {
1237 dprintk(VIDC_ERR, "%s invalid parameters for inst\n", __func__);
1238 return -EINVAL;
1239 }
1240
1241 for (c = 0; c < ctrl->ncontrols; ++c) {
1242 if (ctrl->cluster[c]->is_new) {
1243 rc = msm_vidc_try_set_ctrl(inst, ctrl->cluster[c]);
1244 if (rc) {
1245 dprintk(VIDC_ERR, "Failed setting %x\n",
1246 ctrl->cluster[c]->id);
1247 break;
1248 }
1249 }
1250 }
1251 if (rc)
1252 dprintk(VIDC_ERR, "Failed setting control: Inst = %pK (%s)\n",
1253 inst, v4l2_ctrl_get_name(ctrl->id));
1254 return rc;
1255}
1256
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001257static int msm_vidc_get_count(struct msm_vidc_inst *inst,
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001258 struct v4l2_ctrl *ctrl)
1259{
1260 int rc = 0;
Praneeth Paladugu6e637472017-05-16 16:06:46 -07001261 struct hal_buffer_requirements *bufreq;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001262 enum hal_buffer buffer_type;
1263
1264 if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_OUTPUT) {
1265 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT);
1266 if (!bufreq) {
1267 dprintk(VIDC_ERR,
1268 "Failed to find bufreqs for buffer type = %d\n",
1269 HAL_BUFFER_INPUT);
1270 return 0;
1271 }
1272 if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming) {
1273 ctrl->val = bufreq->buffer_count_min_host;
1274 return 0;
1275 }
1276 if (ctrl->val > bufreq->buffer_count_min_host) {
1277 dprintk(VIDC_DBG,
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001278 "Buffer count Host changed from %d to %d\n",
1279 bufreq->buffer_count_min_host,
1280 ctrl->val);
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001281 bufreq->buffer_count_actual =
1282 bufreq->buffer_count_min =
1283 bufreq->buffer_count_min_host =
1284 ctrl->val;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001285 } else {
1286 ctrl->val = bufreq->buffer_count_min_host;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001287 }
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001288 rc = set_buffer_count(inst,
1289 bufreq->buffer_count_min_host,
1290 bufreq->buffer_count_actual,
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001291 HAL_BUFFER_INPUT);
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001292
1293 msm_vidc_update_host_buff_counts(inst);
1294 ctrl->val = bufreq->buffer_count_min_host;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001295 return rc;
1296
1297 } else if (ctrl->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE) {
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001298
1299 buffer_type = msm_comm_get_hal_output_buffer(inst);
1300 bufreq = get_buff_req_buffer(inst,
1301 buffer_type);
1302 if (!bufreq) {
1303 dprintk(VIDC_ERR,
1304 "Failed to find bufreqs for buffer type = %d\n",
1305 buffer_type);
1306 return 0;
1307 }
1308 if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming) {
1309 if (ctrl->val != bufreq->buffer_count_min_host)
1310 return -EINVAL;
1311 else
1312 return 0;
1313 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001314
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001315 if (inst->session_type == MSM_VIDC_DECODER &&
1316 !inst->in_reconfig &&
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001317 inst->state < MSM_VIDC_LOAD_RESOURCES_DONE) {
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001318 dprintk(VIDC_DBG,
1319 "Clients updates Buffer count from %d to %d\n",
1320 bufreq->buffer_count_min_host, ctrl->val);
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001321 bufreq->buffer_count_actual =
1322 bufreq->buffer_count_min =
1323 bufreq->buffer_count_min_host =
1324 ctrl->val;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001325 }
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001326 if (ctrl->val > bufreq->buffer_count_min_host) {
1327 dprintk(VIDC_DBG,
1328 "Buffer count Host changed from %d to %d\n",
1329 bufreq->buffer_count_min_host,
1330 ctrl->val);
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001331 bufreq->buffer_count_actual =
1332 bufreq->buffer_count_min =
1333 bufreq->buffer_count_min_host =
1334 ctrl->val;
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001335 } else {
1336 ctrl->val = bufreq->buffer_count_min_host;
1337 }
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001338 rc = set_buffer_count(inst,
1339 bufreq->buffer_count_min_host,
1340 bufreq->buffer_count_actual,
Praneeth Paladugu1f9d1d92017-04-11 10:36:16 -07001341 HAL_BUFFER_OUTPUT);
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001342
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001343 msm_vidc_update_host_buff_counts(inst);
1344 ctrl->val = bufreq->buffer_count_min_host;
1345
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001346 return rc;
1347 }
1348 return -EINVAL;
1349}
1350
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001351static int try_get_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
1352{
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001353 int rc = 0;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001354 struct hal_buffer_requirements *bufreq = NULL;
1355 enum hal_buffer buffer_type;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001356
1357 switch (ctrl->id) {
1358
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001359 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001360 ctrl->val = msm_comm_hal_to_v4l2(
1361 V4L2_CID_MPEG_VIDEO_H264_PROFILE,
1362 inst->profile);
1363 break;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001364 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001365 ctrl->val = msm_comm_hal_to_v4l2(
1366 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE,
1367 inst->profile);
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001368 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001369
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001370 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001371 ctrl->val = msm_comm_hal_to_v4l2(
1372 V4L2_CID_MPEG_VIDEO_H264_LEVEL,
1373 inst->level);
1374 break;
Chinmay Sawarkar7f1cc152017-05-05 18:16:36 -07001375 case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001376 ctrl->val = msm_comm_hal_to_v4l2(
1377 V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL,
1378 inst->level);
1379 break;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001380 case V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL:
Vaibhav Deshu Venkateshce585582017-05-18 13:45:33 -07001381 ctrl->val = msm_comm_hal_to_v4l2(
1382 V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL,
1383 inst->level);
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001384 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001385
1386 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
1387 ctrl->val = inst->entropy_mode;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001388 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001389
1390 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
Praneeth Paladuguf4b15822017-06-27 15:39:24 -07001391 if (inst->in_reconfig)
1392 msm_vidc_update_host_buff_counts(inst);
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001393 buffer_type = msm_comm_get_hal_output_buffer(inst);
1394 bufreq = get_buff_req_buffer(inst,
1395 buffer_type);
1396 if (!bufreq) {
1397 dprintk(VIDC_ERR,
1398 "Failed to find bufreqs for buffer type = %d\n",
1399 buffer_type);
1400 return -EINVAL;
1401 }
1402 ctrl->val = bufreq->buffer_count_min_host;
1403 break;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001404 case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001405 bufreq = get_buff_req_buffer(inst, HAL_BUFFER_INPUT);
1406 if (!bufreq) {
1407 dprintk(VIDC_ERR,
1408 "Failed to find bufreqs for buffer type = %d\n",
1409 HAL_BUFFER_INPUT);
1410 return -EINVAL;
1411 }
1412 ctrl->val = bufreq->buffer_count_min_host;
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001413 break;
1414 default:
1415 /*
1416 * Other controls aren't really volatile, shouldn't need to
1417 * modify ctrl->value
1418 */
1419 break;
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001420 }
Praneeth Paladugudefea4e2017-02-09 23:44:08 -08001421
1422 return rc;
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001423}
1424
1425static int msm_vidc_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
1426{
1427 int rc = 0, c = 0;
1428 struct msm_vidc_inst *inst;
1429 struct v4l2_ctrl *master;
1430
1431 if (!ctrl) {
1432 dprintk(VIDC_ERR, "%s invalid parameters for ctrl\n", __func__);
1433 return -EINVAL;
1434 }
1435
1436 inst = container_of(ctrl->handler,
1437 struct msm_vidc_inst, ctrl_handler);
1438 if (!inst) {
1439 dprintk(VIDC_ERR, "%s invalid parameters for inst\n", __func__);
1440 return -EINVAL;
1441 }
1442 master = ctrl->cluster[0];
1443 if (!master) {
1444 dprintk(VIDC_ERR, "%s invalid parameters for master\n",
1445 __func__);
1446 return -EINVAL;
1447 }
1448
1449 for (c = 0; c < master->ncontrols; ++c) {
1450 if (master->cluster[c]->flags & V4L2_CTRL_FLAG_VOLATILE) {
1451 rc = try_get_ctrl(inst, master->cluster[c]);
1452 if (rc) {
1453 dprintk(VIDC_ERR, "Failed getting %x\n",
1454 master->cluster[c]->id);
1455 return rc;
1456 }
1457 }
1458 }
1459 if (rc)
1460 dprintk(VIDC_ERR, "Failed getting control: Inst = %pK (%s)\n",
1461 inst, v4l2_ctrl_get_name(ctrl->id));
1462 return rc;
1463}
1464
1465static const struct v4l2_ctrl_ops msm_vidc_ctrl_ops = {
1466
1467 .s_ctrl = msm_vidc_op_s_ctrl,
1468 .g_volatile_ctrl = msm_vidc_op_g_volatile_ctrl,
1469};
1470
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001471void *msm_vidc_open(int core_id, int session_type)
1472{
1473 struct msm_vidc_inst *inst = NULL;
1474 struct msm_vidc_core *core = NULL;
1475 int rc = 0;
1476 int i = 0;
1477
1478 if (core_id >= MSM_VIDC_CORES_MAX ||
1479 session_type >= MSM_VIDC_MAX_DEVICES) {
1480 dprintk(VIDC_ERR, "Invalid input, core_id = %d, session = %d\n",
1481 core_id, session_type);
1482 goto err_invalid_core;
1483 }
1484 core = get_vidc_core(core_id);
1485 if (!core) {
1486 dprintk(VIDC_ERR,
1487 "Failed to find core for core_id = %d\n", core_id);
1488 goto err_invalid_core;
1489 }
1490
1491 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1492 if (!inst) {
1493 dprintk(VIDC_ERR, "Failed to allocate memory\n");
1494 rc = -ENOMEM;
1495 goto err_invalid_core;
1496 }
1497
1498 pr_info(VIDC_DBG_TAG "Opening video instance: %pK, %d\n",
1499 VIDC_MSG_PRIO2STRING(VIDC_INFO), inst, session_type);
1500 mutex_init(&inst->sync_lock);
1501 mutex_init(&inst->bufq[CAPTURE_PORT].lock);
1502 mutex_init(&inst->bufq[OUTPUT_PORT].lock);
1503 mutex_init(&inst->lock);
1504
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001505 INIT_MSM_VIDC_LIST(&inst->scratchbufs);
Praneeth Paladugub71968b2015-08-19 20:47:57 -07001506 INIT_MSM_VIDC_LIST(&inst->freqs);
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07001507 INIT_MSM_VIDC_LIST(&inst->input_crs);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001508 INIT_MSM_VIDC_LIST(&inst->persistbufs);
1509 INIT_MSM_VIDC_LIST(&inst->pending_getpropq);
1510 INIT_MSM_VIDC_LIST(&inst->outputbufs);
1511 INIT_MSM_VIDC_LIST(&inst->registeredbufs);
Praneeth Paladugu319e7922017-03-16 11:09:06 -07001512 INIT_MSM_VIDC_LIST(&inst->reconbufs);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07001513 INIT_MSM_VIDC_LIST(&inst->eosbufs);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001514
1515 kref_init(&inst->kref);
1516
1517 inst->session_type = session_type;
1518 inst->state = MSM_VIDC_CORE_UNINIT_DONE;
1519 inst->core = core;
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07001520 inst->clk_data.min_freq = 0;
1521 inst->clk_data.curr_freq = 0;
1522 inst->clk_data.bitrate = 0;
1523 inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001524 inst->bit_depth = MSM_VIDC_BIT_DEPTH_8;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001525 inst->pic_struct = MSM_VIDC_PIC_STRUCT_PROGRESSIVE;
1526 inst->colour_space = MSM_VIDC_BT601_6_525;
Chinmay Sawarkarb3c6ccb2017-02-23 18:01:32 -08001527 inst->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
1528 inst->level = V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
1529 inst->entropy_mode = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001530
1531 for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
1532 i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) {
1533 init_completion(&inst->completions[i]);
1534 }
1535 inst->mem_client = msm_smem_new_client(SMEM_ION,
1536 &inst->core->resources, session_type);
1537 if (!inst->mem_client) {
1538 dprintk(VIDC_ERR, "Failed to create memory client\n");
1539 goto fail_mem_client;
1540 }
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001541
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001542 if (session_type == MSM_VIDC_DECODER) {
1543 msm_vdec_inst_init(inst);
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001544 rc = msm_vdec_ctrl_init(inst, &msm_vidc_ctrl_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001545 } else if (session_type == MSM_VIDC_ENCODER) {
1546 msm_venc_inst_init(inst);
Praneeth Paladugube42cb22016-04-12 22:34:39 -07001547 rc = msm_venc_ctrl_init(inst, &msm_vidc_ctrl_ops);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001548 }
1549
1550 if (rc)
1551 goto fail_bufq_capture;
1552
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001553 rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
1554 session_type);
1555 if (rc) {
1556 dprintk(VIDC_ERR,
1557 "Failed to initialize vb2 queue on capture port\n");
1558 goto fail_bufq_capture;
1559 }
1560 rc = vb2_bufq_init(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
1561 session_type);
1562 if (rc) {
1563 dprintk(VIDC_ERR,
1564 "Failed to initialize vb2 queue on capture port\n");
1565 goto fail_bufq_output;
1566 }
1567
1568 setup_event_queue(inst, &core->vdev[session_type].vdev);
1569
1570 mutex_lock(&core->lock);
1571 list_add_tail(&inst->list, &core->instances);
1572 mutex_unlock(&core->lock);
1573
1574 rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT_DONE);
1575 if (rc) {
1576 dprintk(VIDC_ERR,
1577 "Failed to move video instance to init state\n");
1578 goto fail_init;
1579 }
1580
Praneeth Paladugu13c90962017-04-24 13:15:28 -07001581 msm_dcvs_try_enable(inst);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001582 if (msm_vidc_check_for_inst_overload(core)) {
1583 dprintk(VIDC_ERR,
1584 "Instance count reached Max limit, rejecting session");
1585 goto fail_init;
1586 }
1587
Praneeth Paladugue5fd0872017-04-19 11:24:28 -07001588 msm_comm_scale_clocks_and_bus(inst);
1589
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001590 inst->debugfs_root =
1591 msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
1592
1593 return inst;
1594fail_init:
1595 mutex_lock(&core->lock);
1596 list_del(&inst->list);
1597 mutex_unlock(&core->lock);
1598
1599 v4l2_fh_del(&inst->event_handler);
1600 v4l2_fh_exit(&inst->event_handler);
1601 vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);
1602fail_bufq_output:
1603 vb2_queue_release(&inst->bufq[CAPTURE_PORT].vb2_bufq);
1604fail_bufq_capture:
1605 msm_comm_ctrl_deinit(inst);
1606 msm_smem_delete_client(inst->mem_client);
1607fail_mem_client:
1608 mutex_destroy(&inst->sync_lock);
1609 mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
1610 mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
1611 mutex_destroy(&inst->lock);
1612
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001613 DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
1614 DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
1615 DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
1616 DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
1617 DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07001618 DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07001619 DEINIT_MSM_VIDC_LIST(&inst->freqs);
1620 DEINIT_MSM_VIDC_LIST(&inst->input_crs);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001621
1622 kfree(inst);
1623 inst = NULL;
1624err_invalid_core:
1625 return inst;
1626}
1627EXPORT_SYMBOL(msm_vidc_open);
1628
Maheshwar Ajja99422322017-07-07 17:31:15 -07001629static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001630{
Maheshwar Ajja99422322017-07-07 17:31:15 -07001631 struct msm_vidc_buffer *temp, *dummy;
1632
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001633 if (!inst) {
1634 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
1635 return;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001636 }
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001637
Maheshwar Ajja99422322017-07-07 17:31:15 -07001638 mutex_lock(&inst->registeredbufs.lock);
1639 list_for_each_entry_safe(temp, dummy, &inst->registeredbufs.list,
1640 list) {
1641 print_vidc_buffer(VIDC_ERR, "undequeud buf", inst, temp);
1642 msm_comm_unmap_vidc_buffer(inst, temp);
1643 list_del(&temp->list);
Maheshwar Ajjacca04052017-07-12 17:59:45 -07001644 kref_put_mbuf(temp);
Maheshwar Ajja99422322017-07-07 17:31:15 -07001645 }
1646 mutex_unlock(&inst->registeredbufs.lock);
1647
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001648 msm_comm_free_freq_table(inst);
1649
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07001650 msm_comm_free_input_cr_table(inst);
1651
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001652 if (msm_comm_release_scratch_buffers(inst, false))
1653 dprintk(VIDC_ERR,
1654 "Failed to release scratch buffers\n");
1655
1656 if (msm_comm_release_recon_buffers(inst))
1657 dprintk(VIDC_ERR,
1658 "Failed to release recon buffers\n");
1659
1660 if (msm_comm_release_persist_buffers(inst))
1661 dprintk(VIDC_ERR,
1662 "Failed to release persist buffers\n");
1663
1664 /*
1665 * At this point all buffes should be with driver
1666 * irrespective of scenario
1667 */
1668 msm_comm_validate_output_buffers(inst);
1669
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07001670 msm_comm_release_eos_buffers(inst);
1671
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001672 if (msm_comm_release_output_buffers(inst, true))
1673 dprintk(VIDC_ERR,
1674 "Failed to release output buffers\n");
1675
1676 if (inst->extradata_handle)
1677 msm_comm_smem_free(inst, inst->extradata_handle);
1678
1679 debugfs_remove_recursive(inst->debugfs_root);
1680
1681 mutex_lock(&inst->pending_getpropq.lock);
1682 WARN_ON(!list_empty(&inst->pending_getpropq.list));
1683 mutex_unlock(&inst->pending_getpropq.lock);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001684}
1685
1686int msm_vidc_destroy(struct msm_vidc_inst *inst)
1687{
1688 struct msm_vidc_core *core;
1689 int i = 0;
1690
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001691 if (!inst || !inst->core) {
1692 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001693 return -EINVAL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001694 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001695
1696 core = inst->core;
1697
1698 mutex_lock(&core->lock);
1699 /* inst->list lives in core->instances */
1700 list_del(&inst->list);
1701 mutex_unlock(&core->lock);
1702
1703 msm_comm_ctrl_deinit(inst);
1704
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001705 v4l2_fh_del(&inst->event_handler);
1706 v4l2_fh_exit(&inst->event_handler);
1707
1708 for (i = 0; i < MAX_PORT_NUM; i++)
1709 vb2_queue_release(&inst->bufq[i].vb2_bufq);
1710
Maheshwar Ajja99422322017-07-07 17:31:15 -07001711 DEINIT_MSM_VIDC_LIST(&inst->scratchbufs);
1712 DEINIT_MSM_VIDC_LIST(&inst->persistbufs);
1713 DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq);
1714 DEINIT_MSM_VIDC_LIST(&inst->outputbufs);
1715 DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
Praneeth Paladuguf9ef8172017-07-18 22:55:59 -07001716 DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
Praneeth Paladugu7722b4e2017-07-07 11:01:56 -07001717 DEINIT_MSM_VIDC_LIST(&inst->freqs);
1718 DEINIT_MSM_VIDC_LIST(&inst->input_crs);
Maheshwar Ajja99422322017-07-07 17:31:15 -07001719
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001720 mutex_destroy(&inst->sync_lock);
1721 mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
1722 mutex_destroy(&inst->bufq[OUTPUT_PORT].lock);
1723 mutex_destroy(&inst->lock);
1724
1725 pr_info(VIDC_DBG_TAG "Closed video instance: %pK\n",
1726 VIDC_MSG_PRIO2STRING(VIDC_INFO), inst);
1727 kfree(inst);
1728 return 0;
1729}
1730
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001731static void close_helper(struct kref *kref)
1732{
1733 struct msm_vidc_inst *inst = container_of(kref,
1734 struct msm_vidc_inst, kref);
1735
1736 msm_vidc_destroy(inst);
1737}
1738
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001739int msm_vidc_close(void *instance)
1740{
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001741 struct msm_vidc_inst *inst = instance;
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001742 int rc = 0;
1743
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001744 if (!inst || !inst->core) {
1745 dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001746 return -EINVAL;
Maheshwar Ajjac6407c02017-06-09 18:53:20 -07001747 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001748
Praneeth Paladuguceec6d82016-12-21 15:09:57 -08001749 /*
1750 * Make sure that HW stop working on these buffers that
1751 * we are going to free.
1752 */
Maheshwar Ajja99422322017-07-07 17:31:15 -07001753 rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001754 if (rc)
1755 dprintk(VIDC_ERR,
Maheshwar Ajja99422322017-07-07 17:31:15 -07001756 "Failed to move inst %pK to rel resource done state\n",
1757 inst);
1758
1759 msm_vidc_cleanup_instance(inst);
1760
1761 rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
1762 if (rc) {
1763 dprintk(VIDC_ERR,
1764 "Failed to move inst %pK to uninit state\n", inst);
1765 rc = msm_comm_force_cleanup(inst);
1766 }
Praneeth Paladugu6e6fbdb2017-01-16 15:43:01 -08001767
1768 msm_comm_session_clean(inst);
1769 msm_smem_delete_client(inst->mem_client);
1770
1771 kref_put(&inst->kref, close_helper);
1772 return 0;
1773}
1774EXPORT_SYMBOL(msm_vidc_close);
1775
1776int msm_vidc_suspend(int core_id)
1777{
1778 return msm_comm_suspend(core_id);
1779}
1780EXPORT_SYMBOL(msm_vidc_suspend);
1781