blob: c87211a2b3fa7da821730bc43f544e98d39b71cd [file] [log] [blame]
Vinay Kalia3766b1e2012-01-11 18:58:41 -08001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/slab.h>
15
16#include "msm_vidc_internal.h"
17#include "msm_vidc_common.h"
18#include "vidc_hal_api.h"
19#include "msm_smem.h"
20
21#define MSM_VDEC_DVC_NAME "msm_vdec_8974"
22#define MAX_PLANES 1
23#define DEFAULT_HEIGHT 720
24#define DEFAULT_WIDTH 1280
Praneeth Paladuguc5041da2012-07-18 15:44:57 -070025#define MAX_SUPPORTED_WIDTH 4096
26#define MAX_SUPPORTED_HEIGHT 2160
Vinay Kalia3766b1e2012-01-11 18:58:41 -080027#define MIN_NUM_OUTPUT_BUFFERS 2
28#define MAX_NUM_OUTPUT_BUFFERS 6
29
30static const char *const mpeg_video_vidc_divx_format[] = {
Deva Ramasubramanianc249b752012-05-18 17:31:03 -070031 "DIVX Format 3",
Vinay Kalia3766b1e2012-01-11 18:58:41 -080032 "DIVX Format 4",
33 "DIVX Format 5",
34 "DIVX Format 6",
35 NULL
36};
37static const char *mpeg_video_stream_format[] = {
38 "NAL Format Start Codes",
39 "NAL Format One NAL Per Buffer",
40 "NAL Format One Byte Length",
41 "NAL Format Two Byte Length",
42 "NAL Format Four Byte Length",
43 NULL
44};
45static const char *const mpeg_video_output_order[] = {
46 "Display Order",
47 "Decode Order",
48 NULL
49};
50static const struct msm_vidc_ctrl msm_vdec_ctrls[] = {
51 {
52 .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT,
53 .name = "NAL Format",
54 .type = V4L2_CTRL_TYPE_MENU,
55 .minimum = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES,
56 .maximum = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH,
57 .default_value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES,
58 .menu_skip_mask = ~(
59 (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES) |
60 (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_NAL_PER_BUFFER) |
61 (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_BYTE_LENGTH) |
62 (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH) |
63 (1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH)
64 ),
65 .qmenu = mpeg_video_stream_format,
66 .step = 0,
67 },
68 {
69 .id = V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER,
70 .name = "Output Order",
71 .type = V4L2_CTRL_TYPE_MENU,
72 .minimum = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY,
73 .maximum = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE,
74 .default_value = V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY,
75 .menu_skip_mask = ~(
76 (1 << V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DISPLAY) |
77 (1 << V4L2_MPEG_VIDC_VIDEO_OUTPUT_ORDER_DECODE)
78 ),
79 .qmenu = mpeg_video_output_order,
80 .step = 0,
81 },
82 {
83 .id = V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_PICTURE_TYPE,
84 .name = "Picture Type Decoding",
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .minimum = 1,
87 .maximum = 15,
88 .default_value = 15,
89 .step = 1,
90 .menu_skip_mask = 0,
91 .qmenu = NULL,
92 },
93 {
94 .id = V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO,
95 .name = "Keep Aspect Ratio",
96 .type = V4L2_CTRL_TYPE_BOOLEAN,
97 .minimum = 0,
98 .maximum = 1,
99 .default_value = 0,
100 .step = 1,
101 .menu_skip_mask = 0,
102 .qmenu = NULL,
103 },
104 {
105 .id = V4L2_CID_MPEG_VIDC_VIDEO_POST_LOOP_DEBLOCKER_MODE,
106 .name = "Deblocker Mode",
107 .type = V4L2_CTRL_TYPE_BOOLEAN,
108 .minimum = 0,
109 .maximum = 1,
110 .default_value = 0,
111 .step = 1,
112 .menu_skip_mask = 0,
113 .qmenu = NULL,
114 },
115 {
116 .id = V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT,
117 .name = "Divx Format",
118 .type = V4L2_CTRL_TYPE_MENU,
119 .minimum = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4,
120 .maximum = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6,
121 .default_value = V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4,
122 .menu_skip_mask = ~(
123 (1 << V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_4) |
124 (1 << V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_5) |
125 (1 << V4L2_MPEG_VIDC_VIDEO_DIVX_FORMAT_6)
126 ),
127 .qmenu = mpeg_video_vidc_divx_format,
128 .step = 0,
129 },
130 {
131 .id = V4L2_CID_MPEG_VIDC_VIDEO_MB_ERROR_MAP_REPORTING,
132 .name = "MB Error Map Reporting",
133 .type = V4L2_CTRL_TYPE_BOOLEAN,
134 .minimum = 0,
135 .maximum = 1,
136 .default_value = 0,
137 .step = 1,
138 .menu_skip_mask = 0,
139 .qmenu = NULL,
140 },
141 {
142 .id = V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER,
143 .name = "control",
144 .type = V4L2_CTRL_TYPE_BOOLEAN,
145 .minimum = 0,
146 .maximum = 1,
147 .default_value = 0,
148 .step = 1,
149 .menu_skip_mask = 0,
150 .qmenu = NULL,
151 },
152};
153
154#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
155
156static u32 get_frame_size_nv12(int plane,
157 u32 height, u32 width)
158{
Deva Ramasubramanian2bf4fb12012-06-27 20:42:33 -0700159 int luma_stride = ALIGN(width, 32);
160 int luma_slice = ALIGN(height, 32);
161 int chroma_stride = ALIGN(roundup(width, 2)/2, 32);
162 int chroma_slice = ALIGN(roundup(height, 2)/2, 32);
163 return (luma_stride * luma_slice) + (chroma_stride * chroma_slice) * 2;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800164}
165static u32 get_frame_size_nv21(int plane,
166 u32 height, u32 width)
167{
168 return height * width * 2;
169}
170
171static u32 get_frame_size_compressed(int plane,
172 u32 height, u32 width)
173{
Praneeth Paladuguc5041da2012-07-18 15:44:57 -0700174 return (MAX_SUPPORTED_WIDTH * MAX_SUPPORTED_HEIGHT * 3/2)/2;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800175}
176
177static const struct msm_vidc_format vdec_formats[] = {
178 {
179 .name = "YCbCr Semiplanar 4:2:0",
180 .description = "Y/CbCr 4:2:0",
181 .fourcc = V4L2_PIX_FMT_NV12,
182 .num_planes = 1,
183 .get_frame_size = get_frame_size_nv12,
184 .type = CAPTURE_PORT,
185 },
186 {
187 .name = "Mpeg4",
188 .description = "Mpeg4 compressed format",
189 .fourcc = V4L2_PIX_FMT_MPEG4,
190 .num_planes = 1,
191 .get_frame_size = get_frame_size_compressed,
192 .type = OUTPUT_PORT,
193 },
194 {
195 .name = "Mpeg2",
196 .description = "Mpeg2 compressed format",
197 .fourcc = V4L2_PIX_FMT_MPEG2,
198 .num_planes = 1,
199 .get_frame_size = get_frame_size_compressed,
200 .type = OUTPUT_PORT,
201 },
202 {
203 .name = "H263",
204 .description = "H263 compressed format",
205 .fourcc = V4L2_PIX_FMT_H263,
206 .num_planes = 1,
207 .get_frame_size = get_frame_size_compressed,
208 .type = OUTPUT_PORT,
209 },
210 {
Praneeth Paladugue29238b2012-07-06 12:04:17 -0700211 .name = "VC1",
212 .description = "VC-1 compressed format",
213 .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
214 .num_planes = 1,
215 .get_frame_size = get_frame_size_compressed,
216 .type = OUTPUT_PORT,
217 },
218 {
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800219 .name = "H264",
220 .description = "H264 compressed format",
221 .fourcc = V4L2_PIX_FMT_H264,
222 .num_planes = 1,
223 .get_frame_size = get_frame_size_compressed,
224 .type = OUTPUT_PORT,
225 },
226 {
Praneeth Paladugu1e8ddae2012-07-06 12:13:06 -0700227 .name = "VP8",
228 .description = "VP8 compressed format",
229 .fourcc = V4L2_PIX_FMT_VP8,
230 .num_planes = 1,
231 .get_frame_size = get_frame_size_compressed,
232 .type = OUTPUT_PORT,
233 },
234 {
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800235 .name = "YCrCb Semiplanar 4:2:0",
236 .description = "Y/CrCb 4:2:0",
237 .fourcc = V4L2_PIX_FMT_NV21,
238 .num_planes = 1,
239 .get_frame_size = get_frame_size_nv21,
240 .type = CAPTURE_PORT,
241 },
Deva Ramasubramanianc249b752012-05-18 17:31:03 -0700242 {
243 .name = "DIVX 311",
244 .description = "DIVX 311 compressed format",
245 .fourcc = V4L2_PIX_FMT_DIVX_311,
246 .num_planes = 1,
247 .get_frame_size = get_frame_size_compressed,
248 .type = OUTPUT_PORT,
Deva Ramasubramaniana1980a12012-05-31 12:31:10 -0700249 },
250 {
251 .name = "DIVX",
252 .description = "DIVX 4/5/6 compressed format",
253 .fourcc = V4L2_PIX_FMT_DIVX,
254 .num_planes = 1,
255 .get_frame_size = get_frame_size_compressed,
256 .type = OUTPUT_PORT,
Deva Ramasubramanianc249b752012-05-18 17:31:03 -0700257 }
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800258};
259
260int msm_vdec_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
261{
262 int rc = 0;
263 struct vb2_queue *q;
264 q = msm_comm_get_vb2q(inst, i);
265 if (!q) {
266 pr_err("Failed to find buffer queue for type = %d\n", i);
267 return -EINVAL;
268 }
269 pr_debug("Calling streamon\n");
270 rc = vb2_streamon(q, i);
271 if (rc)
272 pr_err("streamon failed on port: %d\n", i);
273 return rc;
274}
275
276int msm_vdec_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i)
277{
278 int rc = 0;
279 struct vb2_queue *q;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800280
281 q = msm_comm_get_vb2q(inst, i);
282 if (!q) {
283 pr_err("Failed to find buffer queue for type = %d\n", i);
284 return -EINVAL;
285 }
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800286 pr_debug("Calling streamoff\n");
287 rc = vb2_streamoff(q, i);
288 if (rc)
289 pr_err("streamoff failed on port: %d\n", i);
290 return rc;
291}
292
293int msm_vdec_prepare_buf(struct msm_vidc_inst *inst,
294 struct v4l2_buffer *b)
295{
296 int rc = 0;
297 int i;
298 struct vidc_buffer_addr_info buffer_info;
299 switch (b->type) {
300 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
301 break;
Vinay Kaliae6a37af2012-05-16 16:47:54 -0700302 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800303 for (i = 0; i < b->length; i++) {
304 pr_err("device_addr = %ld, size = %d\n",
305 b->m.planes[i].m.userptr,
306 b->m.planes[i].length);
307 buffer_info.buffer_size = b->m.planes[i].length;
308 buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
309 buffer_info.num_buffers = 1;
310 buffer_info.align_device_addr =
311 b->m.planes[i].m.userptr;
Vinay Kalia68398a42012-06-22 18:36:12 -0700312 if (!inst->extradata_handle) {
313 inst->extradata_handle =
314 msm_smem_alloc(inst->mem_client,
315 4096 * 1024, 1, 0,
316 inst->core->resources.io_map[NS_MAP].domain,
317 0);
318 if (!inst->extradata_handle) {
319 pr_err("Failed to allocate extradta memory\n");
320 rc = -ENOMEM;
321 break;
322 }
323 }
324 buffer_info.extradata_addr =
325 inst->extradata_handle->device_addr;
326 buffer_info.extradata_size = 4096 * 1024;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800327 rc = vidc_hal_session_set_buffers((void *)inst->session,
328 &buffer_info);
329 if (rc) {
330 pr_err("vidc_hal_session_set_buffers failed");
331 break;
332 }
333 }
334 break;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800335 default:
336 pr_err("Buffer type not recognized: %d\n", b->type);
337 break;
338 }
339 return rc;
340}
341
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700342int msm_vdec_release_buf(struct msm_vidc_inst *inst,
343 struct v4l2_buffer *b)
344{
345 int rc = 0;
346 int i;
347 struct vidc_buffer_addr_info buffer_info;
348
349 switch (b->type) {
350 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
351 break;
Vinay Kaliae6a37af2012-05-16 16:47:54 -0700352 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700353 for (i = 0; i < b->length; i++) {
Vinay Kaliae6a37af2012-05-16 16:47:54 -0700354 pr_debug("Release device_addr = %ld, size = %d\n",
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700355 b->m.planes[i].m.userptr,
356 b->m.planes[i].length);
357 buffer_info.buffer_size = b->m.planes[i].length;
358 buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
359 buffer_info.num_buffers = 1;
360 buffer_info.align_device_addr =
361 b->m.planes[i].m.userptr;
Vinay Kalia68398a42012-06-22 18:36:12 -0700362 buffer_info.extradata_addr =
363 inst->extradata_handle->device_addr;
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700364 rc = vidc_hal_session_release_buffers(
365 (void *)inst->session, &buffer_info);
366 if (rc)
367 pr_err("vidc_hal_session_release_buffers failed");
368 }
369 break;
370 default:
371 pr_err("Buffer type not recognized: %d\n", b->type);
372 break;
373 }
374 return rc;
375}
376
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800377int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
378{
379 struct vb2_queue *q = NULL;
380 int rc = 0;
381 q = msm_comm_get_vb2q(inst, b->type);
382 if (!q) {
383 pr_err("Failed to find buffer queue for type = %d\n", b->type);
384 return -EINVAL;
385 }
386 rc = vb2_qbuf(q, b);
387 if (rc)
388 pr_err("Failed to qbuf, %d\n", rc);
389 return rc;
390}
391int msm_vdec_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
392{
393 struct vb2_queue *q = NULL;
394 int rc = 0;
395 q = msm_comm_get_vb2q(inst, b->type);
396 if (!q) {
397 pr_err("Failed to find buffer queue for type = %d\n", b->type);
398 return -EINVAL;
399 }
400 rc = vb2_dqbuf(q, b, true);
401 if (rc)
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700402 pr_err("Failed to dqbuf, %d\n", rc);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800403 return rc;
404}
405
406int msm_vdec_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b)
407{
408 struct vb2_queue *q = NULL;
409 int rc = 0;
410 if (!inst || !b) {
411 pr_err("Invalid input, inst = %p, buffer = %p\n", inst, b);
412 return -EINVAL;
413 }
414 q = msm_comm_get_vb2q(inst, b->type);
415 if (!q) {
416 pr_err("Failed to find buffer queue for type = %d\n", b->type);
417 return -EINVAL;
418 }
419
420 rc = vb2_reqbufs(q, b);
421 if (rc)
422 pr_err("Failed to get reqbufs, %d\n", rc);
423 return rc;
424}
425
426int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
427{
428 const struct msm_vidc_format *fmt = NULL;
429 int rc = 0;
430 int i;
431 if (!inst || !f) {
432 pr_err("Invalid input, inst = %p, format = %p\n", inst, f);
433 return -EINVAL;
434 }
435 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
436 fmt = inst->fmts[CAPTURE_PORT];
437 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
438 fmt = inst->fmts[OUTPUT_PORT];
439
440 if (fmt) {
441 f->fmt.pix_mp.pixelformat = fmt->fourcc;
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700442 if (inst->in_reconfig == true) {
Vinay Kalia12d8eef2012-08-03 17:45:53 -0700443 inst->prop.height = inst->reconfig_height;
444 inst->prop.width = inst->reconfig_width;
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700445 }
Vinay Kalia12d8eef2012-08-03 17:45:53 -0700446 f->fmt.pix_mp.height = inst->prop.height;
447 f->fmt.pix_mp.width = inst->prop.width;
Deva Ramasubramanianb17f8aa2012-07-30 17:16:32 -0700448 f->fmt.pix_mp.num_planes = fmt->num_planes;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800449 for (i = 0; i < fmt->num_planes; ++i) {
450 f->fmt.pix_mp.plane_fmt[i].sizeimage =
Vinay Kalia12d8eef2012-08-03 17:45:53 -0700451 fmt->get_frame_size(i, inst->prop.height,
452 inst->prop.width);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800453 }
454 } else {
455 pr_err("Buf type not recognized, type = %d\n",
456 f->type);
457 rc = -EINVAL;
458 }
459 return rc;
460}
461
462int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
463{
464 const struct msm_vidc_format *fmt = NULL;
465 int rc = 0;
466 int i;
467 if (!inst || !f) {
468 pr_err("Invalid input, inst = %p, format = %p\n", inst, f);
469 return -EINVAL;
470 }
471 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
Vinay Kalia94b221b2012-06-25 18:50:13 -0700472 inst->prop.width = f->fmt.pix_mp.width;
473 inst->prop.height = f->fmt.pix_mp.height;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800474 fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
475 ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
476 CAPTURE_PORT);
477 if (fmt && fmt->type != CAPTURE_PORT) {
478 pr_err("Format: %d not supported on CAPTURE port\n",
479 f->fmt.pix_mp.pixelformat);
480 rc = -EINVAL;
481 goto err_invalid_fmt;
482 }
483 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
484 fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
485 ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
486 OUTPUT_PORT);
487 if (fmt && fmt->type != OUTPUT_PORT) {
488 pr_err("Format: %d not supported on OUTPUT port\n",
489 f->fmt.pix_mp.pixelformat);
490 rc = -EINVAL;
491 goto err_invalid_fmt;
492 }
493 }
494
495 if (fmt) {
Deva Ramasubramanianb17f8aa2012-07-30 17:16:32 -0700496 f->fmt.pix_mp.num_planes = fmt->num_planes;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800497 for (i = 0; i < fmt->num_planes; ++i) {
498 f->fmt.pix_mp.plane_fmt[i].sizeimage =
499 fmt->get_frame_size(i, f->fmt.pix_mp.height,
500 f->fmt.pix_mp.width);
501 }
502 inst->fmts[fmt->type] = fmt;
503 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
504 rc = msm_comm_try_state(inst, MSM_VIDC_OPEN);
505 if (rc) {
506 pr_err("Failed to open instance\n");
507 goto err_invalid_fmt;
508 }
509 }
510 } else {
511 pr_err("Buf type not recognized, type = %d\n",
512 f->type);
513 rc = -EINVAL;
514 }
515err_invalid_fmt:
516 return rc;
517}
518
519int msm_vdec_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap)
520{
521 if (!inst || !cap) {
522 pr_err("Invalid input, inst = %p, cap = %p\n", inst, cap);
523 return -EINVAL;
524 }
525 strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
526 strlcpy(cap->card, MSM_VDEC_DVC_NAME, sizeof(cap->card));
527 cap->bus_info[0] = 0;
528 cap->version = MSM_VIDC_VERSION;
529 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
530 V4L2_CAP_VIDEO_OUTPUT_MPLANE |
531 V4L2_CAP_STREAMING;
532 memset(cap->reserved, 0, sizeof(cap->reserved));
533 return 0;
534}
535
536int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
537{
538 const struct msm_vidc_format *fmt = NULL;
539 int rc = 0;
540 if (!inst || !f) {
541 pr_err("Invalid input, inst = %p, f = %p\n", inst, f);
542 return -EINVAL;
543 }
544 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
545 fmt = msm_comm_get_pixel_fmt_index(vdec_formats,
546 ARRAY_SIZE(vdec_formats), f->index, CAPTURE_PORT);
547 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
548 fmt = msm_comm_get_pixel_fmt_index(vdec_formats,
549 ARRAY_SIZE(vdec_formats), f->index, OUTPUT_PORT);
550 f->flags = V4L2_FMT_FLAG_COMPRESSED;
551 }
552
553 memset(f->reserved, 0 , sizeof(f->reserved));
554 if (fmt) {
555 strlcpy(f->description, fmt->description,
556 sizeof(f->description));
557 f->pixelformat = fmt->fourcc;
558 } else {
559 pr_err("No more formats found\n");
560 rc = -EINVAL;
561 }
562 return rc;
563}
564
Steve Mucklef132c6c2012-06-06 18:30:57 -0700565static int msm_vdec_queue_setup(struct vb2_queue *q,
566 const struct v4l2_format *fmt,
567 unsigned int *num_buffers,
568 unsigned int *num_planes, unsigned int sizes[],
569 void *alloc_ctxs[])
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800570{
571 int i, rc = 0;
572 struct msm_vidc_inst *inst;
573 struct hal_frame_size frame_sz;
574 unsigned long flags;
575 if (!q || !q->drv_priv) {
576 pr_err("Invalid input, q = %p\n", q);
577 return -EINVAL;
578 }
579 inst = q->drv_priv;
580 switch (q->type) {
581 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
582 *num_planes = 1;
583 if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS ||
584 *num_buffers > MAX_NUM_OUTPUT_BUFFERS)
585 *num_buffers = MIN_NUM_OUTPUT_BUFFERS;
586 for (i = 0; i < *num_planes; i++) {
587 sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
Vinay Kalia12d8eef2012-08-03 17:45:53 -0700588 i, inst->prop.height, inst->prop.width);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800589 }
590 break;
591 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
592 pr_debug("Getting bufreqs on capture plane\n");
593 rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
594 if (rc) {
595 pr_err("Failed to open instance\n");
596 break;
597 }
598 frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
Vinay Kalia94b221b2012-06-25 18:50:13 -0700599 frame_sz.width = inst->prop.width;
600 frame_sz.height = inst->prop.height;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800601 pr_debug("width = %d, height = %d\n",
602 frame_sz.width, frame_sz.height);
603 rc = vidc_hal_session_set_property((void *)inst->session,
604 HAL_PARAM_FRAME_SIZE, &frame_sz);
605 if (rc) {
606 pr_err("Failed to set hal property for framesize\n");
607 break;
608 }
609 rc = msm_comm_try_get_bufreqs(inst);
610 if (rc) {
611 pr_err("Failed to get buffer requirements: %d\n", rc);
612 break;
613 }
614 *num_planes = 1;
615 spin_lock_irqsave(&inst->lock, flags);
616 *num_buffers = inst->buff_req.buffer[1].buffer_count_actual;
617 spin_unlock_irqrestore(&inst->lock, flags);
618 pr_debug("size = %d, alignment = %d\n",
619 inst->buff_req.buffer[1].buffer_size,
620 inst->buff_req.buffer[1].buffer_alignment);
621 for (i = 0; i < *num_planes; i++) {
622 sizes[i] = inst->fmts[CAPTURE_PORT]->get_frame_size(
Vinay Kalia94b221b2012-06-25 18:50:13 -0700623 i, inst->prop.height, inst->prop.width);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800624 }
625
626 break;
627 default:
628 pr_err("Invalid q type = %d\n", q->type);
629 rc = -EINVAL;
630 break;
631 }
632 return rc;
633}
634
635static inline int start_streaming(struct msm_vidc_inst *inst)
636{
637 int rc = 0;
638 unsigned long flags;
639 struct vb2_buf_entry *temp;
640 struct list_head *ptr, *next;
Praneeth Paladugu1b035542012-07-06 11:02:38 -0700641 rc = msm_comm_try_get_bufreqs(inst);
642 if (rc) {
643 pr_err("Failed to get buffer requirements : %d\n", rc);
644 goto fail_start;
645 }
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800646 rc = msm_comm_set_scratch_buffers(inst);
647 if (rc) {
648 pr_err("Failed to set scratch buffers: %d\n", rc);
649 goto fail_start;
650 }
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800651 rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
652 if (rc) {
653 pr_err("Failed to move inst: %p to start done state\n",
Praneeth Paladugu1b035542012-07-06 11:02:38 -0700654 inst);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800655 goto fail_start;
656 }
657 spin_lock_irqsave(&inst->lock, flags);
658 if (!list_empty(&inst->pendingq)) {
659 list_for_each_safe(ptr, next, &inst->pendingq) {
660 temp = list_entry(ptr, struct vb2_buf_entry, list);
661 rc = msm_comm_qbuf(temp->vb);
662 if (rc) {
663 pr_err("Failed to qbuf to hardware\n");
664 break;
665 }
666 list_del(&temp->list);
667 kfree(temp);
668 }
669 }
670 spin_unlock_irqrestore(&inst->lock, flags);
671 return rc;
672fail_start:
673 return rc;
674}
675
Steve Mucklef132c6c2012-06-06 18:30:57 -0700676static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800677{
678 struct msm_vidc_inst *inst;
679 int rc = 0;
680 if (!q || !q->drv_priv) {
681 pr_err("Invalid input, q = %p\n", q);
682 return -EINVAL;
683 }
684 inst = q->drv_priv;
685 pr_debug("Streamon called on: %d capability\n", q->type);
686 switch (q->type) {
687 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
Vinay Kalia94b221b2012-06-25 18:50:13 -0700688 if (msm_comm_scale_clocks(inst->core))
689 pr_err("Failed to scale clocks. Performance/power might be impacted\n");
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800690 if (inst->vb2_bufq[CAPTURE_PORT].streaming)
691 rc = start_streaming(inst);
692 break;
693 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
Vinay Kalia94b221b2012-06-25 18:50:13 -0700694 if (msm_comm_scale_clocks(inst->core))
695 pr_err("Failed to scale clocks. Performance/power might be impacted\n");
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800696 if (inst->vb2_bufq[OUTPUT_PORT].streaming)
697 rc = start_streaming(inst);
698 break;
699 default:
700 pr_err("Q-type is not supported: %d\n", q->type);
701 rc = -EINVAL;
702 break;
703 }
704 return rc;
705}
706
707static int msm_vdec_stop_streaming(struct vb2_queue *q)
708{
709 struct msm_vidc_inst *inst;
710 int rc = 0;
711 if (!q || !q->drv_priv) {
712 pr_err("Invalid input, q = %p\n", q);
713 return -EINVAL;
714 }
715 inst = q->drv_priv;
716 pr_debug("Streamoff called on: %d capability\n", q->type);
717 switch (q->type) {
718 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700719 if (!inst->vb2_bufq[CAPTURE_PORT].streaming)
720 rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800721 break;
722 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
Praneeth Paladuguf2acb852012-05-07 17:44:53 -0700723 if (!inst->vb2_bufq[OUTPUT_PORT].streaming)
724 rc = msm_comm_try_state(inst, MSM_VIDC_CLOSE_DONE);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800725 break;
726 default:
727 pr_err("Q-type is not supported: %d\n", q->type);
728 rc = -EINVAL;
729 break;
730 }
731 if (rc)
732 pr_err("Failed to move inst: %p, cap = %d to state: %d\n",
733 inst, q->type, MSM_VIDC_CLOSE_DONE);
734 return rc;
735}
736
737static void msm_vdec_buf_queue(struct vb2_buffer *vb)
738{
739 int rc;
740 rc = msm_comm_qbuf(vb);
741 if (rc)
742 pr_err("Failed to queue buffer: %d\n", rc);
743}
744
745static const struct vb2_ops msm_vdec_vb2q_ops = {
746 .queue_setup = msm_vdec_queue_setup,
747 .start_streaming = msm_vdec_start_streaming,
748 .buf_queue = msm_vdec_buf_queue,
749 .stop_streaming = msm_vdec_stop_streaming,
750};
751
752const struct vb2_ops *msm_vdec_get_vb2q_ops(void)
753{
754 return &msm_vdec_vb2q_ops;
755}
756
757int msm_vdec_inst_init(struct msm_vidc_inst *inst)
758{
759 int rc = 0;
760 if (!inst) {
761 pr_err("Invalid input = %p\n", inst);
762 return -EINVAL;
763 }
764 inst->fmts[OUTPUT_PORT] = &vdec_formats[1];
765 inst->fmts[CAPTURE_PORT] = &vdec_formats[0];
Vinay Kalia94b221b2012-06-25 18:50:13 -0700766 inst->prop.height = DEFAULT_HEIGHT;
767 inst->prop.width = DEFAULT_WIDTH;
768 inst->prop.fps = 30;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800769 return rc;
770}
771
772static int msm_vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)
773{
Praneeth Paladugu1b035542012-07-06 11:02:38 -0700774 int rc = 0;
775 struct v4l2_control control;
776 struct hal_nal_stream_format_supported stream_format;
777 struct hal_enable_picture enable_picture;
778 struct hal_enable hal_property;/*, prop;*/
779 u32 control_idx = 0;
780 enum hal_property property_id = 0;
781 u32 property_val = 0;
782 void *pdata;
783 struct msm_vidc_inst *inst = container_of(ctrl->handler,
784 struct msm_vidc_inst, ctrl_handler);
785 rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
786
787 if (rc) {
788 pr_err("Failed to move inst: %p to start done state\n",
789 inst);
790 goto failed_open_done;
791 }
792
793 control.id = ctrl->id;
794 control.value = ctrl->val;
795
796 switch (control.id) {
797 case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT:
798 property_id =
799 HAL_PARAM_NAL_STREAM_FORMAT_SELECT;
800 stream_format.nal_stream_format_supported =
801 (0x00000001 << control.value);
802 pdata = &stream_format;
803 break;
804 case V4L2_CID_MPEG_VIDC_VIDEO_OUTPUT_ORDER:
805 property_id = HAL_PARAM_VDEC_OUTPUT_ORDER;
806 property_val = control.value;
807 pdata = &property_val;
808 break;
809 case V4L2_CID_MPEG_VIDC_VIDEO_ENABLE_PICTURE_TYPE:
810 property_id =
811 HAL_PARAM_VDEC_PICTURE_TYPE_DECODE;
812 enable_picture.picture_type = control.value;
813 pdata = &enable_picture;
814 break;
815 case V4L2_CID_MPEG_VIDC_VIDEO_KEEP_ASPECT_RATIO:
816 property_id =
817 HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
818 hal_property.enable = control.value;
819 pdata = &hal_property;
820 break;
821 case V4L2_CID_MPEG_VIDC_VIDEO_POST_LOOP_DEBLOCKER_MODE:
822 property_id =
823 HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
824 hal_property.enable = control.value;
825 pdata = &hal_property;
826 break;
827 case V4L2_CID_MPEG_VIDC_VIDEO_DIVX_FORMAT:
828 property_id = HAL_PARAM_DIVX_FORMAT;
829 property_val = control.value;
830 pdata = &property_val;
831 break;
832 case V4L2_CID_MPEG_VIDC_VIDEO_MB_ERROR_MAP_REPORTING:
833 property_id =
834 HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
835 hal_property.enable = control.value;
836 pdata = &hal_property;
837 break;
838 case V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER:
839 property_id =
840 HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
841 hal_property.enable = control.value;
842 pdata = &hal_property;
843 break;
844 default:
845 break;
846 }
847 if (property_id) {
848 pr_debug("Control: HAL property=%d,ctrl_id=%d,ctrl_value=%d\n",
849 property_id,
850 msm_vdec_ctrls[control_idx].id,
851 control.value);
852 rc = vidc_hal_session_set_property((void *)
853 inst->session, property_id,
854 pdata);
855 }
856 if (rc)
857 pr_err("Failed to set hal property for framesize\n");
858
859failed_open_done:
860
861 return rc;
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800862}
863static int msm_vdec_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
864{
865 return 0;
866}
867
868static const struct v4l2_ctrl_ops msm_vdec_ctrl_ops = {
869
870 .s_ctrl = msm_vdec_op_s_ctrl,
871 .g_volatile_ctrl = msm_vdec_op_g_volatile_ctrl,
872};
873
874const struct v4l2_ctrl_ops *msm_vdec_get_ctrl_ops(void)
875{
876 return &msm_vdec_ctrl_ops;
877}
878
879int msm_vdec_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
880{
Steve Mucklef132c6c2012-06-06 18:30:57 -0700881 return v4l2_s_ctrl(NULL, &inst->ctrl_handler, ctrl);
Vinay Kalia3766b1e2012-01-11 18:58:41 -0800882}
883int msm_vdec_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
884{
885 return v4l2_g_ctrl(&inst->ctrl_handler, ctrl);
886}
887int msm_vdec_ctrl_init(struct msm_vidc_inst *inst)
888{
889 int idx = 0;
890 struct v4l2_ctrl_config ctrl_cfg;
891 int ret_val = 0;
892
893 ret_val = v4l2_ctrl_handler_init(&inst->ctrl_handler, NUM_CTRLS);
894
895 if (ret_val) {
896 pr_err("CTRL ERR: Control handler init failed, %d\n",
897 inst->ctrl_handler.error);
898 return ret_val;
899 }
900
901 for (; idx < NUM_CTRLS; idx++) {
902 if (IS_PRIV_CTRL(msm_vdec_ctrls[idx].id)) {
903 /*add private control*/
904 ctrl_cfg.def = msm_vdec_ctrls[idx].default_value;
905 ctrl_cfg.flags = 0;
906 ctrl_cfg.id = msm_vdec_ctrls[idx].id;
907 /*ctrl_cfg.is_private =
908 * msm_vdec_ctrls[idx].is_private;
909 * ctrl_cfg.is_volatile =
910 * msm_vdec_ctrls[idx].is_volatile;*/
911 ctrl_cfg.max = msm_vdec_ctrls[idx].maximum;
912 ctrl_cfg.min = msm_vdec_ctrls[idx].minimum;
913 ctrl_cfg.menu_skip_mask =
914 msm_vdec_ctrls[idx].menu_skip_mask;
915 ctrl_cfg.name = msm_vdec_ctrls[idx].name;
916 ctrl_cfg.ops = &msm_vdec_ctrl_ops;
917 ctrl_cfg.step = msm_vdec_ctrls[idx].step;
918 ctrl_cfg.type = msm_vdec_ctrls[idx].type;
919 ctrl_cfg.qmenu = msm_vdec_ctrls[idx].qmenu;
920
921 v4l2_ctrl_new_custom(&inst->ctrl_handler,
922 &ctrl_cfg, NULL);
923 } else {
924 if (msm_vdec_ctrls[idx].type == V4L2_CTRL_TYPE_MENU) {
925 v4l2_ctrl_new_std_menu(&inst->ctrl_handler,
926 &msm_vdec_ctrl_ops,
927 msm_vdec_ctrls[idx].id,
928 msm_vdec_ctrls[idx].maximum,
929 msm_vdec_ctrls[idx].menu_skip_mask,
930 msm_vdec_ctrls[idx].default_value);
931 } else {
932 v4l2_ctrl_new_std(&inst->ctrl_handler,
933 &msm_vdec_ctrl_ops,
934 msm_vdec_ctrls[idx].id,
935 msm_vdec_ctrls[idx].minimum,
936 msm_vdec_ctrls[idx].maximum,
937 msm_vdec_ctrls[idx].step,
938 msm_vdec_ctrls[idx].default_value);
939 }
940 }
941 }
942 ret_val = inst->ctrl_handler.error;
943 if (ret_val)
944 pr_err("CTRL ERR: Error adding ctrls to ctrl handle, %d\n",
945 inst->ctrl_handler.error);
946 return ret_val;
947}