blob: e1cabf93d355d50b36f0ce50a65118739f98165d [file] [log] [blame]
Vinay Kalia699edcf2011-12-01 17:43:47 -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 <media/v4l2-subdev.h>
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -080015#include <mach/iommu_domains.h>
Vinay Kalia699edcf2011-12-01 17:43:47 -080016#include "enc-subdev.h"
17#include "wfd-util.h"
18#include <media/msm/vcd_api.h>
19#include <media/msm/vidc_init.h>
20#include <media/msm/vcd_property.h>
21#include <linux/time.h>
22#include <linux/ktime.h>
23
24#define VID_ENC_MAX_ENCODER_CLIENTS 1
25#define MAX_NUM_CTRLS 20
26
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -070027static long venc_fill_outbuf(struct v4l2_subdev *sd, void *arg);
28
Vinay Kalia699edcf2011-12-01 17:43:47 -080029struct venc_inst {
30 struct video_client_ctx venc_client;
31 void *cbdata;
32 void (*op_buffer_done)(void *cookie, u32 status,
33 struct vb2_buffer *buf);
34 void (*ip_buffer_done)(void *cookie, u32 status,
35 struct mem_region *mregion);
36 u32 width;
37 u32 height;
Deepak kotur13d82f82012-03-12 11:12:32 -070038 int secure;
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -070039 struct mem_region unqueued_op_bufs;
40 bool streaming;
Vinay Kalia699edcf2011-12-01 17:43:47 -080041};
42
43struct venc {
44 s32 device_handle;
45 void *virt_base;
46 struct venc_inst venc_clients[VID_ENC_MAX_ENCODER_CLIENTS];
47 struct mutex lock;
48 struct ion_client *iclient;
49};
50
51static struct venc venc_p;
52
53static void *venc_map_dev_base_addr(void *device_name)
54{
55 return venc_p.virt_base;
56}
57
58static void venc_interrupt_deregister(void)
59{
60}
61
62static void venc_interrupt_register(void *device_name)
63{
64}
65
66static void venc_interrupt_clear(void)
67{
68}
69
70int venc_load_fw(struct v4l2_subdev *sd)
71{
72 return !vidc_load_firmware();
73}
74
75static u32 venc_get_empty_client_index(void)
76{
77 u32 i;
78 u32 found = false;
79
Deva Ramasubramaniana6bde8d2012-04-20 16:34:29 -070080 for (i = 0; i < VID_ENC_MAX_ENCODER_CLIENTS; i++) {
Vinay Kalia699edcf2011-12-01 17:43:47 -080081 if (!venc_p.venc_clients[i].venc_client.vcd_handle) {
82 found = true;
83 break;
84 }
85 }
86 if (!found) {
87 WFD_MSG_ERR("%s():ERROR No space for new client\n",
88 __func__);
89 return -ENOMEM;
90 }
91 WFD_MSG_INFO("%s(): available client index = %u\n",
92 __func__, i);
93 return i;
94}
95
96int venc_init(struct v4l2_subdev *sd, u32 val)
97{
98 struct vcd_init_config vcd_init_config;
99 mutex_init(&venc_p.lock);
100 venc_p.virt_base = vidc_get_ioaddr();
101 vcd_init_config.device_name = "VIDC";
102 vcd_init_config.map_dev_base_addr = venc_map_dev_base_addr;
103 vcd_init_config.interrupt_clr = venc_interrupt_clear;
104 vcd_init_config.register_isr = venc_interrupt_register;
105 vcd_init_config.deregister_isr = venc_interrupt_deregister;
106 vcd_init(&vcd_init_config, &venc_p.device_handle);
107 return 0;
108}
109
110static void venc_notify_client(struct video_client_ctx *client_ctx)
111{
112 if (client_ctx)
113 complete(&client_ctx->event);
114}
115
116static void venc_open_done(struct video_client_ctx *client_ctx,
117 struct vcd_handle_container *handle_container)
118{
119 if (client_ctx) {
120 if (handle_container)
121 client_ctx->vcd_handle = handle_container->handle;
122 else
123 WFD_MSG_ERR("handle_container is NULL\n");
124 venc_notify_client(client_ctx);
125 } else
126 WFD_MSG_ERR("ERROR. client_ctx is NULL");
127}
128
129static void venc_start_done(struct video_client_ctx *client_ctx, u32 status)
130{
131 if (client_ctx)
132 venc_notify_client(client_ctx);
133 else
134 WFD_MSG_ERR("ERROR. client_ctx is NULL");
135}
136
137static void venc_stop_done(struct video_client_ctx *client_ctx, u32 status)
138{
139 WFD_MSG_DBG("Inside venc_stop_done: E\n");
140 if (client_ctx)
141 venc_notify_client(client_ctx);
142 else
143 WFD_MSG_ERR("ERROR. client_ctx is NULL");
144 WFD_MSG_DBG("Inside venc_stop_done: X\n");
145}
146
147static void venc_cb(u32 event, u32 status, void *info, u32 size, void *handle,
148 void *const client_data)
149{
150 struct venc_inst *inst = client_data;
151 struct video_client_ctx *client_ctx = &inst->venc_client;
152 struct vb2_buffer *vbuf;
153 struct mem_region *mregion;
154 struct vcd_frame_data *frame_data = (struct vcd_frame_data *)info;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800155
156 if (!client_ctx) {
157 WFD_MSG_ERR("Client context is NULL\n");
158 return;
159 }
160 client_ctx->event_status = status;
161 switch (event) {
162 case VCD_EVT_RESP_OPEN:
163 WFD_MSG_DBG("EVENT: open done = %d\n", event);
164 venc_open_done(client_ctx,
165 (struct vcd_handle_container *)info);
166 break;
167 case VCD_EVT_RESP_INPUT_DONE:
168 case VCD_EVT_RESP_INPUT_FLUSHED:
169 WFD_MSG_DBG("EVENT: input done = %d\n", event);
170 mregion = (struct mem_region *)
171 frame_data->frm_clnt_data;
172 inst->ip_buffer_done(inst->cbdata, status, mregion);
173 break;
174 case VCD_EVT_RESP_OUTPUT_DONE:
175 case VCD_EVT_RESP_OUTPUT_FLUSHED:
176 WFD_MSG_DBG("EVENT: output done = %d\n", event);
177 vbuf = (struct vb2_buffer *)
178 frame_data->frm_clnt_data;
179 vbuf->v4l2_planes[0].bytesused =
180 frame_data->data_len;
181
182 switch (frame_data->frame) {
183 case VCD_FRAME_I:
184 case VCD_FRAME_IDR:
185 vbuf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
186 break;
187 case VCD_FRAME_P:
188 vbuf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
189 break;
190 case VCD_FRAME_B:
191 vbuf->v4l2_buf.flags |= V4L2_BUF_FLAG_BFRAME;
192 break;
193 default:
194 break;
195 }
196
Deva Ramasubramanianb84fc502012-01-16 11:42:58 -0800197 vbuf->v4l2_buf.timestamp =
Deva Ramasubramanian4947d8c2012-04-03 12:41:06 -0700198 ns_to_timeval(frame_data->time_stamp * NSEC_PER_USEC);
Vinay Kalia699edcf2011-12-01 17:43:47 -0800199
200 WFD_MSG_DBG("bytes used %d, ts: %d.%d, frame type is %d\n",
201 frame_data->data_len,
202 (int)vbuf->v4l2_buf.timestamp.tv_sec,
203 (int)vbuf->v4l2_buf.timestamp.tv_usec,
204 frame_data->frame);
205
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -0800206 /*
207 * Output buffers are enc-subdev and vcd's problem, so
208 * if buffer is cached, need to flush before giving to
209 * client. So doing the dirty stuff in this little context
210 */
211 {
212 unsigned long kvaddr, phys_addr;
213 s32 buffer_index = -1, ion_flags = 0;
214 struct ion_handle *ion_handle;
215 int pmem_fd;
216 struct file *filp;
217 bool rc;
218
219 rc = vidc_lookup_addr_table(client_ctx,
220 BUFFER_TYPE_OUTPUT, true,
221 (unsigned long *)&frame_data->
222 frm_clnt_data, &kvaddr, &phys_addr,
223 &pmem_fd, &filp, &buffer_index);
224
225 if (rc)
226 ion_flags = vidc_get_fd_info(client_ctx,
227 BUFFER_TYPE_OUTPUT, pmem_fd,
228 kvaddr, buffer_index, &ion_handle);
229 else
230 WFD_MSG_ERR("Got an output buffer that we "
231 "couldn't recognize!\n");
232
233 if (msm_ion_do_cache_op(client_ctx->user_ion_client,
234 ion_handle, &kvaddr, frame_data->data_len,
235 ION_IOC_CLEAN_INV_CACHES))
236 WFD_MSG_ERR("OP buffer flush failed\n");
237
238 }
239
Vinay Kalia699edcf2011-12-01 17:43:47 -0800240 inst->op_buffer_done(inst->cbdata, status, vbuf);
241 break;
242 case VCD_EVT_RESP_START:
243 WFD_MSG_DBG("EVENT: start done = %d\n", event);
244 venc_start_done(client_ctx, status);
245 /*TODO: should wait for this event*/
246 break;
247 case VCD_EVT_RESP_STOP:
248 WFD_MSG_DBG("EVENT: not expected = %d\n", event);
249 venc_stop_done(client_ctx, status);
250 break;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800251 case VCD_EVT_RESP_FLUSH_INPUT_DONE:
252 case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
Vinay Kaliab6dd5872012-04-05 15:24:58 -0700253 venc_notify_client(client_ctx);
254 break;
255 case VCD_EVT_RESP_PAUSE:
Vinay Kalia699edcf2011-12-01 17:43:47 -0800256 case VCD_EVT_IND_OUTPUT_RECONFIG:
257 WFD_MSG_DBG("EVENT: not expected = %d\n", event);
258 break;
259 case VCD_EVT_IND_HWERRFATAL:
260 case VCD_EVT_IND_RESOURCES_LOST:
261 WFD_MSG_DBG("EVENT: error = %d\n", event);
262 break;
263 default:
264 WFD_MSG_ERR("Invalid event type = %u\n", event);
265 break;
266 }
267}
268
269static long venc_open(struct v4l2_subdev *sd, void *arg)
270{
271 u32 client_index;
272 int rc = 0;
273 struct venc_inst *inst;
274 struct video_client_ctx *client_ctx;
275 struct venc_msg_ops *vmops = arg;
Deepak kotur13d82f82012-03-12 11:12:32 -0700276 int flags = 0;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800277 mutex_lock(&venc_p.lock);
278 client_index = venc_get_empty_client_index();
279 if (client_index < 0) {
280 WFD_MSG_ERR("No free clients, client_index = %d\n",
281 client_index);
282 rc = -ENODEV;
283 goto no_free_client;
284 }
285 inst = &venc_p.venc_clients[client_index];
286 client_ctx = &inst->venc_client;
287 init_completion(&client_ctx->event);
288 mutex_init(&client_ctx->msg_queue_lock);
289 mutex_init(&client_ctx->enrty_queue_lock);
290 INIT_LIST_HEAD(&client_ctx->msg_queue);
291 init_waitqueue_head(&client_ctx->msg_wait);
292 inst->op_buffer_done = vmops->op_buffer_done;
293 inst->ip_buffer_done = vmops->ip_buffer_done;
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700294 INIT_LIST_HEAD(&inst->unqueued_op_bufs.list);
Vinay Kalia699edcf2011-12-01 17:43:47 -0800295 inst->cbdata = vmops->cbdata;
Deepak kotur13d82f82012-03-12 11:12:32 -0700296 inst->secure = vmops->secure;
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700297 inst->streaming = false;
Deepak kotur13d82f82012-03-12 11:12:32 -0700298 if (vmops->secure) {
299 WFD_MSG_ERR("OPENING SECURE SESSION\n");
300 flags |= VCD_CP_SESSION;
301 }
Vinay Kalia699edcf2011-12-01 17:43:47 -0800302 if (vcd_get_ion_status()) {
303 client_ctx->user_ion_client = vcd_get_ion_client();
304 if (!client_ctx->user_ion_client) {
305 WFD_MSG_ERR("vcd_open ion get client failed");
306 return -EFAULT;
307 }
308 }
309
310 rc = vcd_open(venc_p.device_handle, false, venc_cb,
Deepak kotur13d82f82012-03-12 11:12:32 -0700311 inst, flags);
Vinay Kalia699edcf2011-12-01 17:43:47 -0800312 if (rc) {
313 WFD_MSG_ERR("vcd_open failed, rc = %d\n", rc);
Deepak kotur13d82f82012-03-12 11:12:32 -0700314 rc = -ENODEV;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800315 goto no_free_client;
316 }
317 wait_for_completion(&client_ctx->event);
318 if (client_ctx->event_status) {
319 WFD_MSG_ERR("callback for vcd_open returned error: %u",
320 client_ctx->event_status);
321 goto no_free_client;
322 }
323 WFD_MSG_ERR("NOTE: client_ctx = %p\n", client_ctx);
324 vmops->cookie = inst;
325 sd->dev_priv = inst;
326no_free_client:
327 mutex_unlock(&venc_p.lock);
328 return rc;
329}
330
331static long venc_close(struct v4l2_subdev *sd, void *arg)
332{
333 long rc = 0;
334 struct venc_inst *inst;
335 struct video_client_ctx *client_ctx = NULL;
336 mutex_lock(&venc_p.lock);
337 inst = sd->dev_priv;
338 client_ctx = &inst->venc_client;
339 if (!client_ctx || !client_ctx->vcd_handle) {
340 WFD_MSG_ERR("Invalid client context in close\n");
341 rc = -ENODEV;
342 goto end;
343 }
344 rc = vcd_close(client_ctx->vcd_handle);
345 if (rc) {
346 WFD_MSG_ERR("Failed to close encoder subdevice\n");
347 goto end;
348 }
349 memset((void *)client_ctx, 0,
350 sizeof(struct video_client_ctx));
351end:
352 mutex_unlock(&venc_p.lock);
353 return rc;
354}
355
356static long venc_get_buffer_req(struct v4l2_subdev *sd, void *arg)
357{
358 int rc = 0;
359 struct v4l2_requestbuffers *b = arg;
360 struct vcd_buffer_requirement buf_req;
361 struct venc_inst *inst = sd->dev_priv;
362 struct video_client_ctx *client_ctx = &inst->venc_client;
363 if (!client_ctx) {
364 WFD_MSG_ERR("Invalid client context");
365 rc = -EINVAL;
366 goto err;
367 }
368 rc = vcd_get_buffer_requirements(client_ctx->vcd_handle,
369 VCD_BUFFER_OUTPUT, &buf_req);
370 if (rc) {
371 WFD_MSG_ERR("Failed to get out buf reqs rc = %d", rc);
372 goto err;
373 }
Deva Ramasubramanian66d2cbe42012-03-16 12:28:55 -0700374
375 buf_req.actual_count = b->count = max(buf_req.min_count, b->count);
376 rc = vcd_set_buffer_requirements(client_ctx->vcd_handle,
377 VCD_BUFFER_OUTPUT, &buf_req);
378 if (rc) {
379 WFD_MSG_ERR("Failed to set out buf reqs rc = %d", rc);
380 goto err;
381 }
382
Vinay Kalia699edcf2011-12-01 17:43:47 -0800383err:
384 return rc;
385}
386
387static long venc_set_buffer_req(struct v4l2_subdev *sd, void *arg)
388{
389 int rc = 0;
390 struct bufreq *b = arg;
391 struct vcd_buffer_requirement buf_req;
392 struct venc_inst *inst = sd->dev_priv;
393 struct video_client_ctx *client_ctx = &inst->venc_client;
Deva Ramasubramaniana6e49232012-03-01 18:06:48 -0800394 int aligned_width, aligned_height;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800395 if (!client_ctx) {
396 WFD_MSG_ERR("Invalid client context");
397 rc = -EINVAL;
398 goto err;
399 }
Deva Ramasubramaniana6e49232012-03-01 18:06:48 -0800400 aligned_width = ALIGN(b->width, 16);
401 aligned_height = ALIGN(b->height, 16);
402
403 if (aligned_width != b->width) {
404 WFD_MSG_ERR("Width not 16 byte aligned\n");
405 rc = -EINVAL;
406 goto err;
407 }
408
Vinay Kalia699edcf2011-12-01 17:43:47 -0800409 buf_req.actual_count = b->count;
410 buf_req.min_count = b->count;
411 buf_req.max_count = b->count;
Deva Ramasubramaniana6e49232012-03-01 18:06:48 -0800412 buf_req.sz = ALIGN(aligned_height * aligned_width, SZ_2K)
413 + ALIGN(aligned_height * aligned_width * 1/2, SZ_2K);
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -0800414 buf_req.align = SZ_4K;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800415 inst->width = b->width;
416 inst->height = b->height;
417 rc = vcd_set_buffer_requirements(client_ctx->vcd_handle,
418 VCD_BUFFER_INPUT, &buf_req);
419 if (rc) {
420 WFD_MSG_ERR("Failed to get out buf reqs rc = %d", rc);
421 goto err;
422 }
423 b->size = buf_req.sz;
424err:
425 return rc;
426}
427
428static long venc_start(struct v4l2_subdev *sd)
429{
430 struct venc_inst *inst = sd->dev_priv;
431 struct video_client_ctx *client_ctx = &inst->venc_client;
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700432 struct mem_region *curr = NULL, *temp = NULL;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800433 int rc;
434 if (!client_ctx) {
435 WFD_MSG_ERR("Client context is NULL");
436 return -EINVAL;
437 }
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700438
Vinay Kalia699edcf2011-12-01 17:43:47 -0800439 rc = vcd_encode_start(client_ctx->vcd_handle);
440 if (rc) {
441 WFD_MSG_ERR("vcd_encode_start failed, rc = %d\n", rc);
442 goto err;
443 }
444 wait_for_completion(&client_ctx->event);
445 if (client_ctx->event_status)
446 WFD_MSG_ERR("callback for vcd_encode_start returned error: %u",
447 client_ctx->event_status);
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700448
449 inst->streaming = true;
450 /* Push any buffers that we have held back */
451 list_for_each_entry_safe(curr, temp,
452 &inst->unqueued_op_bufs.list, list) {
453 venc_fill_outbuf(sd, curr);
454 list_del(&curr->list);
455 kfree(curr);
456 }
Vinay Kalia699edcf2011-12-01 17:43:47 -0800457err:
458 return rc;
459}
460
461static long venc_stop(struct v4l2_subdev *sd)
462{
463 struct venc_inst *inst = sd->dev_priv;
464 struct video_client_ctx *client_ctx = &inst->venc_client;
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700465 struct mem_region *curr = NULL, *temp = NULL;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800466 int rc;
467 if (!client_ctx) {
468 WFD_MSG_ERR("Client context is NULL");
469 return -EINVAL;
470 }
471 rc = vcd_stop(client_ctx->vcd_handle);
472 wait_for_completion(&client_ctx->event);
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -0700473 inst->streaming = false;
474 /* Drop whatever frames we haven't queued */
475 list_for_each_entry_safe(curr, temp,
476 &inst->unqueued_op_bufs.list, list) {
477 inst->op_buffer_done(inst->cbdata, 0,
478 (struct vb2_buffer *)curr->cookie);
479 list_del(&curr->list);
480 kfree(curr);
481 }
Vinay Kalia699edcf2011-12-01 17:43:47 -0800482 return rc;
483}
484
485static long venc_set_codec(struct video_client_ctx *client_ctx, __s32 codec)
486{
487 struct vcd_property_codec vcd_property_codec;
488 struct vcd_property_hdr vcd_property_hdr;
489 vcd_property_hdr.prop_id = VCD_I_CODEC;
490 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
491 vcd_property_codec.codec = VCD_CODEC_H264;
Deva Ramasubramanianc34de062012-01-25 14:42:58 -0800492
Vinay Kalia699edcf2011-12-01 17:43:47 -0800493 switch (codec) {
Deva Ramasubramanianc34de062012-01-25 14:42:58 -0800494 case V4L2_PIX_FMT_H264:
Vinay Kalia699edcf2011-12-01 17:43:47 -0800495 vcd_property_codec.codec = VCD_CODEC_H264;
496 break;
Deva Ramasubramanianc34de062012-01-25 14:42:58 -0800497 case V4L2_PIX_FMT_MPEG4:
Vinay Kalia699edcf2011-12-01 17:43:47 -0800498 vcd_property_codec.codec = VCD_CODEC_MPEG4;
499 break;
500 default:
501 WFD_MSG_ERR("Codec not supported, defaulting to h264\n");
502 break;
503 }
504 return vcd_set_property(client_ctx->vcd_handle,
505 &vcd_property_hdr, &vcd_property_codec);
506}
507
Vinay Kalia699edcf2011-12-01 17:43:47 -0800508static long venc_set_codec_level(struct video_client_ctx *client_ctx,
509 __s32 codec, __s32 level)
510{
511 struct vcd_property_level vcd_property_level;
512 struct vcd_property_hdr vcd_property_hdr;
513 struct vcd_property_codec vcd_property_codec;
514
515 int rc = 0;
516 int mpeg4_base = VCD_LEVEL_MPEG4_0;
517 int h264_base = VCD_LEVEL_H264_1;
518
519 /* Validate params */
520 vcd_property_hdr.prop_id = VCD_I_CODEC;
521 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
522 rc = vcd_get_property(client_ctx->vcd_handle,
523 &vcd_property_hdr, &vcd_property_codec);
524
525 if (rc < 0) {
526 WFD_MSG_ERR("Error getting codec property");
527 rc = -EINVAL;
528 goto err;
529 }
530
531 if (!((vcd_property_codec.codec == VCD_CODEC_H264
532 && codec == V4L2_CID_MPEG_VIDEO_H264_LEVEL) ||
533 (vcd_property_codec.codec == VCD_CODEC_MPEG4
534 && codec == V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL))) {
535 WFD_MSG_ERR("Attempting to set %d for codec type %d",
536 codec, vcd_property_codec.codec);
537 rc = -EINVAL;
538 goto err;
539 }
540
541 /* Set property */
542 vcd_property_hdr.prop_id = VCD_I_LEVEL;
543 vcd_property_hdr.sz = sizeof(struct vcd_property_level);
544
545 if (codec == V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL) {
546 vcd_property_level.level = mpeg4_base + level;
547
548 if (vcd_property_level.level < VCD_LEVEL_MPEG4_0
549 || vcd_property_level.level > VCD_LEVEL_MPEG4_X) {
550 WFD_MSG_ERR("Level (%d) out of range"
551 "for codec (%d)\n", level, codec);
552
553 rc = -EINVAL;
554 goto err;
555 }
556 } else if (codec == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
557 vcd_property_level.level = h264_base + level;
558
559 if (vcd_property_level.level < VCD_LEVEL_H264_1
560 || vcd_property_level.level > VCD_LEVEL_H264_5p1) {
561 WFD_MSG_ERR("Level (%d) out of range"
562 "for codec (%d)\n", level, codec);
563
564 rc = -EINVAL;
565 goto err;
566 }
567 } else {
568 WFD_MSG_ERR("Codec (%d) not supported, not setting level (%d)",
569 codec, level);
570 rc = -ENOTSUPP;
571 goto err;
572 }
573
574 rc = vcd_set_property(client_ctx->vcd_handle,
575 &vcd_property_hdr, &vcd_property_level);
576err:
577 return rc;
578}
579
580static long venc_get_codec_level(struct video_client_ctx *client_ctx,
581 __s32 codec, __s32 *level)
582{
583 struct vcd_property_level vcd_property_level;
584 struct vcd_property_hdr vcd_property_hdr;
585 struct vcd_property_codec vcd_property_codec;
586
587 int rc = 0;
588 int mpeg4_base = VCD_LEVEL_MPEG4_0;
589 int h264_base = VCD_LEVEL_H264_1;
590
591 /* Validate params */
592 vcd_property_hdr.prop_id = VCD_I_CODEC;
593 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
594 rc = vcd_get_property(client_ctx->vcd_handle,
595 &vcd_property_hdr, &vcd_property_codec);
596
597 if (rc < 0) {
598 WFD_MSG_ERR("Error getting codec property");
599 rc = -EINVAL;
600 goto err;
601 }
602
603 if (!((vcd_property_codec.codec == VCD_CODEC_H264
604 && codec == V4L2_CID_MPEG_VIDEO_H264_LEVEL) ||
605 (vcd_property_codec.codec == VCD_CODEC_MPEG4
606 && codec == V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL))) {
607 WFD_MSG_ERR("Attempting to get %d for codec type %d",
608 codec, vcd_property_codec.codec);
609 rc = -EINVAL;
610 goto err;
611 }
612
613 vcd_property_hdr.prop_id = VCD_I_LEVEL;
614 vcd_property_hdr.sz = sizeof(struct vcd_property_level);
615
616 rc = vcd_get_property(client_ctx->vcd_handle,
617 &vcd_property_hdr, &vcd_property_level);
618 if (rc < 0) {
619 rc = -EINVAL;
620 goto err;
621 }
622
623 if (codec == V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL) {
624 *level = vcd_property_level.level - mpeg4_base;
625 } else if (codec == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
626 *level = vcd_property_level.level - h264_base;
627 } else {
628 WFD_MSG_ERR("Codec (%d) not supported", codec);
629 rc = -ENOTSUPP;
630 goto err;
631 }
632
633err:
634 return rc;
635}
636
637static long venc_set_codec_profile(struct video_client_ctx *client_ctx,
638 __s32 codec, __s32 profile)
639{
640 struct vcd_property_profile vcd_property_profile;
641 struct vcd_property_hdr vcd_property_hdr;
642 struct vcd_property_codec vcd_property_codec;
Deva Ramasubramanian147c7602012-04-29 14:46:58 -0700643 struct vcd_property_i_period vcd_property_i_period;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800644 int rc = 0;
645
646 /* Validate params */
647 vcd_property_hdr.prop_id = VCD_I_CODEC;
648 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
649 rc = vcd_get_property(client_ctx->vcd_handle,
650 &vcd_property_hdr, &vcd_property_codec);
651
652 if (rc < 0) {
653 WFD_MSG_ERR("Error getting codec property");
654 rc = -EINVAL;
Deva Ramasubramanian147c7602012-04-29 14:46:58 -0700655 goto err_set_profile;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800656 }
657
658 if (!((vcd_property_codec.codec == VCD_CODEC_H264
659 && codec == V4L2_CID_MPEG_VIDEO_H264_PROFILE) ||
660 (vcd_property_codec.codec == VCD_CODEC_MPEG4
661 && codec == V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE))) {
662 WFD_MSG_ERR("Attempting to set %d for codec type %d",
663 codec, vcd_property_codec.codec);
664 rc = -EINVAL;
Deva Ramasubramanian147c7602012-04-29 14:46:58 -0700665 goto err_set_profile;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800666 }
667
668 /* Set property */
669 vcd_property_hdr.prop_id = VCD_I_PROFILE;
670 vcd_property_hdr.sz = sizeof(struct vcd_property_profile);
671
672 if (codec == V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE) {
673 switch (profile) {
674 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
675 vcd_property_profile.profile = VCD_PROFILE_MPEG4_SP;
676 break;
677 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
678 vcd_property_profile.profile = VCD_PROFILE_MPEG4_ASP;
679 break;
680 default:
681 WFD_MSG_ERR("Profile %d not supported,"
682 "defaulting to simple (%d)",
683 profile, VCD_PROFILE_MPEG4_SP);
684 vcd_property_profile.profile = VCD_PROFILE_MPEG4_SP;
685 break;
686 }
687 } else if (codec == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
688 switch (profile) {
689 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
690 vcd_property_profile.profile =
691 VCD_PROFILE_H264_BASELINE;
692 break;
693 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
694 vcd_property_profile.profile = VCD_PROFILE_H264_MAIN;
695 break;
696 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
697 vcd_property_profile.profile = VCD_PROFILE_H264_HIGH;
698 break;
699 default:
700 WFD_MSG_ERR("Profile %d not supported,"
701 "defaulting to baseline (%d)",
702 profile, VCD_PROFILE_H264_BASELINE);
703 vcd_property_profile.profile =
704 VCD_PROFILE_H264_BASELINE;
705 break;
706 }
707 } else {
708 WFD_MSG_ERR("Codec (%d) not supported,"
709 "not setting profile (%d)",
710 codec, profile);
711 rc = -ENOTSUPP;
Deva Ramasubramanian147c7602012-04-29 14:46:58 -0700712 goto err_set_profile;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800713 }
714
715 rc = vcd_set_property(client_ctx->vcd_handle,
716 &vcd_property_hdr, &vcd_property_profile);
Deva Ramasubramanian147c7602012-04-29 14:46:58 -0700717
718 /* Disable B-frames, since VSG doesn't support out of order i/p bufs */
719 vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
720 vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
721
722 rc = vcd_get_property(client_ctx->vcd_handle,
723 &vcd_property_hdr, &vcd_property_i_period);
724 if (rc) {
725 WFD_MSG_ERR("Error getting I-period property");
726 goto err_set_profile;
727 }
728 vcd_property_i_period.b_frames = 0;
729 rc = vcd_set_property(client_ctx->vcd_handle,
730 &vcd_property_hdr, &vcd_property_i_period);
731 if (rc) {
732 WFD_MSG_ERR("Error setting I-period property");
733 goto err_set_profile;
734 }
735
736err_set_profile:
Vinay Kalia699edcf2011-12-01 17:43:47 -0800737 return rc;
738}
739
740static long venc_get_codec_profile(struct video_client_ctx *client_ctx,
741 __s32 codec, __s32 *profile)
742{
743 struct vcd_property_profile vcd_property_profile;
744 struct vcd_property_hdr vcd_property_hdr;
745 struct vcd_property_codec vcd_property_codec;
746 int rc = 0;
747
748 /* Validate params */
749 vcd_property_hdr.prop_id = VCD_I_CODEC;
750 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
751 rc = vcd_get_property(client_ctx->vcd_handle,
752 &vcd_property_hdr, &vcd_property_codec);
753
754 if (rc < 0) {
755 WFD_MSG_ERR("Error getting codec property");
756 rc = -EINVAL;
757 goto err;
758 }
759
760 if (!((vcd_property_codec.codec == VCD_CODEC_H264
761 && codec == V4L2_CID_MPEG_VIDEO_H264_PROFILE) ||
762 (vcd_property_codec.codec == VCD_CODEC_MPEG4
763 && codec == V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE))) {
764 WFD_MSG_ERR("Attempting to set %d for codec type %d",
765 codec, vcd_property_codec.codec);
766 rc = -EINVAL;
767 goto err;
768 }
769
770 /* Set property */
771 vcd_property_hdr.prop_id = VCD_I_PROFILE;
772 vcd_property_hdr.sz = sizeof(struct vcd_property_profile);
773
774 rc = vcd_get_property(client_ctx->vcd_handle,
775 &vcd_property_hdr, &vcd_property_profile);
776
777 if (rc < 0) {
778 WFD_MSG_ERR("Unable to get property");
779 rc = -EINVAL;
780 goto err;
781 }
782
783 switch (vcd_property_profile.profile) {
784 case VCD_PROFILE_MPEG4_SP:
785 *profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE;
786 break;
787 case VCD_PROFILE_MPEG4_ASP:
788 *profile = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE;
789 break;
790 case VCD_PROFILE_H264_BASELINE:
791 *profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
792 break;
793 case VCD_PROFILE_H264_MAIN:
794 *profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
795 break;
796 case VCD_PROFILE_H264_HIGH:
797 *profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
798 break;
799 default:
800 WFD_MSG_ERR("Unexpected profile");
801 rc = -EINVAL;
802 goto err;
803 break;
804 }
805err:
806 return rc;
807}
808
809static long venc_set_h264_intra_period(struct video_client_ctx *client_ctx,
Deva Ramasubramanian3f2e6022012-02-06 15:02:51 -0800810 __s32 period)
811{
Vinay Kalia699edcf2011-12-01 17:43:47 -0800812 struct vcd_property_i_period vcd_property_i_period;
813 struct vcd_property_codec vcd_property_codec;
814 struct vcd_property_hdr vcd_property_hdr;
815 int rc = 0;
816
817 vcd_property_hdr.prop_id = VCD_I_CODEC;
818 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
819
820 rc = vcd_get_property(client_ctx->vcd_handle,
821 &vcd_property_hdr, &vcd_property_codec);
822
823 if (rc < 0) {
824 WFD_MSG_ERR("Error getting codec property\n");
825 goto err;
826 }
827
828 if (vcd_property_codec.codec != VCD_CODEC_H264) {
829 rc = -ENOTSUPP;
830 WFD_MSG_ERR("Control not supported for non H264 codec\n");
831 goto err;
832 }
833
834 vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
835 vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
836
837 vcd_property_i_period.p_frames = period - 1;
Deva Ramasubramanian3f2e6022012-02-06 15:02:51 -0800838 vcd_property_i_period.b_frames = 0;
Vinay Kalia699edcf2011-12-01 17:43:47 -0800839
840 rc = vcd_set_property(client_ctx->vcd_handle,
841 &vcd_property_hdr, &vcd_property_i_period);
842
843 if (rc < 0) {
844 WFD_MSG_ERR("Error setting intra period\n");
845 goto err;
846 }
847
848err:
849 return rc;
850}
851
Deva Ramasubramanian3f2e6022012-02-06 15:02:51 -0800852static long venc_get_h264_intra_period(struct video_client_ctx *client_ctx,
853 __s32 *period)
854{
855 struct vcd_property_i_period vcd_property_i_period;
856 struct vcd_property_codec vcd_property_codec;
857 struct vcd_property_hdr vcd_property_hdr;
858 int rc = 0;
859
860 vcd_property_hdr.prop_id = VCD_I_CODEC;
861 vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
862
863 rc = vcd_get_property(client_ctx->vcd_handle,
864 &vcd_property_hdr, &vcd_property_codec);
865
866 if (rc < 0) {
867 WFD_MSG_ERR("Error getting codec property\n");
868 goto err;
869 }
870
871 if (vcd_property_codec.codec != VCD_CODEC_H264) {
872 rc = -ENOTSUPP;
873 WFD_MSG_ERR("Control not supported for non H264 codec\n");
874 goto err;
875 }
876
877 vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
878 vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
879
880 rc = vcd_get_property(client_ctx->vcd_handle,
881 &vcd_property_hdr, &vcd_property_i_period);
882
883 if (rc < 0) {
884 WFD_MSG_ERR("Error getting intra period\n");
885 goto err;
886 }
887
888 *period = vcd_property_i_period.p_frames + 1;
889err:
890 return rc;
891}
892
Vinay Kalia699edcf2011-12-01 17:43:47 -0800893static long venc_request_frame(struct video_client_ctx *client_ctx, __s32 type)
894{
895 struct vcd_property_req_i_frame vcd_property_req_i_frame;
896 struct vcd_property_hdr vcd_property_hdr;
897
898 int rc = 0;
899 switch (type) {
900 case V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED:
901 /*So...nothing to do?*/
902 break;
903 case V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME:
904 vcd_property_hdr.prop_id = VCD_I_REQ_IFRAME;
905 vcd_property_hdr.sz = sizeof(struct vcd_property_req_i_frame);
906 vcd_property_req_i_frame.req_i_frame = 1;
907
908 rc = vcd_set_property(client_ctx->vcd_handle,
909 &vcd_property_hdr, &vcd_property_req_i_frame);
910 break;
911 case V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED:
912 default:
913 rc = -ENOTSUPP;
914 }
915
916 return rc;
917}
918
919static long venc_set_bitrate(struct video_client_ctx *client_ctx,
920 __s32 bitrate)
921{
922 struct vcd_property_hdr vcd_property_hdr;
923 struct vcd_property_target_bitrate bit_rate;
924 if (!client_ctx || !bitrate)
925 return -EINVAL;
926
927 vcd_property_hdr.prop_id = VCD_I_TARGET_BITRATE;
928 vcd_property_hdr.sz =
929 sizeof(struct vcd_property_target_bitrate);
930 bit_rate.target_bitrate = bitrate;
931 return vcd_set_property(client_ctx->vcd_handle,
932 &vcd_property_hdr, &bit_rate);
933}
934
935static long venc_get_bitrate(struct video_client_ctx *client_ctx,
936 __s32 *bitrate)
937{
938 struct vcd_property_hdr vcd_property_hdr;
939 struct vcd_property_target_bitrate bit_rate;
940 int rc = 0;
941
942 if (!client_ctx || !bitrate)
943 return -EINVAL;
944
945 vcd_property_hdr.prop_id = VCD_I_TARGET_BITRATE;
946 vcd_property_hdr.sz =
947 sizeof(struct vcd_property_target_bitrate);
948 rc = vcd_get_property(client_ctx->vcd_handle,
949 &vcd_property_hdr, &bit_rate);
950
951 if (rc < 0) {
952 WFD_MSG_ERR("Failed getting property for bitrate");
953 return rc;
954 }
955
956 *bitrate = bit_rate.target_bitrate;
957 return rc;
958}
959
960static long venc_set_bitrate_mode(struct video_client_ctx *client_ctx,
961 __s32 mode)
962{
963 struct vcd_property_hdr vcd_property_hdr;
964 struct vcd_property_rate_control rate_control;
965 int rc = 0;
966
967 if (!client_ctx) {
968 rc = -EINVAL;
969 goto err;
970 }
971
972 vcd_property_hdr.prop_id = VCD_I_RATE_CONTROL;
973 vcd_property_hdr.sz = sizeof(struct vcd_property_rate_control);
974 /*
975 * XXX: V4L doesn't seem have a control to toggle between CFR
976 * and VFR, so assuming worse case VFR.
977 */
978 switch (mode) {
979 case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
980 rate_control.rate_control = VCD_RATE_CONTROL_VBR_VFR;
981 break;
982 case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
983 rate_control.rate_control = VCD_RATE_CONTROL_CBR_VFR;
984 break;
985 default:
986 WFD_MSG_ERR("unknown bitrate mode %d", mode);
987 rc = -EINVAL;
988 goto err;
989 }
990
991 rc = vcd_set_property(client_ctx->vcd_handle,
992 &vcd_property_hdr, &rate_control);
993err:
994 return rc;
995}
996
997static long venc_get_bitrate_mode(struct video_client_ctx *client_ctx,
998 __s32 *mode)
999{
1000 struct vcd_property_hdr vcd_property_hdr;
1001 struct vcd_property_rate_control rate_control;
1002 int rc = 0;
1003
1004 if (!client_ctx)
1005 return -EINVAL;
1006
1007 vcd_property_hdr.prop_id = VCD_I_RATE_CONTROL;
1008 vcd_property_hdr.sz = sizeof(struct vcd_property_rate_control);
1009 rc = vcd_get_property(client_ctx->vcd_handle,
1010 &vcd_property_hdr, &rate_control);
1011
1012 switch (rate_control.rate_control) {
1013 case VCD_RATE_CONTROL_CBR_VFR:
1014 case VCD_RATE_CONTROL_CBR_CFR:
1015 *mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
1016 break;
1017 case VCD_RATE_CONTROL_VBR_VFR:
1018 case VCD_RATE_CONTROL_VBR_CFR:
1019 *mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
1020 break;
1021 default:
1022 WFD_MSG_ERR("unknown bitrate mode %d",
1023 rate_control.rate_control);
1024 return -EINVAL;
1025 }
1026
1027 return 0;
1028}
1029
1030static long venc_set_frame_size(struct video_client_ctx *client_ctx,
1031 u32 height, u32 width)
1032{
1033 struct vcd_property_hdr vcd_property_hdr;
1034 struct vcd_property_frame_size frame_size;
1035 vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
1036 vcd_property_hdr.sz =
1037 sizeof(struct vcd_property_frame_size);
1038 frame_size.height = height;
1039 frame_size.width = width;
1040 return vcd_set_property(client_ctx->vcd_handle,
1041 &vcd_property_hdr, &frame_size);
1042}
1043
1044static long venc_set_format(struct v4l2_subdev *sd, void *arg)
1045{
1046 struct venc_inst *inst;
1047 struct video_client_ctx *client_ctx;
1048 struct v4l2_format *fmt = arg;
1049 struct vcd_buffer_requirement buf_req;
1050 int rc = 0;
1051
1052 inst = sd->dev_priv;
1053 client_ctx = &inst->venc_client;
1054 if (!inst || !client_ctx || !fmt) {
1055 WFD_MSG_ERR("Invalid parameters\n");
1056 return -EINVAL;
1057 }
Deva Ramasubramanianc34de062012-01-25 14:42:58 -08001058 rc = venc_set_codec(client_ctx, fmt->fmt.pix.pixelformat);
1059 if (rc) {
1060 WFD_MSG_ERR("Failed to set codec, rc = %d\n", rc);
1061 goto err;
1062 }
1063
Vinay Kalia699edcf2011-12-01 17:43:47 -08001064 rc = venc_set_frame_size(client_ctx, fmt->fmt.pix.height,
1065 fmt->fmt.pix.width);
1066 if (rc) {
1067 WFD_MSG_ERR("Failed to set frame size, rc = %d\n", rc);
1068 goto err;
1069 }
1070 rc = vcd_get_buffer_requirements(client_ctx->vcd_handle,
1071 VCD_BUFFER_OUTPUT, &buf_req);
1072 if (rc) {
1073 WFD_MSG_ERR("Failed to get buf requrements, rc = %d\n", rc);
1074 goto err;
1075 }
1076 fmt->fmt.pix.sizeimage = buf_req.sz;
1077err:
1078 return rc;
1079}
1080
1081static long venc_set_framerate(struct v4l2_subdev *sd,
1082 void *arg)
1083{
1084 struct venc_inst *inst = sd->dev_priv;
1085 struct video_client_ctx *client_ctx = &inst->venc_client;
1086 struct v4l2_fract *frate = arg;
1087 struct vcd_property_hdr vcd_property_hdr;
1088 struct vcd_property_frame_rate vcd_frame_rate;
Deva Ramasubramanian4947d8c2012-04-03 12:41:06 -07001089 struct vcd_property_vop_timing_constant_delta vcd_delta;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001090 int rc;
1091 vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
1092 vcd_property_hdr.sz =
1093 sizeof(struct vcd_property_frame_rate);
Deva Ramasubramanianb84fc502012-01-16 11:42:58 -08001094 /* v4l2 passes in "fps" as "spf", so take reciprocal*/
1095 vcd_frame_rate.fps_denominator = frate->numerator;
1096 vcd_frame_rate.fps_numerator = frate->denominator;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001097 rc = vcd_set_property(client_ctx->vcd_handle,
1098 &vcd_property_hdr, &vcd_frame_rate);
Deva Ramasubramanian4947d8c2012-04-03 12:41:06 -07001099 if (rc) {
Vinay Kalia699edcf2011-12-01 17:43:47 -08001100 WFD_MSG_ERR("Failed to set frame rate, rc = %d\n", rc);
Deva Ramasubramanian4947d8c2012-04-03 12:41:06 -07001101 goto set_framerate_fail;
1102 }
1103
1104 vcd_property_hdr.prop_id = VCD_I_VOP_TIMING_CONSTANT_DELTA;
1105 vcd_property_hdr.sz = sizeof(vcd_delta);
1106
1107 vcd_delta.constant_delta = (frate->numerator * USEC_PER_SEC) /
1108 frate->denominator;
1109 rc = vcd_set_property(client_ctx->vcd_handle,
1110 &vcd_property_hdr, &vcd_delta);
1111
1112 if (rc) {
1113 WFD_MSG_ERR("Failed to set frame delta, rc = %d", rc);
1114 goto set_framerate_fail;
1115 }
1116
1117set_framerate_fail:
Vinay Kalia699edcf2011-12-01 17:43:47 -08001118 return rc;
1119}
1120
Deva Ramasubramanian3f2e6022012-02-06 15:02:51 -08001121static long venc_set_qp_value(struct video_client_ctx *client_ctx,
1122 __s32 frametype, __s32 qp)
1123{
1124 struct vcd_property_hdr vcd_property_hdr;
1125 struct vcd_property_session_qp vcd_property_session_qp;
1126 int rc = 0;
1127
1128 if (!client_ctx) {
1129 WFD_MSG_ERR("Invalid parameters\n");
1130 return -EINVAL;
1131 }
1132
1133 vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
1134 vcd_property_hdr.sz = sizeof(vcd_property_session_qp);
1135
1136 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1137 &vcd_property_session_qp);
1138
1139 if (rc) {
1140 WFD_MSG_ERR("Failed to get session qp\n");
1141 goto err;
1142 }
1143
1144 switch (frametype) {
1145 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
1146 vcd_property_session_qp.i_frame_qp = qp;
1147 break;
1148 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
1149 vcd_property_session_qp.p_frame_qp = qp;
1150 break;
1151 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
1152 vcd_property_session_qp.b_frame_qp = qp;
1153 break;
1154 case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
1155 case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
1156 case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
1157 case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
1158 case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
1159 case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
1160 rc = -ENOTSUPP;
1161 goto err;
1162 default:
1163 rc = -EINVAL;
1164 goto err;
1165 }
1166
1167
1168 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1169 &vcd_property_session_qp);
1170
1171 if (rc) {
1172 WFD_MSG_ERR("Failed to set session qp\n");
1173 goto err;
1174 }
1175err:
1176 return rc;
1177}
1178
1179static long venc_get_qp_value(struct video_client_ctx *client_ctx,
1180 __s32 frametype, __s32 *qp)
1181{
1182 struct vcd_property_hdr vcd_property_hdr;
1183 struct vcd_property_session_qp vcd_property_session_qp;
1184 int rc = 0;
1185
1186 if (!client_ctx) {
1187 WFD_MSG_ERR("Invalid parameters\n");
1188 return -EINVAL;
1189 }
1190
1191 vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
1192 vcd_property_hdr.sz = sizeof(vcd_property_session_qp);
1193
1194 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1195 &vcd_property_session_qp);
1196
1197 if (rc) {
1198 WFD_MSG_ERR("Failed to get session qp\n");
1199 goto err;
1200 }
1201
1202 switch (frametype) {
1203 case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
1204 case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
1205 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
1206 *qp = vcd_property_session_qp.i_frame_qp;
1207 break;
1208 case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
1209 case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
1210 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
1211 *qp = vcd_property_session_qp.p_frame_qp;
1212 break;
1213 case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
1214 case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
1215 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
1216 *qp = vcd_property_session_qp.b_frame_qp;
1217 break;
1218 default:
1219 rc = -EINVAL;
1220 goto err;
1221 }
1222
1223err:
1224 return rc;
1225}
1226
1227static long venc_set_qp_range(struct video_client_ctx *client_ctx,
1228 __s32 type, __s32 qp)
1229{
1230 struct vcd_property_hdr vcd_property_hdr;
1231 struct vcd_property_qp_range vcd_property_qp_range;
1232 int rc = 0;
1233
1234 if (!client_ctx) {
1235 WFD_MSG_ERR("Invalid parameters\n");
1236 return -EINVAL;
1237 }
1238
1239 vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
1240 vcd_property_hdr.sz = sizeof(vcd_property_qp_range);
1241
1242 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1243 &vcd_property_qp_range);
1244
1245 if (rc) {
1246 WFD_MSG_ERR("Failed to get qp range\n");
1247 goto err;
1248 }
1249
1250 switch (type) {
1251 case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
1252 case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
1253 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
1254 vcd_property_qp_range.min_qp = qp;
1255 break;
1256 case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
1257 case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
1258 case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
1259 vcd_property_qp_range.max_qp = qp;
1260 break;
1261 default:
1262 rc = -EINVAL;
1263 goto err;
1264 }
1265
1266 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1267 &vcd_property_qp_range);
1268
1269 if (rc) {
1270 WFD_MSG_ERR("Failed to set qp range\n");
1271 goto err;
1272 }
1273err:
1274 return rc;
1275}
1276
1277static long venc_get_qp_range(struct video_client_ctx *client_ctx,
1278 __s32 type, __s32 *qp)
1279{
1280 struct vcd_property_hdr vcd_property_hdr;
1281 struct vcd_property_qp_range vcd_property_qp_range;
1282 int rc = 0;
1283
1284 if (!client_ctx) {
1285 WFD_MSG_ERR("Invalid parameters\n");
1286 return -EINVAL;
1287 }
1288
1289 vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
1290 vcd_property_hdr.sz = sizeof(vcd_property_qp_range);
1291
1292 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1293 &vcd_property_qp_range);
1294
1295 if (rc) {
1296 WFD_MSG_ERR("Failed to get qp range\n");
1297 goto err;
1298 }
1299
1300 switch (type) {
1301 case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
1302 case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
1303 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
1304 *qp = vcd_property_qp_range.min_qp;
1305 break;
1306 case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
1307 case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
1308 case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
1309 *qp = vcd_property_qp_range.max_qp;
1310 break;
1311 default:
1312 rc = -EINVAL;
1313 goto err;
1314 }
1315
1316 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1317 &vcd_property_qp_range);
1318
1319 if (rc) {
1320 WFD_MSG_ERR("Failed to set qp range\n");
1321 goto err;
1322 }
1323err:
1324 return rc;
1325}
Vinay Kalia700f5c22012-03-28 17:35:28 -07001326static long venc_set_max_perf_level(struct video_client_ctx *client_ctx,
Deva Ramasubramanian837ae362012-05-12 23:26:53 -07001327 __s32 value)
Vinay Kalia700f5c22012-03-28 17:35:28 -07001328{
1329 int rc = 0;
1330 struct vcd_property_hdr vcd_property_hdr;
1331 struct vcd_property_perf_level perf;
Deva Ramasubramanian837ae362012-05-12 23:26:53 -07001332 int level = 0;
1333
1334 switch (value) {
1335 case V4L2_CID_MPEG_QCOM_PERF_LEVEL_PERFORMANCE:
1336 level = VCD_PERF_LEVEL2;
1337 break;
1338 case V4L2_CID_MPEG_QCOM_PERF_LEVEL_TURBO:
1339 level = VCD_PERF_LEVEL_TURBO;
1340 break;
1341 default:
1342 WFD_MSG_ERR("Unknown performance level: %d\n", value);
1343 rc = -ENOTSUPP;
1344 goto err_set_perf_level;
1345 }
1346
Vinay Kalia700f5c22012-03-28 17:35:28 -07001347 vcd_property_hdr.prop_id = VCD_REQ_PERF_LEVEL;
1348 vcd_property_hdr.sz =
1349 sizeof(struct vcd_property_perf_level);
Deva Ramasubramanian837ae362012-05-12 23:26:53 -07001350 perf.level = level;
Vinay Kalia700f5c22012-03-28 17:35:28 -07001351 rc = vcd_set_property(client_ctx->vcd_handle,
1352 &vcd_property_hdr, &perf);
Deva Ramasubramanian837ae362012-05-12 23:26:53 -07001353err_set_perf_level:
Vinay Kalia700f5c22012-03-28 17:35:28 -07001354 return rc;
1355}
Deva Ramasubramanianc84975c2012-03-10 21:16:27 -08001356static long venc_set_header_mode(struct video_client_ctx *client_ctx,
1357 __s32 mode)
1358{
1359 struct vcd_property_hdr vcd_property_hdr;
1360 struct vcd_property_sps_pps_for_idr_enable sps_pps_for_idr_enable;
1361 int rc = 0;
1362
1363 if (!client_ctx) {
1364 WFD_MSG_ERR("Invalid parameters\n");
1365 rc = -EINVAL;
1366 goto err;
1367 }
1368
1369 vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
1370 vcd_property_hdr.sz = sizeof(sps_pps_for_idr_enable);
1371 switch (mode) {
1372 case V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE:
1373 sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag = 0;
1374 break;
1375 case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME:
1376 sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag = 1;
1377 break;
1378 case V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME:
1379 default:
1380 WFD_MSG_ERR("Video header mode %d not supported\n",
1381 mode);
1382 rc = -ENOTSUPP;
1383 goto err;
1384 }
1385
1386 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1387 &sps_pps_for_idr_enable);
1388 if (rc) {
1389 WFD_MSG_ERR("Failed to set enable_sps_pps_for_idr\n");
1390 goto err;
1391 }
1392err:
1393 return rc;
1394}
1395
1396static long venc_get_header_mode(struct video_client_ctx *client_ctx,
1397 __s32 *mode)
1398{
1399 struct vcd_property_hdr vcd_property_hdr;
1400 struct vcd_property_sps_pps_for_idr_enable sps_pps_for_idr_enable;
1401 int rc = 0;
1402
1403 if (!client_ctx) {
1404 WFD_MSG_ERR("Invalid parameters\n");
1405 rc = -EINVAL;
1406 goto err;
1407 }
1408
1409 vcd_property_hdr.prop_id = VCD_I_ENABLE_SPS_PPS_FOR_IDR;
1410 vcd_property_hdr.sz = sizeof(sps_pps_for_idr_enable);
1411 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1412 &sps_pps_for_idr_enable);
1413 if (rc) {
1414 WFD_MSG_ERR("Failed to get sps/pps for idr enable\n");
1415 goto err;
1416 }
1417
1418 *mode = sps_pps_for_idr_enable.sps_pps_for_idr_enable_flag ?
1419 V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_I_FRAME :
1420 V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
1421err:
1422 return rc;
1423}
1424
Deva Ramasubramanian607fbf22012-04-03 16:23:11 -07001425static long venc_set_multislicing_mode(struct video_client_ctx *client_ctx,
1426 __u32 control, __s32 value)
1427{
1428 int rc = 0;
1429 struct vcd_property_hdr vcd_property_hdr;
1430 struct vcd_property_frame_size vcd_frame_size;
1431 struct vcd_buffer_requirement vcd_buf_req;
1432 struct vcd_property_multi_slice vcd_multi_slice;
1433
1434 if (!client_ctx) {
1435 WFD_MSG_ERR("Invalid parameters\n");
1436 rc = -EINVAL;
1437 goto set_multislicing_mode_fail;
1438 }
1439
1440 vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
1441 vcd_property_hdr.sz =
1442 sizeof(vcd_frame_size);
1443 rc = vcd_get_property(client_ctx->vcd_handle,
1444 &vcd_property_hdr, &vcd_frame_size);
1445
1446 if (rc) {
1447 WFD_MSG_ERR("Failed to get frame size\n");
1448 goto set_multislicing_mode_fail;
1449 }
1450
1451 rc = vcd_get_buffer_requirements(client_ctx->vcd_handle,
1452 VCD_BUFFER_OUTPUT, &vcd_buf_req);
1453
1454 if (rc) {
1455 WFD_MSG_ERR("Failed to get buf reqs\n");
1456 goto set_multislicing_mode_fail;
1457 }
1458
1459 vcd_property_hdr.prop_id = VCD_I_MULTI_SLICE;
1460 vcd_property_hdr.sz = sizeof(vcd_multi_slice);
1461 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1462 &vcd_multi_slice);
1463 if (rc) {
1464 WFD_MSG_ERR("Failed to get multi slice\n");
1465 goto set_multislicing_mode_fail;
1466 }
1467
1468 switch (control) {
1469 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
1470 if (vcd_multi_slice.m_slice_sel !=
1471 VCD_MSLICE_BY_BYTE_COUNT) {
1472 WFD_MSG_ERR("Not in proper mode\n");
1473 goto set_multislicing_mode_fail;
1474 }
1475 vcd_multi_slice.m_slice_size = value;
1476 break;
1477
1478 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
1479 if (vcd_multi_slice.m_slice_sel !=
1480 VCD_MSLICE_BY_MB_COUNT) {
1481 WFD_MSG_ERR("Not in proper mode\n");
1482 goto set_multislicing_mode_fail;
1483 }
1484 vcd_multi_slice.m_slice_size = value;
1485 break;
1486
1487 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
1488 switch (value) {
1489 case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
1490 vcd_multi_slice.m_slice_sel = VCD_MSLICE_OFF;
1491 break;
1492 case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
1493 vcd_multi_slice.m_slice_sel = VCD_MSLICE_BY_MB_COUNT;
1494 /* Just a temporary size until client calls
1495 * V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB */
1496 vcd_multi_slice.m_slice_size =
1497 (vcd_frame_size.stride / 16) *
1498 (vcd_frame_size.scan_lines / 16);
1499 break;
1500 case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
1501 vcd_multi_slice.m_slice_sel = VCD_MSLICE_BY_BYTE_COUNT;
1502 /* Just a temporary size until client calls
1503 * V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES */
1504 vcd_multi_slice.m_slice_size = vcd_buf_req.sz;
1505 break;
1506 default:
1507 WFD_MSG_ERR("Unrecognized mode %d\n", value);
1508 rc = -ENOTSUPP;
1509 goto set_multislicing_mode_fail;
1510 }
1511
1512 break;
1513 default:
1514 rc = -EINVAL;
1515 goto set_multislicing_mode_fail;
1516 }
1517
1518 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1519 &vcd_multi_slice);
1520 if (rc) {
1521 WFD_MSG_ERR("Failed to set multi slice\n");
1522 goto set_multislicing_mode_fail;
1523 }
1524
1525set_multislicing_mode_fail:
1526 return rc;
1527}
1528
1529static long venc_get_multislicing_mode(struct video_client_ctx *client_ctx,
1530 __u32 control, __s32 *value)
1531{
1532 int rc = 0;
1533 struct vcd_property_hdr vcd_property_hdr;
1534 struct vcd_property_frame_size vcd_frame_size;
1535 struct vcd_buffer_requirement vcd_buf_req;
1536 struct vcd_property_multi_slice vcd_multi_slice;
1537
1538 if (!client_ctx) {
1539 WFD_MSG_ERR("Invalid parameters\n");
1540 rc = -EINVAL;
1541 goto get_multislicing_mode_fail;
1542 }
1543
1544 vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
1545 vcd_property_hdr.sz =
1546 sizeof(vcd_frame_size);
1547 rc = vcd_get_property(client_ctx->vcd_handle,
1548 &vcd_property_hdr, &vcd_frame_size);
1549
1550 if (rc) {
1551 WFD_MSG_ERR("Failed to get frame size\n");
1552 goto get_multislicing_mode_fail;
1553 }
1554
1555 vcd_property_hdr.prop_id = VCD_I_MULTI_SLICE;
1556 vcd_property_hdr.sz = sizeof(vcd_multi_slice);
1557 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1558 &vcd_multi_slice);
1559 if (rc) {
1560 WFD_MSG_ERR("Failed to get multi slice\n");
1561 goto get_multislicing_mode_fail;
1562 }
1563
1564 rc = vcd_get_buffer_requirements(client_ctx->vcd_handle,
1565 VCD_BUFFER_OUTPUT, &vcd_buf_req);
1566
1567 if (rc) {
1568 WFD_MSG_ERR("Failed to get buf reqs\n");
1569 goto get_multislicing_mode_fail;
1570 }
1571
1572 switch (control) {
1573 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
1574 if (vcd_multi_slice.m_slice_sel == VCD_MSLICE_BY_BYTE_COUNT)
1575 *value = vcd_multi_slice.m_slice_size;
1576 else {
1577 WFD_MSG_ERR("Invalid query when in slice mode %d\n",
1578 vcd_multi_slice.m_slice_sel);
1579 rc = -EINVAL;
1580 goto get_multislicing_mode_fail;
1581 }
1582 break;
1583
1584 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
1585 if (vcd_multi_slice.m_slice_sel == VCD_MSLICE_BY_MB_COUNT)
1586 *value = vcd_multi_slice.m_slice_size;
1587 else {
1588 WFD_MSG_ERR("Invalid query when in slice mode %d\n",
1589 vcd_multi_slice.m_slice_sel);
1590 rc = -EINVAL;
1591 goto get_multislicing_mode_fail;
1592 }
1593 break;
1594
1595 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
1596 switch (vcd_multi_slice.m_slice_sel) {
1597 case VCD_MSLICE_OFF:
1598 *value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE;
1599 break;
1600 case VCD_MSLICE_BY_MB_COUNT:
1601 *value = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB;
1602 break;
1603 case VCD_MSLICE_BY_BYTE_COUNT:
1604 *value = V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES;
1605 break;
1606 default:
1607 WFD_MSG_ERR("Encoder in an unknown mode %d\n",
1608 vcd_multi_slice.m_slice_sel);
1609 rc = -ENOENT;
1610 goto get_multislicing_mode_fail;
1611
1612 }
1613 break;
1614 default:
1615 rc = -EINVAL;
1616 goto get_multislicing_mode_fail;
1617 }
1618
1619get_multislicing_mode_fail:
1620 return rc;
1621}
1622
Deva Ramasubramanianf94df432012-04-29 11:09:03 -07001623static long venc_set_entropy_mode(struct video_client_ctx *client_ctx,
1624 __s32 value)
1625{
1626 struct vcd_property_hdr vcd_property_hdr;
1627 struct vcd_property_entropy_control entropy_control;
1628 int rc = 0;
1629
1630 if (!client_ctx) {
1631 WFD_MSG_ERR("Invalid parameters\n");
1632 rc = -EINVAL;
1633 goto set_entropy_mode_fail;
1634 }
1635
1636 vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
1637 vcd_property_hdr.sz = sizeof(entropy_control);
1638
1639 switch (value) {
1640 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
1641 entropy_control.entropy_sel = VCD_ENTROPY_SEL_CAVLC;
1642 break;
1643 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
1644 entropy_control.entropy_sel = VCD_ENTROPY_SEL_CABAC;
1645 entropy_control.cabac_model = VCD_CABAC_MODEL_NUMBER_0;
1646 break;
1647 default:
1648 WFD_MSG_ERR("Entropy type %d not supported\n", value);
1649 rc = -ENOTSUPP;
1650 goto set_entropy_mode_fail;
1651 }
1652 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1653 &entropy_control);
1654 if (rc) {
1655 WFD_MSG_ERR("Failed to set entropy mode\n");
1656 goto set_entropy_mode_fail;
1657 }
1658
1659set_entropy_mode_fail:
1660 return rc;
1661}
1662
1663static long venc_get_entropy_mode(struct video_client_ctx *client_ctx,
1664 __s32 *value)
1665{
1666 struct vcd_property_hdr vcd_property_hdr;
1667 struct vcd_property_entropy_control entropy_control;
1668 int rc = 0;
1669
1670 if (!client_ctx || !value) {
1671 WFD_MSG_ERR("Invalid parameters\n");
1672 rc = -EINVAL;
1673 goto get_entropy_mode_fail;
1674 }
1675
1676 vcd_property_hdr.prop_id = VCD_I_ENTROPY_CTRL;
1677 vcd_property_hdr.sz = sizeof(entropy_control);
1678
1679 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1680 &entropy_control);
1681
1682 if (rc) {
1683 WFD_MSG_ERR("Failed to get entropy mode\n");
1684 goto get_entropy_mode_fail;
1685 }
1686
1687 switch (entropy_control.entropy_sel) {
1688 case VCD_ENTROPY_SEL_CAVLC:
1689 *value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC;
1690 break;
1691 case VCD_ENTROPY_SEL_CABAC:
1692 *value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC;
1693 break;
1694 default:
1695 WFD_MSG_ERR("Entropy type %d not known\n",
1696 entropy_control.entropy_sel);
1697 rc = -EINVAL;
1698 goto get_entropy_mode_fail;
1699 }
1700get_entropy_mode_fail:
1701 return rc;
1702}
1703
Deva Ramasubramaniane5ce7722012-04-30 11:27:45 -07001704static long venc_set_cyclic_intra_refresh_mb(
1705 struct video_client_ctx *client_ctx,
1706 __s32 value)
1707{
1708 struct vcd_property_hdr vcd_property_hdr;
1709 struct vcd_property_intra_refresh_mb_number cir_mb_num;
1710 int rc = 0;
1711
1712 if (!client_ctx) {
1713 WFD_MSG_ERR("Invalid parameters\n");
1714 rc = -EINVAL;
1715 goto set_cir_mbs_fail;
1716 }
1717
1718 vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
1719 vcd_property_hdr.sz = sizeof(cir_mb_num);
1720
1721 cir_mb_num.cir_mb_number = value;
1722
1723 rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
1724 &cir_mb_num);
1725 if (rc) {
1726 WFD_MSG_ERR("Failed to set CIR MBs\n");
1727 goto set_cir_mbs_fail;
1728 }
1729
1730set_cir_mbs_fail:
1731 return rc;
1732}
1733
1734static long venc_get_cyclic_intra_refresh_mb(
1735 struct video_client_ctx *client_ctx,
1736 __s32 *value)
1737{
1738 struct vcd_property_hdr vcd_property_hdr;
1739 struct vcd_property_intra_refresh_mb_number cir_mb_num;
1740 int rc = 0;
1741
1742 if (!client_ctx || !value) {
1743 WFD_MSG_ERR("Invalid parameters\n");
1744 rc = -EINVAL;
1745 goto get_cir_mbs_fail;
1746 }
1747
1748 vcd_property_hdr.prop_id = VCD_I_INTRA_REFRESH;
1749 vcd_property_hdr.sz = sizeof(cir_mb_num);
1750
1751 rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
1752 &cir_mb_num);
1753 if (rc) {
1754 WFD_MSG_ERR("Failed to set CIR MBs\n");
1755 goto get_cir_mbs_fail;
1756 }
1757
1758 *value = cir_mb_num.cir_mb_number;
1759
1760get_cir_mbs_fail:
1761 return rc;
1762}
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08001763static long venc_set_input_buffer(struct v4l2_subdev *sd, void *arg)
Vinay Kalia699edcf2011-12-01 17:43:47 -08001764{
1765 struct mem_region *mregion = arg;
1766 struct venc_inst *inst = sd->dev_priv;
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08001767 unsigned long paddr, kvaddr, temp;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001768 struct video_client_ctx *client_ctx = &inst->venc_client;
1769 int rc = 0;
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08001770
Vinay Kalia699edcf2011-12-01 17:43:47 -08001771 if (!client_ctx || !mregion) {
1772 WFD_MSG_ERR("Invalid input\n");
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08001773 rc = -EINVAL;
1774 goto ins_table_fail;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001775 }
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08001776
1777 kvaddr = (unsigned long)mregion->kvaddr;
1778 paddr = (unsigned long)mregion->paddr;
1779
1780 if (!kvaddr || !paddr) {
1781 WFD_MSG_ERR("Invalid addresses\n");
1782 rc = -EINVAL;
1783 goto ins_table_fail;
1784 }
1785
1786 /*
1787 * Just a note: the third arg of vidc_insert_\
1788 * addr_table_kernel is supposed to be a userspace
1789 * address that is used as a key in the table. As
1790 * these bufs never leave the kernel, we need to have
1791 * an unique value to use as a key. So re-using kernel
1792 * virtual addr for this purpose
1793 */
1794 rc = vidc_insert_addr_table_kernel(client_ctx,
1795 BUFFER_TYPE_INPUT, kvaddr, kvaddr,
1796 paddr, 32, mregion->size);
1797
1798 if (rc == (u32)false) {
1799 WFD_MSG_ERR("Failed to insert input buffer into table\n");
1800 rc = -EFAULT;
1801 goto ins_table_fail;
1802 }
1803
1804 rc = vcd_set_buffer(client_ctx->vcd_handle,
1805 VCD_BUFFER_INPUT, (u8 *)kvaddr,
1806 mregion->size);
1807
1808 if (rc) {
1809 WFD_MSG_ERR("Failed to set input buffer\n");
1810 rc = -EFAULT;
1811 goto set_input_buf_fail;
1812 }
1813
1814
1815 return rc;
1816
1817set_input_buf_fail:
1818 vidc_delete_addr_table(client_ctx, BUFFER_TYPE_INPUT,
1819 kvaddr, &temp);
1820ins_table_fail:
Vinay Kalia699edcf2011-12-01 17:43:47 -08001821 return rc;
1822}
1823
1824static long venc_set_output_buffer(struct v4l2_subdev *sd, void *arg)
1825{
1826 int rc = 0;
1827 struct venc_inst *inst = sd->dev_priv;
1828 struct video_client_ctx *client_ctx = &inst->venc_client;
1829 struct mem_region *mregion = arg;
1830 if (!client_ctx || !mregion) {
1831 WFD_MSG_ERR("Invalid input\n");
1832 return -EINVAL;
1833 }
1834 WFD_MSG_DBG("size = %u, offset = %u fd = %d\n", mregion->size,
1835 mregion->offset, mregion->fd);
1836 rc = vidc_insert_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
1837 mregion->cookie,
1838 (unsigned long *)&mregion->kvaddr,
1839 mregion->fd,
1840 mregion->offset,
1841 32,
1842 mregion->size);
Deva Ramasubramanianb84fc502012-01-16 11:42:58 -08001843 if (rc == (u32)false) {
Vinay Kalia699edcf2011-12-01 17:43:47 -08001844 WFD_MSG_ERR("Failed to insert outbuf in table\n");
Deva Ramasubramanianb84fc502012-01-16 11:42:58 -08001845 rc = -EINVAL;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001846 goto err;
1847 }
1848 WFD_MSG_DBG("size = %u, %p\n", mregion->size, mregion->kvaddr);
1849
1850 rc = vcd_set_buffer(client_ctx->vcd_handle,
1851 VCD_BUFFER_OUTPUT, (u8 *) mregion->kvaddr,
1852 mregion->size);
1853 if (rc)
1854 WFD_MSG_ERR("Failed to set outbuf on encoder\n");
1855err:
1856 return rc;
1857}
1858
1859static long venc_fill_outbuf(struct v4l2_subdev *sd, void *arg)
1860{
1861 int rc = 0;
1862 struct venc_inst *inst = sd->dev_priv;
1863 struct video_client_ctx *client_ctx = &inst->venc_client;
1864 struct mem_region *mregion = arg;
1865 struct vcd_frame_data vcd_frame = {0};
1866 unsigned long kernel_vaddr, phy_addr, user_vaddr;
1867 int pmem_fd;
1868 struct file *file;
1869 s32 buffer_index = -1;
1870
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -07001871 if (inst->streaming) {
1872 user_vaddr = mregion->cookie;
1873 rc = vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
1874 true, &user_vaddr,
1875 &kernel_vaddr, &phy_addr, &pmem_fd, &file,
1876 &buffer_index);
1877 if (!rc) {
1878 WFD_MSG_ERR("Address lookup failed\n");
1879 goto err;
1880 }
1881 vcd_frame.virtual = (u8 *) kernel_vaddr;
1882 vcd_frame.frm_clnt_data = mregion->cookie;
1883 vcd_frame.alloc_len = mregion->size;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001884
Deva Ramasubramanian08413fc2012-07-16 17:27:02 -07001885 rc = vcd_fill_output_buffer(client_ctx->vcd_handle, &vcd_frame);
1886 if (rc)
1887 WFD_MSG_ERR("Failed to fill output buffer on encoder");
1888 } else {
1889 struct mem_region *temp = kzalloc(sizeof(*temp), GFP_KERNEL);
1890 *temp = *mregion;
1891 INIT_LIST_HEAD(&temp->list);
1892 list_add_tail(&temp->list, &inst->unqueued_op_bufs.list);
1893 }
Vinay Kalia699edcf2011-12-01 17:43:47 -08001894err:
1895 return rc;
1896}
1897
1898static long venc_encode_frame(struct v4l2_subdev *sd, void *arg)
1899{
1900 int rc = 0;
1901 struct venc_inst *inst = sd->dev_priv;
1902 struct video_client_ctx *client_ctx = &inst->venc_client;
Deva Ramasubramanianb84fc502012-01-16 11:42:58 -08001903 struct venc_buf_info *venc_buf = arg;
1904 struct mem_region *mregion = venc_buf->mregion;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001905 struct vcd_frame_data vcd_input_buffer = {0};
Deva Ramasubramanian4947d8c2012-04-03 12:41:06 -07001906 int64_t ts = 0;
1907
1908 ts = venc_buf->timestamp;
1909 do_div(ts, NSEC_PER_USEC);
Vinay Kalia699edcf2011-12-01 17:43:47 -08001910
1911 vcd_input_buffer.virtual = mregion->kvaddr;
1912 vcd_input_buffer.frm_clnt_data = (u32)mregion;
1913 vcd_input_buffer.ip_frm_tag = (u32)mregion;
1914 vcd_input_buffer.data_len = mregion->size;
Deva Ramasubramanian4947d8c2012-04-03 12:41:06 -07001915 vcd_input_buffer.time_stamp = ts;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001916 vcd_input_buffer.offset = 0;
1917
1918 rc = vcd_encode_frame(client_ctx->vcd_handle,
1919 &vcd_input_buffer);
1920
1921 if (rc)
1922 WFD_MSG_ERR("encode frame failed\n");
1923 return rc;
1924}
1925
1926static long venc_alloc_recon_buffers(struct v4l2_subdev *sd, void *arg)
1927{
1928 int rc = 0;
1929 struct venc_inst *inst = sd->dev_priv;
1930 struct video_client_ctx *client_ctx = &inst->venc_client;
1931 struct vcd_property_hdr vcd_property_hdr;
1932 struct vcd_property_buffer_size control;
1933 struct vcd_property_enc_recon_buffer *ctrl = NULL;
1934 unsigned long phy_addr;
1935 int i = 0;
Deepak kotur13d82f82012-03-12 11:12:32 -07001936 int flags = 0;
Vinay Kalia699edcf2011-12-01 17:43:47 -08001937 u32 len;
1938 control.width = inst->width;
1939 control.height = inst->height;
1940 vcd_property_hdr.prop_id = VCD_I_GET_RECON_BUFFER_SIZE;
1941 vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
1942
1943 rc = vcd_get_property(client_ctx->vcd_handle,
1944 &vcd_property_hdr, &control);
1945 if (rc) {
1946 WFD_MSG_ERR("Failed to get recon buf size\n");
1947 goto err;
1948 }
Deepak kotur13d82f82012-03-12 11:12:32 -07001949 flags = ION_HEAP(ION_CP_MM_HEAP_ID);
1950 flags |= inst->secure ? ION_SECURE : ION_HEAP(ION_IOMMU_HEAP_ID);
Vinay Kalia699edcf2011-12-01 17:43:47 -08001951
1952 if (vcd_get_ion_status()) {
1953 for (i = 0; i < 4; ++i) {
1954 ctrl = &client_ctx->recon_buffer[i];
1955 ctrl->buffer_size = control.size;
1956 ctrl->pmem_fd = 0;
1957 ctrl->offset = 0;
1958 ctrl->user_virtual_addr = (void *)i;
1959 client_ctx->recon_buffer_ion_handle[i]
1960 = ion_alloc(client_ctx->user_ion_client,
Deepak kotur13d82f82012-03-12 11:12:32 -07001961 control.size, SZ_8K, flags);
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08001962
Vinay Kalia699edcf2011-12-01 17:43:47 -08001963 ctrl->kernel_virtual_addr = ion_map_kernel(
1964 client_ctx->user_ion_client,
1965 client_ctx->recon_buffer_ion_handle[i], 0);
1966
Arun Menon0e1d3a12012-07-30 14:38:39 -07001967 if (IS_ERR_OR_NULL(ctrl->kernel_virtual_addr)) {
1968 WFD_MSG_ERR("ion map kernel failed\n");
1969 rc = -EINVAL;
1970 goto free_ion_alloc;
1971 }
1972
1973 if (inst->secure) {
1974 rc = ion_phys(client_ctx->user_ion_client,
1975 client_ctx->recon_buffer_ion_handle[i],
1976 &phy_addr, (size_t *)&len);
1977 if (rc || !phy_addr) {
1978 WFD_MSG_ERR("ion physical failed\n");
1979 goto unmap_ion_alloc;
1980 }
1981 } else {
1982 rc = ion_map_iommu(client_ctx->user_ion_client,
1983 client_ctx->recon_buffer_ion_handle[i],
1984 VIDEO_DOMAIN, VIDEO_MAIN_POOL, SZ_4K,
1985 0, &phy_addr, (unsigned long *)&len,
1986 0, 0);
1987 if (rc || !phy_addr) {
1988 WFD_MSG_ERR(
1989 "ion map iommu failed, rc = %d, phy_addr = 0x%lx\n",
1990 rc, phy_addr);
1991 goto unmap_ion_alloc;
1992 }
1993
Vinay Kalia699edcf2011-12-01 17:43:47 -08001994 }
1995 ctrl->physical_addr = (u8 *) phy_addr;
1996 ctrl->dev_addr = ctrl->physical_addr;
1997 vcd_property_hdr.prop_id = VCD_I_RECON_BUFFERS;
1998 vcd_property_hdr.sz =
1999 sizeof(struct vcd_property_enc_recon_buffer);
2000 rc = vcd_set_property(client_ctx->vcd_handle,
2001 &vcd_property_hdr, ctrl);
2002 if (rc) {
2003 WFD_MSG_ERR("Failed to set recon buffers\n");
Arun Menon0e1d3a12012-07-30 14:38:39 -07002004 goto unmap_ion_iommu;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002005 }
2006 }
2007 } else {
2008 WFD_MSG_ERR("PMEM not suported\n");
2009 return -ENOMEM;
2010 }
Arun Menon0e1d3a12012-07-30 14:38:39 -07002011 return rc;
2012unmap_ion_iommu:
2013 if (!inst->secure) {
2014 if (client_ctx->recon_buffer_ion_handle[i]) {
2015 ion_unmap_iommu(client_ctx->user_ion_client,
2016 client_ctx->recon_buffer_ion_handle[i],
2017 VIDEO_DOMAIN, VIDEO_MAIN_POOL);
2018 }
2019 }
2020unmap_ion_alloc:
2021 if (client_ctx->recon_buffer_ion_handle[i]) {
2022 ion_unmap_kernel(client_ctx->user_ion_client,
2023 client_ctx->recon_buffer_ion_handle[i]);
2024 ctrl->kernel_virtual_addr = NULL;
2025 ctrl->physical_addr = NULL;
2026 }
2027free_ion_alloc:
2028 if (client_ctx->recon_buffer_ion_handle[i]) {
2029 ion_free(client_ctx->user_ion_client,
2030 client_ctx->recon_buffer_ion_handle[i]);
2031 client_ctx->recon_buffer_ion_handle[i] = NULL;
2032 }
2033 WFD_MSG_ERR("Failed to allo recon buffers\n");
Vinay Kalia699edcf2011-12-01 17:43:47 -08002034err:
2035 return rc;
2036}
2037
2038static long venc_free_output_buffer(struct v4l2_subdev *sd, void *arg)
2039{
2040 int rc = 0;
2041 struct venc_inst *inst = sd->dev_priv;
2042 struct video_client_ctx *client_ctx = &inst->venc_client;
2043 struct mem_region *mregion = arg;
2044 unsigned long kernel_vaddr, user_vaddr;
2045
2046 if (!client_ctx || !mregion) {
2047 WFD_MSG_ERR("Invalid input\n");
2048 return -EINVAL;
2049 }
2050
2051 user_vaddr = mregion->cookie;
2052 rc = vidc_delete_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
2053 user_vaddr,
2054 &kernel_vaddr);
2055 if (!rc) {
2056 WFD_MSG_ERR("Failed to delete buf from address table\n");
2057 return -EINVAL;
2058 }
2059 return vcd_free_buffer(client_ctx->vcd_handle, VCD_BUFFER_OUTPUT,
2060 (u8 *)kernel_vaddr);
2061}
2062
Vinay Kaliab6dd5872012-04-05 15:24:58 -07002063static long venc_flush_buffers(struct v4l2_subdev *sd, void *arg)
2064{
2065 int rc = 0;
2066 struct venc_inst *inst = sd->dev_priv;
2067 struct video_client_ctx *client_ctx = &inst->venc_client;
2068 if (!client_ctx) {
2069 WFD_MSG_ERR("Invalid input\n");
2070 return -EINVAL;
2071 }
2072 rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_INPUT);
2073 if (rc) {
2074 WFD_MSG_ERR("Failed to flush input buffers\n");
2075 rc = -EIO;
2076 goto flush_failed;
2077 }
2078 wait_for_completion(&client_ctx->event);
2079 if (client_ctx->event_status) {
2080 WFD_MSG_ERR("callback for vcd_flush input returned error: %u",
2081 client_ctx->event_status);
2082 rc = -EIO;
2083 goto flush_failed;
2084 }
2085 rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_OUTPUT);
2086 if (rc) {
2087 WFD_MSG_ERR("Failed to flush output buffers\n");
2088 rc = -EIO;
2089 goto flush_failed;
2090 }
2091 wait_for_completion(&client_ctx->event);
2092 if (client_ctx->event_status) {
2093 WFD_MSG_ERR("callback for vcd_flush output returned error: %u",
2094 client_ctx->event_status);
2095 rc = -EIO;
2096 goto flush_failed;
2097 }
2098
2099flush_failed:
2100 return rc;
2101}
2102
Vinay Kalia699edcf2011-12-01 17:43:47 -08002103static long venc_free_input_buffer(struct v4l2_subdev *sd, void *arg)
2104{
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08002105 int del_rc = 0, free_rc = 0;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002106 struct venc_inst *inst = sd->dev_priv;
2107 struct video_client_ctx *client_ctx = &inst->venc_client;
2108 struct mem_region *mregion = arg;
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08002109 unsigned long vidc_kvaddr;
2110
Vinay Kalia699edcf2011-12-01 17:43:47 -08002111 if (!client_ctx || !mregion) {
2112 WFD_MSG_ERR("Invalid input\n");
2113 return -EINVAL;
2114 }
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08002115
2116 del_rc = vidc_delete_addr_table(client_ctx, BUFFER_TYPE_INPUT,
2117 (unsigned long)mregion->kvaddr,
2118 &vidc_kvaddr);
2119 /*
2120 * Even if something went wrong in when
2121 * deleting from table, call vcd_free_buf
2122 */
2123 if (del_rc == (u32)false) {
2124 WFD_MSG_ERR("Failed to delete buf from address table\n");
2125 del_rc = -ENOKEY;
2126 } else if ((u8 *)vidc_kvaddr != mregion->kvaddr) {
2127 WFD_MSG_ERR("Failed to find expected buffer\n");
2128 del_rc = -EINVAL;
2129 } else
2130 del_rc = 0;
2131
2132 free_rc = vcd_free_buffer(client_ctx->vcd_handle, VCD_BUFFER_INPUT,
2133 (u8 *)vidc_kvaddr);
2134
2135 if (free_rc) {
2136 WFD_MSG_ERR("Failed to free buffer from encoder\n");
2137 free_rc = -EINVAL;
2138 }
2139
2140 return del_rc ? del_rc : free_rc;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002141}
2142
2143static long venc_free_recon_buffers(struct v4l2_subdev *sd, void *arg)
2144{
2145 int rc = 0;
2146 struct venc_inst *inst = sd->dev_priv;
2147 struct video_client_ctx *client_ctx = &inst->venc_client;
2148 struct vcd_property_hdr vcd_property_hdr;
2149 int i;
2150
2151 if (vcd_get_ion_status()) {
2152 for (i = 0; i < 4; i++) {
2153 vcd_property_hdr.prop_id = VCD_I_FREE_RECON_BUFFERS;
2154 vcd_property_hdr.sz =
2155 sizeof(struct vcd_property_buffer_size);
2156 rc = vcd_set_property(client_ctx->vcd_handle,
2157 &vcd_property_hdr, &client_ctx->recon_buffer[i]);
2158 if (rc)
2159 WFD_MSG_ERR("Failed to free recon buffer\n");
2160
Arun Menon0e1d3a12012-07-30 14:38:39 -07002161 if (IS_ERR_OR_NULL(
2162 client_ctx->recon_buffer_ion_handle[i])) {
2163 if (!inst->secure) {
2164 ion_unmap_iommu(
2165 client_ctx->user_ion_client,
2166 client_ctx->recon_buffer_ion_handle[i],
2167 VIDEO_DOMAIN, VIDEO_MAIN_POOL);
2168 }
Vinay Kalia699edcf2011-12-01 17:43:47 -08002169 ion_unmap_kernel(client_ctx->user_ion_client,
2170 client_ctx->recon_buffer_ion_handle[i]);
2171 ion_free(client_ctx->user_ion_client,
2172 client_ctx->recon_buffer_ion_handle[i]);
2173 client_ctx->recon_buffer_ion_handle[i] = NULL;
2174 }
2175 }
2176 }
2177 return rc;
2178}
2179
2180static long venc_set_property(struct v4l2_subdev *sd, void *arg)
2181{
2182 int rc = 0;
2183 struct venc_inst *inst = sd->dev_priv;
2184 struct v4l2_control *ctrl = arg;
2185 struct video_client_ctx *client_ctx = &inst->venc_client;
2186 switch (ctrl->id) {
2187 case V4L2_CID_MPEG_VIDEO_BITRATE:
2188 rc = venc_set_bitrate(client_ctx, ctrl->value);
2189 break;
2190 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
2191 rc = venc_set_bitrate_mode(client_ctx, ctrl->value);
2192 break;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002193 case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
2194 rc = venc_set_h264_intra_period(client_ctx, ctrl->value);
2195 break;
2196 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
2197 rc = venc_set_codec_level(client_ctx, ctrl->id, ctrl->value);
2198 break;
2199 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
2200 rc = venc_set_codec_profile(client_ctx, ctrl->id, ctrl->value);
2201 break;
2202 case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
2203 rc = venc_request_frame(client_ctx, ctrl->value);
2204 break;
Deva Ramasubramanian3f2e6022012-02-06 15:02:51 -08002205 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
2206 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
2207 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
2208 case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
2209 case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
2210 case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
2211 case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
2212 case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
2213 case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
2214 rc = venc_set_qp_value(client_ctx, ctrl->id, ctrl->value);
2215 break;
2216 case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
2217 case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
2218 case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
2219 case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
2220 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
2221 case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
2222 rc = venc_set_qp_range(client_ctx, ctrl->id, ctrl->value);
2223 break;
Deva Ramasubramanianc84975c2012-03-10 21:16:27 -08002224 case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
2225 rc = venc_set_header_mode(client_ctx, ctrl->value);
2226 break;
Deva Ramasubramanian607fbf22012-04-03 16:23:11 -07002227 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
2228 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
2229 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
2230 rc = venc_set_multislicing_mode(client_ctx, ctrl->id,
2231 ctrl->value);
2232 break;
Vinay Kalia700f5c22012-03-28 17:35:28 -07002233 case V4L2_CID_MPEG_QCOM_SET_PERF_LEVEL:
2234 rc = venc_set_max_perf_level(client_ctx, ctrl->value);
2235 break;
Deva Ramasubramanianf94df432012-04-29 11:09:03 -07002236 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
2237 rc = venc_set_entropy_mode(client_ctx, ctrl->value);
2238 break;
Deva Ramasubramaniane5ce7722012-04-30 11:27:45 -07002239 case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
2240 rc = venc_set_cyclic_intra_refresh_mb(client_ctx, ctrl->value);
2241 break;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002242 default:
2243 WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
2244 rc = -ENOTSUPP;
2245 break;
2246 }
2247 return rc;
2248}
2249
2250static long venc_get_property(struct v4l2_subdev *sd, void *arg)
2251{
2252 int rc = 0;
2253 struct venc_inst *inst = sd->dev_priv;
2254 struct v4l2_control *ctrl = arg;
2255 struct video_client_ctx *client_ctx = &inst->venc_client;
2256
2257 switch (ctrl->id) {
2258 case V4L2_CID_MPEG_VIDEO_BITRATE:
2259 rc = venc_get_bitrate(client_ctx, &ctrl->value);
2260 break;
2261 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
2262 rc = venc_get_bitrate_mode(client_ctx, &ctrl->value);
2263 break;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002264 case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
2265 rc = venc_get_codec_level(client_ctx, ctrl->id, &ctrl->value);
2266 break;
2267 case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
2268 rc = venc_get_codec_profile(client_ctx, ctrl->id, &ctrl->value);
2269 break;
Deva Ramasubramanian3f2e6022012-02-06 15:02:51 -08002270 case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
2271 rc = venc_get_h264_intra_period(client_ctx, &ctrl->value);
2272 break;
2273 case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
2274 case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
2275 case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
2276 case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
2277 case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
2278 case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
2279 case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
2280 case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
2281 case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
2282 rc = venc_get_qp_value(client_ctx, ctrl->id, &ctrl->value);
2283 break;
2284 case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
2285 case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
2286 case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
2287 case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
2288 case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
2289 case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
2290 rc = venc_get_qp_range(client_ctx, ctrl->id, &ctrl->value);
2291 break;
Deva Ramasubramanianc84975c2012-03-10 21:16:27 -08002292 case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
2293 rc = venc_get_header_mode(client_ctx, &ctrl->value);
2294 break;
Deva Ramasubramanian607fbf22012-04-03 16:23:11 -07002295 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
2296 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
2297 case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
2298 rc = venc_get_multislicing_mode(client_ctx, ctrl->id,
2299 &ctrl->value);
2300 break;
Deva Ramasubramanianf94df432012-04-29 11:09:03 -07002301 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
2302 rc = venc_get_entropy_mode(client_ctx, &ctrl->value);
2303 break;
Deva Ramasubramaniane5ce7722012-04-30 11:27:45 -07002304 case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
2305 rc = venc_get_cyclic_intra_refresh_mb(client_ctx, &ctrl->value);
2306 break;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002307 default:
2308 WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
2309 rc = -ENOTSUPP;
2310 break;
2311 }
2312 return rc;
2313}
2314
2315long venc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
2316{
2317 long rc = 0;
2318 switch (cmd) {
2319 case OPEN:
2320 rc = venc_open(sd, arg);
2321 break;
2322 case CLOSE:
2323 rc = venc_close(sd, arg);
2324 break;
2325 case ENCODE_START:
2326 rc = venc_start(sd);
2327 break;
2328 case ENCODE_FRAME:
2329 venc_encode_frame(sd, arg);
2330 break;
2331 case ENCODE_STOP:
2332 rc = venc_stop(sd);
2333 break;
2334 case SET_PROP:
2335 rc = venc_set_property(sd, arg);
2336 break;
2337 case GET_PROP:
2338 rc = venc_get_property(sd, arg);
2339 break;
2340 case GET_BUFFER_REQ:
2341 rc = venc_get_buffer_req(sd, arg);
2342 break;
2343 case SET_BUFFER_REQ:
2344 rc = venc_set_buffer_req(sd, arg);
2345 break;
2346 case FREE_BUFFER:
2347 break;
2348 case FILL_OUTPUT_BUFFER:
2349 rc = venc_fill_outbuf(sd, arg);
2350 break;
2351 case SET_FORMAT:
2352 rc = venc_set_format(sd, arg);
2353 break;
2354 case SET_FRAMERATE:
2355 rc = venc_set_framerate(sd, arg);
2356 break;
Deva Ramasubramanian2e99bff2012-02-13 21:12:08 -08002357 case SET_INPUT_BUFFER:
2358 rc = venc_set_input_buffer(sd, arg);
Vinay Kalia699edcf2011-12-01 17:43:47 -08002359 break;
2360 case SET_OUTPUT_BUFFER:
2361 rc = venc_set_output_buffer(sd, arg);
2362 break;
2363 case ALLOC_RECON_BUFFERS:
2364 rc = venc_alloc_recon_buffers(sd, arg);
2365 break;
2366 case FREE_OUTPUT_BUFFER:
2367 rc = venc_free_output_buffer(sd, arg);
2368 break;
2369 case FREE_INPUT_BUFFER:
2370 rc = venc_free_input_buffer(sd, arg);
2371 break;
2372 case FREE_RECON_BUFFERS:
2373 rc = venc_free_recon_buffers(sd, arg);
2374 break;
Vinay Kaliab6dd5872012-04-05 15:24:58 -07002375 case ENCODE_FLUSH:
2376 rc = venc_flush_buffers(sd, arg);
2377 break;
Vinay Kalia699edcf2011-12-01 17:43:47 -08002378 default:
2379 rc = -1;
2380 break;
2381 }
2382 return rc;
2383}