blob: 4704ae7830a78fee7436fe57e9a658719ed032b7 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2008-2009, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/slab.h>
15#include <linux/cdev.h>
16#include <linux/file.h>
17#include <linux/device.h>
18#include <linux/fs.h>
19#include <linux/list.h>
20#include <linux/module.h>
21#include <linux/sched.h>
22#include <linux/spinlock.h>
23#include <linux/uaccess.h>
24#include <linux/wakelock.h>
25#include <linux/android_pmem.h>
26#include <linux/msm_q6venc.h>
Stephen Boyd2fcabf92012-05-30 10:41:11 -070027#include <linux/pm_qos.h>
28
29#include <mach/cpuidle.h>
30
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031#include "dal.h"
32
33#define DALDEVICEID_VENC_DEVICE 0x0200002D
34#define DALDEVICEID_VENC_PORTNAME "DAL_AQ_VID"
35
36#define VENC_NAME "q6venc"
37#define VENC_MSG_MAX 128
38
39#define VENC_INTERFACE_VERSION 0x00020000
40#define MAJOR_MASK 0xFFFF0000
41#define MINOR_MASK 0x0000FFFF
42#define VENC_GET_MAJOR_VERSION(version) ((version & MAJOR_MASK)>>16)
43#define VENC_GET_MINOR_VERSION(version) (version & MINOR_MASK)
44
45enum {
46 VENC_BUFFER_TYPE_INPUT,
47 VENC_BUFFER_TYPE_OUTPUT,
48 VENC_BUFFER_TYPE_QDSP6,
49 VENC_BUFFER_TYPE_HDR
50};
51enum {
52 VENC_DALRPC_GET_SYNTAX_HEADER = DAL_OP_FIRST_DEVICE_API,
53 VENC_DALRPC_UPDATE_INTRA_REFRESH,
54 VENC_DALRPC_UPDATE_FRAME_RATE,
55 VENC_DALRPC_UPDATE_BITRATE,
56 VENC_DALRPC_UPDATE_QP_RANGE,
57 VENC_DALRPC_UPDATE_INTRA_PERIOD,
58 VENC_DALRPC_REQUEST_IFRAME,
59 VENC_DALRPC_START,
60 VENC_DALRPC_STOP,
61 VENC_DALRPC_SUSPEND,
62 VENC_DALRPC_RESUME,
63 VENC_DALRPC_FLUSH,
64 VENC_DALRPC_QUEUE_INPUT,
65 VENC_DALRPC_QUEUE_OUTPUT
66};
67struct venc_input_payload {
68 u32 data;
69};
70struct venc_output_payload {
71 u32 size;
72 long long time_stamp;
73 u32 flags;
74 u32 data;
75 u32 client_data_from_input;
76};
77union venc_payload {
78 struct venc_input_payload input_payload;
79 struct venc_output_payload output_payload;
80};
81struct venc_msg_type {
82 u32 event;
83 u32 status;
84 union venc_payload payload;
85};
86struct venc_input_buf {
87 struct venc_buf_type yuv_buf;
88 u32 data_size;
89 long long time_stamp;
90 u32 flags;
91 u32 dvs_offsetx;
92 u32 dvs_offsety;
93 u32 client_data;
94 u32 op_client_data;
95};
96struct venc_output_buf {
97 struct venc_buf_type bit_stream_buf;
98 u32 client_data;
99};
100
101struct venc_msg_list {
102 struct list_head list;
103 struct venc_msg msg_data;
104};
105struct venc_buf {
106 int fd;
107 u32 src;
108 u32 offset;
109 u32 size;
110 u32 btype;
111 unsigned long paddr;
112 struct file *file;
113};
114struct venc_pmem_list {
115 struct list_head list;
116 struct venc_buf buf;
117};
118struct venc_dev {
119 bool is_active;
120 bool pmem_freed;
121 enum venc_state_type state;
122 struct list_head venc_msg_list_head;
123 struct list_head venc_msg_list_free;
124 spinlock_t venc_msg_list_lock;
125 struct list_head venc_pmem_list_head;
126 spinlock_t venc_pmem_list_lock;
127 struct dal_client *q6_handle;
128 wait_queue_head_t venc_msg_evt;
129 struct device *class_devp;
130};
131
132#define DEBUG_VENC 0
133#if DEBUG_VENC
134#define TRACE(fmt, x...) \
135 do { pr_debug("%s:%d " fmt, __func__, __LINE__, ##x); } while (0)
136#else
137#define TRACE(fmt, x...) do { } while (0)
138#endif
139
140static struct cdev cdev;
141static dev_t venc_dev_num;
142static struct class *venc_class;
143static struct venc_dev *venc_device_p;
144static int venc_ref;
145
146static DEFINE_MUTEX(idlecount_lock);
147static int idlecount;
148static struct wake_lock wakelock;
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700149static struct pm_qos_request pm_qos_req;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700150
151static void prevent_sleep(void)
152{
153 mutex_lock(&idlecount_lock);
154 if (++idlecount == 1) {
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700155 pm_qos_update_request(&pm_qos_req,
156 msm_cpuidle_get_deep_idle_latency());
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157 wake_lock(&wakelock);
158 }
159 mutex_unlock(&idlecount_lock);
160}
161
162static void allow_sleep(void)
163{
164 mutex_lock(&idlecount_lock);
165 if (--idlecount == 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 wake_unlock(&wakelock);
Stephen Boyd2fcabf92012-05-30 10:41:11 -0700167 pm_qos_update_request(&pm_qos_req, PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700168 }
169 mutex_unlock(&idlecount_lock);
170}
171
172static inline int venc_check_version(u32 client, u32 server)
173{
174 int ret = -EINVAL;
175
176 if ((VENC_GET_MAJOR_VERSION(client) == VENC_GET_MAJOR_VERSION(server))
177 && (VENC_GET_MINOR_VERSION(client) <=
178 VENC_GET_MINOR_VERSION(server)))
179 ret = 0;
180
181 return ret;
182}
183
184static int venc_get_msg(struct venc_dev *dvenc, void *msg)
185{
186 struct venc_msg_list *l;
187 unsigned long flags;
188 int ret = 0;
189 struct venc_msg qdsp_msg;
190
191 if (!dvenc->is_active)
192 return -EPERM;
193 spin_lock_irqsave(&dvenc->venc_msg_list_lock, flags);
194 list_for_each_entry_reverse(l, &dvenc->venc_msg_list_head, list) {
195 memcpy(&qdsp_msg, &l->msg_data, sizeof(struct venc_msg));
196 list_del(&l->list);
197 list_add(&l->list, &dvenc->venc_msg_list_free);
198 ret = 1;
199 break;
200 }
201 spin_unlock_irqrestore(&dvenc->venc_msg_list_lock, flags);
202 if (copy_to_user(msg, &qdsp_msg, sizeof(struct venc_msg)))
203 pr_err("%s failed to copy_to_user\n", __func__);
204 return ret;
205}
206
207static void venc_put_msg(struct venc_dev *dvenc, struct venc_msg *msg)
208{
209 struct venc_msg_list *l;
210 unsigned long flags;
211 int found = 0;
212
213 spin_lock_irqsave(&dvenc->venc_msg_list_lock, flags);
214 list_for_each_entry(l, &dvenc->venc_msg_list_free, list) {
215 memcpy(&l->msg_data, msg, sizeof(struct venc_msg));
216 list_del(&l->list);
217 list_add(&l->list, &dvenc->venc_msg_list_head);
218 found = 1;
219 break;
220 }
221 spin_unlock_irqrestore(&dvenc->venc_msg_list_lock, flags);
222 if (found)
223 wake_up(&dvenc->venc_msg_evt);
224 else
225 pr_err("%s: failed to find a free node\n", __func__);
226
227}
228
229static struct venc_pmem_list *venc_add_pmem_to_list(struct venc_dev *dvenc,
230 struct venc_pmem *mptr,
231 u32 btype)
232{
233 int ret = 0;
234 unsigned long flags;
235 unsigned long len;
236 unsigned long vaddr;
237 struct venc_pmem_list *plist = NULL;
238
239 plist = kzalloc(sizeof(struct venc_pmem_list), GFP_KERNEL);
240 if (!plist) {
241 pr_err("%s: kzalloc failed\n", __func__);
242 return NULL;
243 }
244
245 ret = get_pmem_file(mptr->fd, &(plist->buf.paddr),
246 &vaddr, &len, &(plist->buf.file));
247 if (ret) {
248 pr_err("%s: get_pmem_file failed for fd=%d offset=%d\n",
249 __func__, mptr->fd, mptr->offset);
250 goto err_venc_add_pmem;
251 } else if (mptr->offset >= len) {
252 pr_err("%s: invalid offset (%d > %ld) for fd=%d\n",
253 __func__, mptr->offset, len, mptr->fd);
254 ret = -EINVAL;
255 goto err_venc_get_pmem;
256 }
257
258 plist->buf.fd = mptr->fd;
259 plist->buf.paddr += mptr->offset;
260 plist->buf.size = mptr->size;
261 plist->buf.btype = btype;
262 plist->buf.offset = mptr->offset;
263 plist->buf.src = mptr->src;
264
265 spin_lock_irqsave(&dvenc->venc_pmem_list_lock, flags);
266 list_add(&plist->list, &dvenc->venc_pmem_list_head);
267 spin_unlock_irqrestore(&dvenc->venc_pmem_list_lock, flags);
268 return plist;
269
270err_venc_get_pmem:
271 put_pmem_file(plist->buf.file);
272err_venc_add_pmem:
273 kfree(plist);
274 return NULL;
275}
276
277static struct venc_pmem_list *venc_get_pmem_from_list(
278 struct venc_dev *dvenc, u32 pmem_fd,
279 u32 offset, u32 btype)
280{
281 struct venc_pmem_list *plist;
282 unsigned long flags;
283 struct file *file;
284 int found = 0;
285
286 file = fget(pmem_fd);
287 if (!file) {
288 pr_err("%s: invalid encoder buffer fd(%d)\n", __func__,
289 pmem_fd);
290 return NULL;
291 }
292 spin_lock_irqsave(&dvenc->venc_pmem_list_lock, flags);
293 list_for_each_entry(plist, &dvenc->venc_pmem_list_head, list) {
294 if (plist->buf.btype == btype && plist->buf.file == file &&
295 plist->buf.offset == offset) {
296 found = 1;
297 break;
298 }
299 }
300 spin_unlock_irqrestore(&dvenc->venc_pmem_list_lock, flags);
301 fput(file);
302 if (found)
303 return plist;
304
305 else
306 return NULL;
307}
308
309static int venc_set_buffer(struct venc_dev *dvenc, void *argp,
310 u32 btype)
311{
312 struct venc_pmem pmem;
313 struct venc_pmem_list *plist;
314 int ret = 0;
315
316 ret = copy_from_user(&pmem, argp, sizeof(pmem));
317 if (ret) {
318 pr_err("%s: copy_from_user failed\n", __func__);
319 return ret;
320 }
321 plist = venc_add_pmem_to_list(dvenc, &pmem, btype);
322 if (plist == NULL) {
323 pr_err("%s: buffer add_to_pmem_list failed\n",
324 __func__);
325 return -EPERM;
326 }
327 return ret;
328}
329
330static int venc_assign_q6_buffers(struct venc_dev *dvenc,
331 struct venc_buffers *pbufs,
332 struct venc_nonio_buf_config *pcfg)
333{
334 int ret = 0;
335 struct venc_pmem_list *plist;
336
337 plist = venc_add_pmem_to_list(dvenc, &(pbufs->recon_buf[0]),
338 VENC_BUFFER_TYPE_QDSP6);
339 if (plist == NULL) {
340 pr_err("%s: recon_buf0 failed to add_to_pmem_list\n",
341 __func__);
342 return -EPERM;
343 }
344 pcfg->recon_buf1.region = pbufs->recon_buf[0].src;
345 pcfg->recon_buf1.phys = plist->buf.paddr;
346 pcfg->recon_buf1.size = plist->buf.size;
347 pcfg->recon_buf1.offset = 0;
348
349 plist = venc_add_pmem_to_list(dvenc, &(pbufs->recon_buf[1]),
350 VENC_BUFFER_TYPE_QDSP6);
351 if (plist == NULL) {
352 pr_err("%s: recons_buf1 failed to add_to_pmem_list\n",
353 __func__);
354 return -EPERM;
355 }
356 pcfg->recon_buf2.region = pbufs->recon_buf[1].src;
357 pcfg->recon_buf2.phys = plist->buf.paddr;
358 pcfg->recon_buf2.size = plist->buf.size;
359 pcfg->recon_buf2.offset = 0;
360
361 plist = venc_add_pmem_to_list(dvenc, &(pbufs->wb_buf),
362 VENC_BUFFER_TYPE_QDSP6);
363 if (plist == NULL) {
364 pr_err("%s: wb_buf failed to add_to_pmem_list\n",
365 __func__);
366 return -EPERM;
367 }
368 pcfg->wb_buf.region = pbufs->wb_buf.src;
369 pcfg->wb_buf.phys = plist->buf.paddr;
370 pcfg->wb_buf.size = plist->buf.size;
371 pcfg->wb_buf.offset = 0;
372
373 plist = venc_add_pmem_to_list(dvenc, &(pbufs->cmd_buf),
374 VENC_BUFFER_TYPE_QDSP6);
375 if (plist == NULL) {
376 pr_err("%s: cmd_buf failed to add_to_pmem_list\n",
377 __func__);
378 return -EPERM;
379 }
380 pcfg->cmd_buf.region = pbufs->cmd_buf.src;
381 pcfg->cmd_buf.phys = plist->buf.paddr;
382 pcfg->cmd_buf.size = plist->buf.size;
383 pcfg->cmd_buf.offset = 0;
384
385 plist = venc_add_pmem_to_list(dvenc, &(pbufs->vlc_buf),
386 VENC_BUFFER_TYPE_QDSP6);
387 if (plist == NULL) {
388 pr_err("%s: vlc_buf failed to add_to_pmem_list"
389 " failed\n", __func__);
390 return -EPERM;
391 }
392 pcfg->vlc_buf.region = pbufs->vlc_buf.src;
393 pcfg->vlc_buf.phys = plist->buf.paddr;
394 pcfg->vlc_buf.size = plist->buf.size;
395 pcfg->vlc_buf.offset = 0;
396
397 return ret;
398}
399
400static int venc_start(struct venc_dev *dvenc, void *argp)
401{
402 int ret = 0;
403 struct venc_q6_config q6_config;
404 struct venc_init_config vconfig;
405
406 dvenc->state = VENC_STATE_START;
407 ret = copy_from_user(&vconfig, argp, sizeof(struct venc_init_config));
408 if (ret) {
409 pr_err("%s: copy_from_user failed\n", __func__);
410 return ret;
411 }
412 memcpy(&q6_config, &(vconfig.q6_config), sizeof(q6_config));
413 ret = venc_assign_q6_buffers(dvenc, &(vconfig.q6_bufs),
414 &(q6_config.buf_params));
415 if (ret != 0) {
416 pr_err("%s: assign_q6_buffers failed\n", __func__);
417 return -EPERM;
418 }
419
420 q6_config.callback_event = dvenc->q6_handle;
421 TRACE("%s: parameters: handle:%p, config:%p, callback:%p \n", __func__,
422 dvenc->q6_handle, &q6_config, q6_config.callback_event);
423 TRACE("%s: parameters:recon1:0x%x, recon2:0x%x,"
424 " wb_buf:0x%x, cmd:0x%x, vlc:0x%x\n", __func__,
425 q6_config.buf_params.recon_buf1.phys,
426 q6_config.buf_params.recon_buf2.phys,
427 q6_config.buf_params.wb_buf.phys,
428 q6_config.buf_params.cmd_buf.phys,
429 q6_config.buf_params.vlc_buf.phys);
430 TRACE("%s: size of param:%d \n", __func__, sizeof(q6_config));
431 ret = dal_call_f5(dvenc->q6_handle, VENC_DALRPC_START, &q6_config,
432 sizeof(q6_config));
433 if (ret != 0) {
434 pr_err("%s: remote function failed (%d)\n", __func__, ret);
435 return ret;
436 }
437 return ret;
438}
439
440static int venc_encode_frame(struct venc_dev *dvenc, void *argp)
441{
442 int ret = 0;
443 struct venc_pmem buf;
444 struct venc_input_buf q6_input;
445 struct venc_pmem_list *plist;
446 struct venc_buffer input;
447
448 ret = copy_from_user(&input, argp, sizeof(struct venc_buffer));
449 if (ret) {
450 pr_err("%s: copy_from_user failed\n", __func__);
451 return ret;
452 }
453 ret = copy_from_user(&buf,
454 ((struct venc_buffer *)argp)->ptr_buffer,
455 sizeof(struct venc_pmem));
456 if (ret) {
457 pr_err("%s: copy_from_user failed\n", __func__);
458 return ret;
459 }
460
461 plist = venc_get_pmem_from_list(dvenc, buf.fd, buf.offset,
462 VENC_BUFFER_TYPE_INPUT);
463 if (NULL == plist) {
464 plist = venc_add_pmem_to_list(dvenc, &buf,
465 VENC_BUFFER_TYPE_INPUT);
466 if (plist == NULL) {
467 pr_err("%s: buffer add_to_pmem_list failed\n",
468 __func__);
469 return -EPERM;
470 }
471 }
472
473 q6_input.flags = 0;
474 if (input.flags & VENC_FLAG_EOS)
475 q6_input.flags |= 0x00000001;
476 q6_input.yuv_buf.region = plist->buf.src;
477 q6_input.yuv_buf.phys = plist->buf.paddr;
478 q6_input.yuv_buf.size = plist->buf.size;
479 q6_input.yuv_buf.offset = 0;
480 q6_input.data_size = plist->buf.size;
481 q6_input.client_data = (u32)input.client_data;
482 q6_input.time_stamp = input.time_stamp;
483 q6_input.dvs_offsetx = 0;
484 q6_input.dvs_offsety = 0;
485
486 TRACE("Pushing down input phys=0x%x fd= %d, client_data: 0x%x,"
487 " time_stamp:%lld \n", q6_input.yuv_buf.phys, plist->buf.fd,
488 input.client_data, input.time_stamp);
489 ret = dal_call_f5(dvenc->q6_handle, VENC_DALRPC_QUEUE_INPUT,
490 &q6_input, sizeof(q6_input));
491
492 if (ret != 0)
493 pr_err("%s: Q6 queue_input failed (%d)\n", __func__,
494 (int)ret);
495 return ret;
496}
497
498static int venc_fill_output(struct venc_dev *dvenc, void *argp)
499{
500 int ret = 0;
501 struct venc_pmem buf;
502 struct venc_output_buf q6_output;
503 struct venc_pmem_list *plist;
504 struct venc_buffer output;
505
506 ret = copy_from_user(&output, argp, sizeof(struct venc_buffer));
507 if (ret) {
508 pr_err("%s: copy_from_user failed\n", __func__);
509 return ret;
510 }
511 ret = copy_from_user(&buf,
512 ((struct venc_buffer *)argp)->ptr_buffer,
513 sizeof(struct venc_pmem));
514 if (ret) {
515 pr_err("%s: copy_from_user failed\n", __func__);
516 return ret;
517 }
518 plist = venc_get_pmem_from_list(dvenc, buf.fd, buf.offset,
519 VENC_BUFFER_TYPE_OUTPUT);
520 if (NULL == plist) {
521 plist = venc_add_pmem_to_list(dvenc, &buf,
522 VENC_BUFFER_TYPE_OUTPUT);
523 if (NULL == plist) {
524 pr_err("%s: output buffer failed to add_to_pmem_list"
525 "\n", __func__);
526 return -EPERM;
527 }
528 }
529 q6_output.bit_stream_buf.region = plist->buf.src;
530 q6_output.bit_stream_buf.phys = (u32)plist->buf.paddr;
531 q6_output.bit_stream_buf.size = plist->buf.size;
532 q6_output.bit_stream_buf.offset = 0;
533 q6_output.client_data = (u32)output.client_data;
534 ret =
535 dal_call_f5(dvenc->q6_handle, VENC_DALRPC_QUEUE_OUTPUT, &q6_output,
536 sizeof(q6_output));
537 if (ret != 0)
538 pr_err("%s: remote function failed (%d)\n", __func__, ret);
539 return ret;
540}
541
542static int venc_stop(struct venc_dev *dvenc)
543{
544 int ret = 0;
545 struct venc_msg msg;
546
547 ret = dal_call_f0(dvenc->q6_handle, VENC_DALRPC_STOP, 1);
548 if (ret) {
549 pr_err("%s: remote runction failed (%d)\n", __func__, ret);
550 msg.msg_code = VENC_MSG_STOP;
551 msg.msg_data_size = 0;
552 msg.status_code = VENC_S_EFAIL;
553 venc_put_msg(dvenc, &msg);
554 }
555 return ret;
556}
557
558static int venc_pause(struct venc_dev *dvenc)
559{
560 int ret = 0;
561 struct venc_msg msg;
562
563 ret = dal_call_f0(dvenc->q6_handle, VENC_DALRPC_SUSPEND, 1);
564 if (ret) {
565 pr_err("%s: remote function failed (%d)\n", __func__, ret);
566 msg.msg_code = VENC_MSG_PAUSE;
567 msg.status_code = VENC_S_EFAIL;
568 msg.msg_data_size = 0;
569 venc_put_msg(dvenc, &msg);
570 }
571 return ret;
572}
573
574static int venc_resume(struct venc_dev *dvenc)
575{
576 int ret = 0;
577 struct venc_msg msg;
578
579 ret = dal_call_f0(dvenc->q6_handle, VENC_DALRPC_RESUME, 1);
580 if (ret) {
581 pr_err("%s: remote function failed (%d)\n", __func__, ret);
582 msg.msg_code = VENC_MSG_RESUME;
583 msg.msg_data_size = 0;
584 msg.status_code = VENC_S_EFAIL;
585 venc_put_msg(dvenc, &msg);
586 }
587 return ret;
588}
589
590static int venc_flush(struct venc_dev *dvenc, void *argp)
591{
592 int ret = 0;
593 struct venc_msg msg;
594 union venc_msg_data smsg;
595 int status = VENC_S_SUCCESS;
596 struct venc_buffer_flush flush;
597
598 if (copy_from_user(&flush, argp, sizeof(struct venc_buffer_flush)))
599 return -EFAULT;
600 if (flush.flush_mode == VENC_FLUSH_ALL) {
601 ret = dal_call_f0(dvenc->q6_handle, VENC_DALRPC_FLUSH, 1);
602 if (ret)
603 status = VENC_S_EFAIL;
604 } else
605 status = VENC_S_ENOTSUPP;
606
607 if (status != VENC_S_SUCCESS) {
608 if ((flush.flush_mode == VENC_FLUSH_INPUT) ||
609 (flush.flush_mode == VENC_FLUSH_ALL)) {
610 smsg.flush_ret.flush_mode = VENC_FLUSH_INPUT;
611 msg.msg_data = smsg;
612 msg.status_code = status;
613 msg.msg_code = VENC_MSG_FLUSH;
614 msg.msg_data_size = sizeof(union venc_msg_data);
615 venc_put_msg(dvenc, &msg);
616 }
617 if (flush.flush_mode == VENC_FLUSH_OUTPUT ||
618 (flush.flush_mode == VENC_FLUSH_ALL)) {
619 smsg.flush_ret.flush_mode = VENC_FLUSH_OUTPUT;
620 msg.msg_data = smsg;
621 msg.status_code = status;
622 msg.msg_code = VENC_MSG_FLUSH;
623 msg.msg_data_size = sizeof(union venc_msg_data);
624 venc_put_msg(dvenc, &msg);
625 }
626 return -EIO;
627 }
628 return ret;
629}
630
631static int venc_get_sequence_hdr(struct venc_dev *dvenc, void *argp)
632{
633 pr_err("%s not supported\n", __func__);
634 return -EIO;
635}
636
637static int venc_set_qp_range(struct venc_dev *dvenc, void *argp)
638{
639 int ret = 0;
640 struct venc_qp_range qp;
641
642 ret = copy_from_user(&qp, argp, sizeof(struct venc_qp_range));
643 if (ret) {
644 pr_err("%s: copy_from_user failed\n", __func__);
645 return ret;
646 }
647
648 if (dvenc->state == VENC_STATE_START ||
649 dvenc->state == VENC_STATE_PAUSE) {
650 ret =
651 dal_call_f5(dvenc->q6_handle, VENC_DALRPC_UPDATE_QP_RANGE,
652 &qp, sizeof(struct venc_qp_range));
653 if (ret) {
654 pr_err("%s: remote function failed (%d) \n", __func__,
655 ret);
656 return ret;
657 }
658 }
659 return ret;
660}
661
662static int venc_set_intra_period(struct venc_dev *dvenc, void *argp)
663{
664 int ret = 0;
665 u32 pnum = 0;
666
667 ret = copy_from_user(&pnum, argp, sizeof(int));
668 if (ret) {
669 pr_err("%s: copy_from_user failed\n", __func__);
670 return ret;
671 }
672 if (dvenc->state == VENC_STATE_START ||
673 dvenc->state == VENC_STATE_PAUSE) {
674 ret = dal_call_f0(dvenc->q6_handle,
675 VENC_DALRPC_UPDATE_INTRA_PERIOD, pnum);
676 if (ret)
677 pr_err("%s: remote function failed (%d)\n", __func__,
678 ret);
679 }
680 return ret;
681}
682
683static int venc_set_intra_refresh(struct venc_dev *dvenc, void *argp)
684{
685 int ret = 0;
686 u32 mb_num = 0;
687
688 ret = copy_from_user(&mb_num, argp, sizeof(int));
689 if (ret) {
690 pr_err("%s: copy_from_user failed\n", __func__);
691 return ret;
692 }
693 if (dvenc->state == VENC_STATE_START ||
694 dvenc->state == VENC_STATE_PAUSE) {
695 ret = dal_call_f0(dvenc->q6_handle,
696 VENC_DALRPC_UPDATE_INTRA_REFRESH, mb_num);
697 if (ret)
698 pr_err("%s: remote function failed (%d)\n", __func__,
699 ret);
700 }
701 return ret;
702}
703
704static int venc_set_frame_rate(struct venc_dev *dvenc, void *argp)
705{
706 int ret = 0;
707 struct venc_frame_rate pdata;
708 ret = copy_from_user(&pdata, argp, sizeof(struct venc_frame_rate));
709 if (ret) {
710 pr_err("%s: copy_from_user failed\n", __func__);
711 return ret;
712 }
713 if (dvenc->state == VENC_STATE_START ||
714 dvenc->state == VENC_STATE_PAUSE) {
715 ret = dal_call_f5(dvenc->q6_handle,
716 VENC_DALRPC_UPDATE_FRAME_RATE,
717 (void *)&(pdata),
718 sizeof(struct venc_frame_rate));
719 if (ret)
720 pr_err("%s: remote function failed (%d)\n", __func__,
721 ret);
722 }
723 return ret;
724}
725
726static int venc_set_target_bitrate(struct venc_dev *dvenc, void *argp)
727{
728 int ret = 0;
729 u32 pdata = 0;
730
731 ret = copy_from_user(&pdata, argp, sizeof(int));
732 if (ret) {
733 pr_err("%s: copy_from_user failed\n", __func__);
734 return ret;
735 }
736 if (dvenc->state == VENC_STATE_START ||
737 dvenc->state == VENC_STATE_PAUSE) {
738 ret = dal_call_f0(dvenc->q6_handle,
739 VENC_DALRPC_UPDATE_BITRATE, pdata);
740 if (ret)
741 pr_err("%s: remote function failed (%d)\n", __func__,
742 ret);
743 }
744 return ret;
745}
746
747static int venc_request_iframe(struct venc_dev *dvenc)
748{
749 int ret = 0;
750
751 if (dvenc->state != VENC_STATE_START)
752 return -EINVAL;
753
754 ret = dal_call_f0(dvenc->q6_handle, VENC_DALRPC_REQUEST_IFRAME, 1);
755 if (ret)
756 pr_err("%s: remote function failed (%d)\n", __func__, ret);
757 return ret;
758}
759
760static int venc_stop_read_msg(struct venc_dev *dvenc)
761{
762 struct venc_msg msg;
763 int ret = 0;
764
765 msg.status_code = 0;
766 msg.msg_code = VENC_MSG_STOP_READING_MSG;
767 msg.msg_data_size = 0;
768 venc_put_msg(dvenc, &msg);
769 return ret;
770}
771
772static int venc_q6_stop(struct venc_dev *dvenc)
773{
774 int ret = 0;
775 struct venc_pmem_list *plist;
776 unsigned long flags;
777
778 wake_up(&dvenc->venc_msg_evt);
779 spin_lock_irqsave(&dvenc->venc_pmem_list_lock, flags);
780 if (!dvenc->pmem_freed) {
781 list_for_each_entry(plist, &dvenc->venc_pmem_list_head, list)
782 put_pmem_file(plist->buf.file);
783 dvenc->pmem_freed = 1;
784 }
785 spin_unlock_irqrestore(&dvenc->venc_pmem_list_lock, flags);
786
787 dvenc->state = VENC_STATE_STOP;
788 return ret;
789}
790
791static int venc_translate_error(enum venc_status_code q6_status)
792{
793 int ret = 0;
794
795 switch (q6_status) {
796 case VENC_STATUS_SUCCESS:
797 ret = VENC_S_SUCCESS;
798 break;
799 case VENC_STATUS_ERROR:
800 ret = VENC_S_EFAIL;
801 break;
802 case VENC_STATUS_INVALID_STATE:
803 ret = VENC_S_EINVALSTATE;
804 break;
805 case VENC_STATUS_FLUSHING:
806 ret = VENC_S_EFLUSHED;
807 break;
808 case VENC_STATUS_INVALID_PARAM:
809 ret = VENC_S_EBADPARAM;
810 break;
811 case VENC_STATUS_CMD_QUEUE_FULL:
812 ret = VENC_S_ECMDQFULL;
813 break;
814 case VENC_STATUS_CRITICAL:
815 ret = VENC_S_EFATAL;
816 break;
817 case VENC_STATUS_INSUFFICIENT_RESOURCES:
818 ret = VENC_S_ENOHWRES;
819 break;
820 case VENC_STATUS_TIMEOUT:
821 ret = VENC_S_ETIMEOUT;
822 break;
823 }
824 if (q6_status != VENC_STATUS_SUCCESS)
825 pr_err("%s: Q6 failed (%d)", __func__, (int)q6_status);
826 return ret;
827}
828
829static void venc_q6_callback(void *data, int len, void *cookie)
830{
831 int status = 0;
832 struct venc_dev *dvenc = (struct venc_dev *)cookie;
833 struct venc_msg_type *q6_msg = NULL;
834 struct venc_msg msg, msg1;
835 union venc_msg_data smsg1, smsg2;
836 unsigned long msg_code = 0;
837 struct venc_input_payload *pload1;
838 struct venc_output_payload *pload2;
839 uint32_t * tmp = (uint32_t *) data;
840
841 if (dvenc == NULL) {
842 pr_err("%s: empty driver parameter\n", __func__);
843 return;
844 }
845 if (tmp[2] == sizeof(struct venc_msg_type)) {
846 q6_msg = (struct venc_msg_type *)&tmp[3];
847 } else {
848 pr_err("%s: callback with empty message (%d, %d)\n",
849 __func__, tmp[2], sizeof(struct venc_msg_type));
850 return;
851 }
852 msg.msg_data_size = 0;
853 status = venc_translate_error(q6_msg->status);
854 switch ((enum venc_event_type_enum)q6_msg->event) {
855 case VENC_EVENT_START_STATUS:
856 dvenc->state = VENC_STATE_START;
857 msg_code = VENC_MSG_START;
858 break;
859 case VENC_EVENT_STOP_STATUS:
860 venc_q6_stop(dvenc);
861 msg_code = VENC_MSG_STOP;
862 break;
863 case VENC_EVENT_SUSPEND_STATUS:
864 dvenc->state = VENC_STATE_PAUSE;
865 msg_code = VENC_MSG_PAUSE;
866 break;
867 case VENC_EVENT_RESUME_STATUS:
868 dvenc->state = VENC_STATE_START;
869 msg_code = VENC_MSG_RESUME;
870 break;
871 case VENC_EVENT_FLUSH_STATUS:
872 smsg1.flush_ret.flush_mode = VENC_FLUSH_INPUT;
873 msg1.status_code = status;
874 msg1.msg_code = VENC_MSG_FLUSH;
875 msg1.msg_data = smsg1;
876 msg1.msg_data_size = sizeof(union venc_msg_data);
877 venc_put_msg(dvenc, &msg1);
878 smsg2.flush_ret.flush_mode = VENC_FLUSH_OUTPUT;
879 msg_code = VENC_MSG_FLUSH;
880 msg.msg_data = smsg2;
881 msg.msg_data_size = sizeof(union venc_msg_data);
882 break;
883 case VENC_EVENT_RELEASE_INPUT:
884 pload1 = &((q6_msg->payload).input_payload);
885 TRACE("Release_input: data: 0x%x \n", pload1->data);
886 if (pload1 != NULL) {
887 msg.msg_data.buf.client_data = pload1->data;
888 msg_code = VENC_MSG_INPUT_BUFFER_DONE;
889 msg.msg_data_size = sizeof(union venc_msg_data);
890 }
891 break;
892 case VENC_EVENT_DELIVER_OUTPUT:
893 pload2 = &((q6_msg->payload).output_payload);
894 smsg1.buf.flags = 0;
895 if (pload2->flags & VENC_FLAG_SYNC_FRAME)
896 smsg1.buf.flags |= VENC_FLAG_SYNC_FRAME;
897 if (pload2->flags & VENC_FLAG_CODEC_CONFIG)
898 smsg1.buf.flags |= VENC_FLAG_CODEC_CONFIG;
899 if (pload2->flags & VENC_FLAG_END_OF_FRAME)
900 smsg1.buf.flags |= VENC_FLAG_END_OF_FRAME;
901 if (pload2->flags & VENC_FLAG_EOS)
902 smsg1.buf.flags |= VENC_FLAG_EOS;
903 smsg1.buf.len = pload2->size;
904 smsg1.buf.offset = 0;
905 smsg1.buf.time_stamp = pload2->time_stamp;
906 smsg1.buf.client_data = pload2->data;
907 msg_code = VENC_MSG_OUTPUT_BUFFER_DONE;
908 msg.msg_data = smsg1;
909 msg.msg_data_size = sizeof(union venc_msg_data);
910 break;
911 default:
912 pr_err("%s: invalid response from Q6 (%d)\n", __func__,
913 (int)q6_msg->event);
914 return;
915 }
916 msg.status_code = status;
917 msg.msg_code = msg_code;
918 venc_put_msg(dvenc, &msg);
919 return;
920}
921
922static int venc_get_version(struct venc_dev *dvenc, void *argp)
923{
924 struct venc_version ver_info;
925 int ret = 0;
926
927 ver_info.major = VENC_GET_MAJOR_VERSION(VENC_INTERFACE_VERSION);
928 ver_info.minor = VENC_GET_MINOR_VERSION(VENC_INTERFACE_VERSION);
929
930 ret = copy_to_user(((struct venc_version *)argp),
931 &ver_info, sizeof(ver_info));
932 if (ret)
933 pr_err("%s failed to copy_to_user\n", __func__);
934
935 return ret;
936
937}
938
939static long q6venc_ioctl(struct file *file, u32 cmd,
940 unsigned long arg)
941{
942 long ret = 0;
943 void __user *argp = (void __user *)arg;
944 struct venc_dev *dvenc = file->private_data;
945
946 if (!dvenc || !dvenc->is_active)
947 return -EPERM;
948
949 switch (cmd) {
950 case VENC_IOCTL_SET_INPUT_BUFFER:
951 ret = venc_set_buffer(dvenc, argp, VENC_BUFFER_TYPE_INPUT);
952 break;
953 case VENC_IOCTL_SET_OUTPUT_BUFFER:
954 ret = venc_set_buffer(dvenc, argp, VENC_BUFFER_TYPE_OUTPUT);
955 break;
956 case VENC_IOCTL_GET_SEQUENCE_HDR:
957 ret = venc_get_sequence_hdr(dvenc, argp);
958 break;
959 case VENC_IOCTL_SET_QP_RANGE:
960 ret = venc_set_qp_range(dvenc, argp);
961 break;
962 case VENC_IOCTL_SET_INTRA_PERIOD:
963 ret = venc_set_intra_period(dvenc, argp);
964 break;
965 case VENC_IOCTL_SET_INTRA_REFRESH:
966 ret = venc_set_intra_refresh(dvenc, argp);
967 break;
968 case VENC_IOCTL_SET_FRAME_RATE:
969 ret = venc_set_frame_rate(dvenc, argp);
970 break;
971 case VENC_IOCTL_SET_TARGET_BITRATE:
972 ret = venc_set_target_bitrate(dvenc, argp);
973 break;
974 case VENC_IOCTL_CMD_REQUEST_IFRAME:
975 if (dvenc->state == VENC_STATE_START)
976 ret = venc_request_iframe(dvenc);
977 break;
978 case VENC_IOCTL_CMD_START:
979 ret = venc_start(dvenc, argp);
980 break;
981 case VENC_IOCTL_CMD_STOP:
982 ret = venc_stop(dvenc);
983 break;
984 case VENC_IOCTL_CMD_PAUSE:
985 ret = venc_pause(dvenc);
986 break;
987 case VENC_IOCTL_CMD_RESUME:
988 ret = venc_resume(dvenc);
989 break;
990 case VENC_IOCTL_CMD_ENCODE_FRAME:
991 ret = venc_encode_frame(dvenc, argp);
992 break;
993 case VENC_IOCTL_CMD_FILL_OUTPUT_BUFFER:
994 ret = venc_fill_output(dvenc, argp);
995 break;
996 case VENC_IOCTL_CMD_FLUSH:
997 ret = venc_flush(dvenc, argp);
998 break;
999 case VENC_IOCTL_CMD_READ_NEXT_MSG:
1000 wait_event_interruptible(dvenc->venc_msg_evt,
1001 venc_get_msg(dvenc, argp));
1002 break;
1003 case VENC_IOCTL_CMD_STOP_READ_MSG:
1004 ret = venc_stop_read_msg(dvenc);
1005 break;
1006 case VENC_IOCTL_GET_VERSION:
1007 ret = venc_get_version(dvenc, argp);
1008 break;
1009 default:
1010 pr_err("%s: invalid ioctl code (%d)\n", __func__, cmd);
1011 ret = -ENOTTY;
1012 break;
1013 }
1014 return ret;
1015}
1016
1017static int q6venc_open(struct inode *inode, struct file *file)
1018{
1019 int i;
1020 int ret = 0;
1021 struct venc_dev *dvenc;
1022 struct venc_msg_list *plist, *tmp;
1023 struct dal_info version_info;
1024
1025 dvenc = kzalloc(sizeof(struct venc_dev), GFP_KERNEL);
1026 if (!dvenc) {
1027 pr_err("%s: unable to allocate memory for struct venc_dev\n",
1028 __func__);
1029 return -ENOMEM;
1030 }
1031 file->private_data = dvenc;
1032 INIT_LIST_HEAD(&dvenc->venc_msg_list_head);
1033 INIT_LIST_HEAD(&dvenc->venc_msg_list_free);
1034 INIT_LIST_HEAD(&dvenc->venc_pmem_list_head);
1035 init_waitqueue_head(&dvenc->venc_msg_evt);
1036 spin_lock_init(&dvenc->venc_msg_list_lock);
1037 spin_lock_init(&dvenc->venc_pmem_list_lock);
1038 venc_ref++;
1039 for (i = 0; i < VENC_MSG_MAX; i++) {
1040 plist = kzalloc(sizeof(struct venc_msg_list), GFP_KERNEL);
1041 if (!plist) {
1042 pr_err("%s: kzalloc failed\n", __func__);
1043 ret = -ENOMEM;
1044 goto err_venc_create_msg_list;
1045 }
1046 list_add(&plist->list, &dvenc->venc_msg_list_free);
1047 }
1048 dvenc->q6_handle =
1049 dal_attach(DALDEVICEID_VENC_DEVICE, DALDEVICEID_VENC_PORTNAME, 1,
1050 venc_q6_callback, (void *)dvenc);
1051 if (!(dvenc->q6_handle)) {
1052 pr_err("%s: daldevice_attach failed (%d)\n", __func__, ret);
1053 goto err_venc_dal_attach;
1054 }
1055 ret = dal_call_f9(dvenc->q6_handle, DAL_OP_INFO, &version_info,
1056 sizeof(struct dal_info));
1057 if (ret) {
1058 pr_err("%s: failed to get version\n", __func__);
1059 goto err_venc_dal_open;
1060 }
1061 if (venc_check_version(VENC_INTERFACE_VERSION, version_info.version)) {
1062 pr_err("%s: driver version mismatch\n", __func__);
1063 goto err_venc_dal_open;
1064 }
1065 ret = dal_call_f0(dvenc->q6_handle, DAL_OP_OPEN, 1);
1066 if (ret) {
1067 pr_err("%s: dal_call_open failed (%d)\n", __func__, ret);
1068 goto err_venc_dal_open;
1069 }
1070 dvenc->state = VENC_STATE_STOP;
1071 dvenc->is_active = 1;
1072 prevent_sleep();
1073 return ret;
1074err_venc_dal_open:
1075 dal_detach(dvenc->q6_handle);
1076err_venc_dal_attach:
1077 list_for_each_entry_safe(plist, tmp, &dvenc->venc_msg_list_free, list) {
1078 list_del(&plist->list);
1079 kfree(plist);
1080 }
1081err_venc_create_msg_list:
1082 kfree(dvenc);
1083 venc_ref--;
1084 return ret;
1085}
1086
1087static int q6venc_release(struct inode *inode, struct file *file)
1088{
1089 int ret = 0;
1090 struct venc_msg_list *l, *n;
1091 struct venc_pmem_list *plist, *m;
1092 struct venc_dev *dvenc;
1093 unsigned long flags;
1094
1095 venc_ref--;
1096 dvenc = file->private_data;
1097 dvenc->is_active = 0;
1098 wake_up_all(&dvenc->venc_msg_evt);
1099 dal_call_f0(dvenc->q6_handle, VENC_DALRPC_STOP, 1);
1100 dal_call_f0(dvenc->q6_handle, DAL_OP_CLOSE, 1);
1101 dal_detach(dvenc->q6_handle);
1102 list_for_each_entry_safe(l, n, &dvenc->venc_msg_list_free, list) {
1103 list_del(&l->list);
1104 kfree(l);
1105 }
1106 list_for_each_entry_safe(l, n, &dvenc->venc_msg_list_head, list) {
1107 list_del(&l->list);
1108 kfree(l);
1109 }
1110 spin_lock_irqsave(&dvenc->venc_pmem_list_lock, flags);
1111 if (!dvenc->pmem_freed) {
1112 list_for_each_entry(plist, &dvenc->venc_pmem_list_head, list)
1113 put_pmem_file(plist->buf.file);
1114 dvenc->pmem_freed = 1;
1115 }
1116 spin_unlock_irqrestore(&dvenc->venc_pmem_list_lock, flags);
1117
1118 list_for_each_entry_safe(plist, m, &dvenc->venc_pmem_list_head, list) {
1119 list_del(&plist->list);
1120 kfree(plist);
1121 }
1122 kfree(dvenc);
1123 allow_sleep();
1124 return ret;
1125}
1126
1127const struct file_operations q6venc_fops = {
1128 .owner = THIS_MODULE,
1129 .open = q6venc_open,
1130 .release = q6venc_release,
1131 .unlocked_ioctl = q6venc_ioctl,
1132};
1133
1134static int __init q6venc_init(void)
1135{
1136 int ret = 0;
1137
Stephen Boyd2fcabf92012-05-30 10:41:11 -07001138 pm_qos_add_request(&pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
1139 PM_QOS_DEFAULT_VALUE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001140 wake_lock_init(&wakelock, WAKE_LOCK_SUSPEND, "venc_suspend");
1141
1142 venc_device_p = kzalloc(sizeof(struct venc_dev), GFP_KERNEL);
1143 if (!venc_device_p) {
1144 pr_err("%s: unable to allocate memory for venc_device_p\n",
1145 __func__);
1146 return -ENOMEM;
1147 }
1148 ret = alloc_chrdev_region(&venc_dev_num, 0, 1, VENC_NAME);
1149 if (ret < 0) {
1150 pr_err("%s: alloc_chrdev_region failed (%d)\n", __func__,
1151 ret);
1152 return ret;
1153 }
1154 venc_class = class_create(THIS_MODULE, VENC_NAME);
1155 if (IS_ERR(venc_class)) {
1156 ret = PTR_ERR(venc_class);
1157 pr_err("%s: failed to create venc_class (%d)\n",
1158 __func__, ret);
1159 goto err_venc_class_create;
1160 }
1161 venc_device_p->class_devp =
1162 device_create(venc_class, NULL, venc_dev_num, NULL,
1163 VENC_NAME);
1164 if (IS_ERR(venc_device_p->class_devp)) {
1165 ret = PTR_ERR(venc_device_p->class_devp);
1166 pr_err("%s: failed to create class_device (%d)\n", __func__,
1167 ret);
1168 goto err_venc_class_device_create;
1169 }
1170 cdev_init(&cdev, &q6venc_fops);
1171 cdev.owner = THIS_MODULE;
1172 ret = cdev_add(&cdev, venc_dev_num, 1);
1173 if (ret < 0) {
1174 pr_err("%s: cdev_add failed (%d)\n", __func__, ret);
1175 goto err_venc_cdev_add;
1176 }
1177 init_waitqueue_head(&venc_device_p->venc_msg_evt);
1178 return ret;
1179
1180err_venc_cdev_add:
1181 device_destroy(venc_class, venc_dev_num);
1182err_venc_class_device_create:
1183 class_destroy(venc_class);
1184err_venc_class_create:
1185 unregister_chrdev_region(venc_dev_num, 1);
1186 return ret;
1187}
1188
1189static void __exit q6venc_exit(void)
1190{
1191 cdev_del(&(cdev));
1192 device_destroy(venc_class, venc_dev_num);
1193 class_destroy(venc_class);
1194 unregister_chrdev_region(venc_dev_num, 1);
1195}
1196
1197MODULE_LICENSE("GPL v2");
1198MODULE_DESCRIPTION("Video encoder driver for QDSP6");
1199MODULE_VERSION("2.0");
1200module_init(q6venc_init);
1201module_exit(q6venc_exit);