diff options
Diffstat (limited to 'camera/jpeg_10/msm_jpeg_sync.c')
| -rw-r--r-- | camera/jpeg_10/msm_jpeg_sync.c | 1579 |
1 files changed, 1579 insertions, 0 deletions
diff --git a/camera/jpeg_10/msm_jpeg_sync.c b/camera/jpeg_10/msm_jpeg_sync.c new file mode 100644 index 00000000..d6b76532 --- /dev/null +++ b/camera/jpeg_10/msm_jpeg_sync.c @@ -0,0 +1,1579 @@ +/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/list.h> +#include <linux/uaccess.h> +#include <linux/slab.h> +#include <linux/compat.h> +#include <linux/ratelimit.h> +#include <lenovo_media/msm_jpeg.h> +#include <linux/msm-bus.h> +#include "msm_jpeg_sync.h" +#include "msm_jpeg_core.h" +#include "msm_jpeg_platform.h" +#include "msm_jpeg_common.h" +#include "cam_hw_ops.h" + +#define JPEG_REG_SIZE 0x308 +#define JPEG_DEV_CNT 4 +#define JPEG_DEC_ID 2 +#define UINT32_MAX (0xFFFFFFFFU) + +#ifdef CONFIG_COMPAT + +#define MSM_JPEG_IOCTL_GET_HW_VERSION32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 1, struct msm_jpeg_hw_cmd32) + +#define MSM_JPEG_IOCTL_RESET32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 2, struct msm_jpeg_ctrl_cmd32) + +#define MSM_JPEG_IOCTL_STOP32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 3, struct msm_jpeg_hw_cmds32) + +#define MSM_JPEG_IOCTL_START32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 4, struct msm_jpeg_hw_cmds32) + +#define MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 5, struct msm_jpeg_buf32) + +#define MSM_JPEG_IOCTL_INPUT_GET32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 6, struct msm_jpeg_buf32) + +#define MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 8, struct msm_jpeg_buf32) + +#define MSM_JPEG_IOCTL_OUTPUT_GET32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 9, struct msm_jpeg_buf32) + +#define MSM_JPEG_IOCTL_EVT_GET32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 11, struct msm_jpeg_ctrl_cmd32) + +#define MSM_JPEG_IOCTL_HW_CMD32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 13, struct msm_jpeg_hw_cmd32) + +#define MSM_JPEG_IOCTL_HW_CMDS32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 14, struct msm_jpeg_hw_cmds32) + +#define MSM_JPEG_IOCTL_TEST_DUMP_REGION32 \ + _IOW(MSM_JPEG_IOCTL_MAGIC, 15, compat_ulong_t) + +struct msm_jpeg_ctrl_cmd32 { + uint32_t type; + uint32_t len; + compat_uptr_t value; +}; +struct msm_jpeg_buf32 { + uint32_t type; + int fd; + + compat_uptr_t vaddr; + + uint32_t y_off; + uint32_t y_len; + uint32_t framedone_len; + + uint32_t cbcr_off; + uint32_t cbcr_len; + + uint32_t num_of_mcu_rows; + uint32_t offset; + uint32_t pln2_off; + uint32_t pln2_len; +}; + +struct msm_jpeg_hw_cmd32 { + + uint32_t type:4; + + /* n microseconds of timeout for WAIT */ + /* n microseconds of time for DELAY */ + /* repeat n times for READ/WRITE */ + /* max is 0xFFF, 4095 */ + uint32_t n:12; + uint32_t offset:16; + uint32_t mask; + union { + uint32_t data; /* for single READ/WRITE/WAIT, n = 1 */ + compat_uptr_t pdata; /* for multiple READ/WRITE/WAIT, n > 1 */ + }; +}; + +struct msm_jpeg_hw_cmds32 { + uint32_t m; /* number of elements in the hw_cmd array */ + struct msm_jpeg_hw_cmd32 hw_cmd[1]; +}; +#endif + + +inline void msm_jpeg_q_init(char const *name, struct msm_jpeg_q *q_p) +{ + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, name); + q_p->name = name; + spin_lock_init(&q_p->lck); + INIT_LIST_HEAD(&q_p->q); + init_waitqueue_head(&q_p->wait); + q_p->unblck = 0; +} + +inline void *msm_jpeg_q_out(struct msm_jpeg_q *q_p) +{ + unsigned long flags; + struct msm_jpeg_q_entry *q_entry_p = NULL; + void *data = NULL; + + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + spin_lock_irqsave(&q_p->lck, flags); + if (!list_empty(&q_p->q)) { + q_entry_p = list_first_entry(&q_p->q, struct msm_jpeg_q_entry, + list); + list_del_init(&q_entry_p->list); + } + spin_unlock_irqrestore(&q_p->lck, flags); + + if (q_entry_p) { + data = q_entry_p->data; + kfree(q_entry_p); + } else { + JPEG_DBG("%s:%d] %s no entry\n", __func__, __LINE__, + q_p->name); + } + + return data; +} + +inline int msm_jpeg_q_in(struct msm_jpeg_q *q_p, void *data) +{ + unsigned long flags; + + struct msm_jpeg_q_entry *q_entry_p; + + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + + q_entry_p = kmalloc(sizeof(struct msm_jpeg_q_entry), GFP_ATOMIC); + if (!q_entry_p) { + JPEG_PR_ERR("%s: no mem\n", __func__); + return -EFAULT; + } + q_entry_p->data = data; + + spin_lock_irqsave(&q_p->lck, flags); + list_add_tail(&q_entry_p->list, &q_p->q); + spin_unlock_irqrestore(&q_p->lck, flags); + + return 0; +} + +inline int msm_jpeg_q_in_buf(struct msm_jpeg_q *q_p, + struct msm_jpeg_core_buf *buf) +{ + struct msm_jpeg_core_buf *buf_p; + + JPEG_DBG("%s:%d]\n", __func__, __LINE__); + buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC); + if (!buf_p) { + JPEG_PR_ERR("%s: no mem\n", __func__); + return -EFAULT; + } + + memcpy(buf_p, buf, sizeof(struct msm_jpeg_core_buf)); + + msm_jpeg_q_in(q_p, buf_p); + return 0; +} + +inline int msm_jpeg_q_wait(struct msm_jpeg_q *q_p) +{ + long tm = MAX_SCHEDULE_TIMEOUT; /* 500ms */ + int rc; + + JPEG_DBG("%s:%d] %s wait\n", __func__, __LINE__, q_p->name); + rc = wait_event_timeout(q_p->wait, + (!list_empty_careful(&q_p->q) || q_p->unblck), + msecs_to_jiffies(tm)); + JPEG_DBG("%s:%d] %s wait done\n", __func__, __LINE__, q_p->name); + if (list_empty_careful(&q_p->q)) { + if (rc == 0) { + rc = -ETIMEDOUT; + JPEG_PR_ERR("%s:%d] %s timeout\n", __func__, __LINE__, + q_p->name); + } else if (q_p->unblck) { + JPEG_DBG("%s:%d] %s unblock is true\n", __func__, + __LINE__, q_p->name); + q_p->unblck = 0; + rc = -ECANCELED; + } + } + return rc; +} + +inline int msm_jpeg_q_wakeup(struct msm_jpeg_q *q_p) +{ + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + wake_up(&q_p->wait); + return 0; +} + +inline int msm_jpeg_q_unblock(struct msm_jpeg_q *q_p) +{ + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + q_p->unblck = 1; + wake_up(&q_p->wait); + return 0; +} + +inline void msm_jpeg_outbuf_q_cleanup(struct msm_jpeg_device *pgmn_dev, + struct msm_jpeg_q *q_p) +{ + struct msm_jpeg_core_buf *buf_p; + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + do { + buf_p = msm_jpeg_q_out(q_p); + if (buf_p) { + msm_jpeg_platform_p2v(pgmn_dev->iommu_hdl, + buf_p->ion_fd); + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + kfree(buf_p); + } + } while (buf_p); + q_p->unblck = 0; +} + +inline void msm_jpeg_q_cleanup(struct msm_jpeg_q *q_p) +{ + void *data; + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + do { + data = msm_jpeg_q_out(q_p); + if (data) { + JPEG_DBG("%s:%d] %s\n", __func__, __LINE__, q_p->name); + kfree(data); + } + } while (data); + q_p->unblck = 0; +} + +/*************** event queue ****************/ + +int msm_jpeg_framedone_irq(struct msm_jpeg_device *pgmn_dev, + struct msm_jpeg_core_buf *buf_in) +{ + int rc = 0; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + + if (buf_in) { + buf_in->vbuf.framedone_len = buf_in->framedone_len; + buf_in->vbuf.type = MSM_JPEG_EVT_SESSION_DONE; + JPEG_DBG("%s:%d] 0x%08x %d framedone_len %d\n", + __func__, __LINE__, + (int) buf_in->y_buffer_addr, buf_in->y_len, + buf_in->vbuf.framedone_len); + rc = msm_jpeg_q_in_buf(&pgmn_dev->evt_q, buf_in); + } else { + JPEG_PR_ERR("%s:%d] no output return buffer\n", + __func__, __LINE__); + rc = -1; + } + + if (buf_in) + rc = msm_jpeg_q_wakeup(&pgmn_dev->evt_q); + + return rc; +} + +int msm_jpeg_evt_get(struct msm_jpeg_device *pgmn_dev, + void __user *to) +{ + struct msm_jpeg_core_buf *buf_p; + struct msm_jpeg_ctrl_cmd ctrl_cmd; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + + msm_jpeg_q_wait(&pgmn_dev->evt_q); + buf_p = msm_jpeg_q_out(&pgmn_dev->evt_q); + + if (!buf_p) { + JPEG_DBG("%s:%d] no buffer\n", __func__, __LINE__); + return -EAGAIN; + } + + memset(&ctrl_cmd, 0, sizeof(ctrl_cmd)); + ctrl_cmd.type = buf_p->vbuf.type; + kfree(buf_p); + + if (ctrl_cmd.type == MSM_JPEG_EVT_SESSION_DONE) { + /* update the bw with zeroth vector */ + msm_camera_update_bus_vector(pgmn_dev->bus_client, 0); + JPEG_BUS_UNVOTED(pgmn_dev); + JPEG_DBG("%s:%d] Bus unvoted\n", __func__, __LINE__); + } + + JPEG_DBG("%s:%d] 0x%08lx %d\n", __func__, __LINE__, + (unsigned long) ctrl_cmd.value, ctrl_cmd.len); + + if (copy_to_user(to, &ctrl_cmd, sizeof(ctrl_cmd))) { + JPEG_PR_ERR("%s:%d]\n", __func__, __LINE__); + return -EFAULT; + } + + return 0; +} + +int msm_jpeg_evt_get_unblock(struct msm_jpeg_device *pgmn_dev) +{ + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + msm_jpeg_q_unblock(&pgmn_dev->evt_q); + return 0; +} + +void msm_jpeg_reset_ack_irq(struct msm_jpeg_device *pgmn_dev) +{ + JPEG_DBG("%s:%d]\n", __func__, __LINE__); +} + +void msm_jpeg_err_irq(struct msm_jpeg_device *pgmn_dev, + int event) +{ + int rc = 0; + struct msm_jpeg_core_buf buf; + + JPEG_PR_ERR("%s:%d] error: %d\n", __func__, __LINE__, event); + + buf.vbuf.type = MSM_JPEG_EVT_ERR; + rc = msm_jpeg_q_in_buf(&pgmn_dev->evt_q, &buf); + if (!rc) + rc = msm_jpeg_q_wakeup(&pgmn_dev->evt_q); + + if (!rc) + JPEG_PR_ERR("%s:%d] err err\n", __func__, __LINE__); + + return; +} + +/*************** output queue ****************/ + +int msm_jpeg_we_pingpong_irq(struct msm_jpeg_device *pgmn_dev, + struct msm_jpeg_core_buf *buf_in) +{ + int rc = 0; + struct msm_jpeg_core_buf *buf_out; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + if (buf_in) { + JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__, + (int) buf_in->y_buffer_addr, buf_in->y_len); + rc = msm_jpeg_q_in_buf(&pgmn_dev->output_rtn_q, buf_in); + } else { + JPEG_DBG("%s:%d] no output return buffer\n", __func__, + __LINE__); + rc = -1; + return rc; + } + + buf_out = msm_jpeg_q_out(&pgmn_dev->output_buf_q); + + if (buf_out) { + JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__, + (int) buf_out->y_buffer_addr, buf_out->y_len); + rc = msm_jpeg_core_we_buf_update(pgmn_dev, buf_out); + kfree(buf_out); + } else { + msm_jpeg_core_we_buf_reset(pgmn_dev, buf_in); + JPEG_DBG("%s:%d] no output buffer\n", __func__, __LINE__); + rc = -2; + } + + if (buf_in) + rc = msm_jpeg_q_wakeup(&pgmn_dev->output_rtn_q); + + return rc; +} + +int msm_jpeg_output_get(struct msm_jpeg_device *pgmn_dev, void __user *to) +{ + struct msm_jpeg_core_buf *buf_p; + struct msm_jpeg_buf buf_cmd; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + + msm_jpeg_q_wait(&pgmn_dev->output_rtn_q); + buf_p = msm_jpeg_q_out(&pgmn_dev->output_rtn_q); + + if (!buf_p) { + JPEG_DBG("%s:%d] no output buffer return\n", + __func__, __LINE__); + return -EAGAIN; + } + + buf_cmd = buf_p->vbuf; + msm_jpeg_platform_p2v(pgmn_dev->iommu_hdl, buf_p->ion_fd); + kfree(buf_p); + + JPEG_DBG("%s:%d] 0x%08lx %d\n", __func__, __LINE__, + (unsigned long) buf_cmd.vaddr, buf_cmd.y_len); + + if (copy_to_user(to, &buf_cmd, sizeof(buf_cmd))) { + JPEG_PR_ERR("%s:%d]", __func__, __LINE__); + return -EFAULT; + } + + return 0; +} + +int msm_jpeg_output_get_unblock(struct msm_jpeg_device *pgmn_dev) +{ + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + msm_jpeg_q_unblock(&pgmn_dev->output_rtn_q); + return 0; +} + +static inline int msm_jpeg_add_u32_check(uint32_t *p, uint32_t n, uint32_t *res) +{ + *res = 0; + + while (n--) { + if ((*res + *p) < *res) + return -EFAULT; + *res += *p++; + } + return 0; +} + +int msm_jpeg_output_buf_enqueue(struct msm_jpeg_device *pgmn_dev, + void __user *arg) +{ + struct msm_jpeg_buf buf_cmd; + struct msm_jpeg_core_buf *buf_p; + uint32_t buf_len_params[10]; + uint32_t total_len = 0; + int n = 0; + + memset(&buf_cmd, 0x0, sizeof(struct msm_jpeg_buf)); + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + buf_len_params[n++] = buf_cmd.y_len; + buf_len_params[n++] = buf_cmd.cbcr_len; + buf_len_params[n++] = buf_cmd.pln2_len; + buf_len_params[n++] = buf_cmd.offset; + buf_len_params[n++] = buf_cmd.y_off; + if (msm_jpeg_add_u32_check(buf_len_params, n, &total_len) < 0) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC); + if (!buf_p) { + JPEG_PR_ERR("%s:%d] no mem\n", __func__, __LINE__); + return -EFAULT; + } + + + JPEG_DBG("%s:%d] vaddr = 0x%08lx y_len = %d\n, fd = %d", + __func__, __LINE__, (unsigned long) buf_cmd.vaddr, + buf_cmd.y_len, buf_cmd.fd); + + buf_p->ion_fd = buf_cmd.fd; + buf_p->y_buffer_addr = msm_jpeg_platform_v2p(pgmn_dev, buf_cmd.fd, + total_len, pgmn_dev->iommu_hdl); + + if (!buf_p->y_buffer_addr) { + JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__); + kfree(buf_p); + return -EFAULT; + } + + buf_p->y_buffer_addr += buf_cmd.offset + buf_cmd.y_off; + + if (buf_cmd.cbcr_len) + buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + + buf_cmd.y_len; + else + buf_p->cbcr_buffer_addr = 0x0; + + if (buf_cmd.pln2_len) + buf_p->pln2_addr = buf_p->cbcr_buffer_addr + + buf_cmd.cbcr_len; + else + buf_p->pln2_addr = 0x0; + + JPEG_DBG("%s:%d]After v2p pln0_addr %x pln0_len %d", + __func__, __LINE__, buf_p->y_buffer_addr, + buf_cmd.y_len); + + JPEG_DBG("pl1_len %d, pln1_addr %x, pln2_adrr %x,pln2_len %d", + buf_cmd.cbcr_len, buf_p->cbcr_buffer_addr, + buf_p->pln2_addr, buf_cmd.pln2_len); + + buf_p->y_len = buf_cmd.y_len; + buf_p->cbcr_len = buf_cmd.cbcr_len; + buf_p->pln2_len = buf_cmd.pln2_len; + buf_p->vbuf = buf_cmd; + + msm_jpeg_q_in(&pgmn_dev->output_buf_q, buf_p); + return 0; +} + +/*************** input queue ****************/ + +int msm_jpeg_fe_pingpong_irq(struct msm_jpeg_device *pgmn_dev, + struct msm_jpeg_core_buf *buf_in) +{ + struct msm_jpeg_core_buf *buf_out; + int rc = 0; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + if (buf_in) { + JPEG_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__, + (int) buf_in->y_buffer_addr, buf_in->y_len); + rc = msm_jpeg_q_in_buf(&pgmn_dev->input_rtn_q, buf_in); + } else { + JPEG_DBG("%s:%d] no input return buffer\n", __func__, + __LINE__); + rc = -EFAULT; + } + + buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q); + + if (buf_out) { + rc = msm_jpeg_core_fe_buf_update(pgmn_dev, buf_out); + kfree(buf_out); + msm_jpeg_core_fe_start(pgmn_dev); + } else { + JPEG_DBG("%s:%d] no input buffer\n", __func__, __LINE__); + rc = -EFAULT; + } + + if (buf_in) + rc = msm_jpeg_q_wakeup(&pgmn_dev->input_rtn_q); + + return rc; +} + +int msm_jpeg_input_get(struct msm_jpeg_device *pgmn_dev, void __user *to) +{ + struct msm_jpeg_core_buf *buf_p; + struct msm_jpeg_buf buf_cmd; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + msm_jpeg_q_wait(&pgmn_dev->input_rtn_q); + buf_p = msm_jpeg_q_out(&pgmn_dev->input_rtn_q); + + if (!buf_p) { + JPEG_DBG("%s:%d] no input buffer return\n", + __func__, __LINE__); + return -EAGAIN; + } + + buf_cmd = buf_p->vbuf; + + msm_jpeg_platform_p2v(pgmn_dev->iommu_hdl, buf_p->ion_fd); + kfree(buf_p); + + JPEG_DBG("%s:%d] 0x%08lx %d\n", __func__, __LINE__, + (unsigned long) buf_cmd.vaddr, buf_cmd.y_len); + + if (copy_to_user(to, &buf_cmd, sizeof(buf_cmd))) { + JPEG_PR_ERR("%s:%d]\n", __func__, __LINE__); + return -EFAULT; + } + + return 0; +} + +int msm_jpeg_input_get_unblock(struct msm_jpeg_device *pgmn_dev) +{ + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + msm_jpeg_q_unblock(&pgmn_dev->input_rtn_q); + return 0; +} + +int msm_jpeg_input_buf_enqueue(struct msm_jpeg_device *pgmn_dev, + void __user *arg) +{ + struct msm_jpeg_core_buf *buf_p; + struct msm_jpeg_buf buf_cmd; + uint32_t buf_len_params[10]; + uint32_t total_len = 0; + int n = 0; + + memset(&buf_cmd, 0x0, sizeof(struct msm_jpeg_buf)); + + if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_jpeg_buf))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + buf_len_params[n++] = buf_cmd.y_len; + buf_len_params[n++] = buf_cmd.cbcr_len; + buf_len_params[n++] = buf_cmd.pln2_len; + buf_len_params[n++] = buf_cmd.offset; + buf_len_params[n++] = buf_cmd.y_off; + if (buf_cmd.cbcr_len) + buf_len_params[n++] = buf_cmd.cbcr_off; + if (buf_cmd.pln2_len) + buf_len_params[n++] = buf_cmd.pln2_off; + + if (msm_jpeg_add_u32_check(buf_len_params, n, &total_len) < 0) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + buf_p = kmalloc(sizeof(struct msm_jpeg_core_buf), GFP_ATOMIC); + if (!buf_p) { + JPEG_PR_ERR("%s:%d] no mem\n", __func__, __LINE__); + return -EFAULT; + } + + JPEG_DBG("%s:%d] 0x%08lx %d\n", __func__, __LINE__, + (unsigned long) buf_cmd.vaddr, buf_cmd.y_len); + + buf_p->ion_fd = buf_cmd.fd; + buf_p->y_buffer_addr = msm_jpeg_platform_v2p(pgmn_dev, buf_cmd.fd, + total_len, pgmn_dev->iommu_hdl); + + if (!buf_p->y_buffer_addr) { + JPEG_PR_ERR("%s:%d] v2p wrong\n", __func__, __LINE__); + kfree(buf_p); + return -EFAULT; + } + + buf_p->y_buffer_addr += buf_cmd.offset + buf_cmd.y_off; + + buf_p->y_len = buf_cmd.y_len; + buf_p->cbcr_len = buf_cmd.cbcr_len; + buf_p->pln2_len = buf_cmd.pln2_len; + buf_p->num_of_mcu_rows = buf_cmd.num_of_mcu_rows; + + if (buf_cmd.cbcr_len) + buf_p->cbcr_buffer_addr = buf_p->y_buffer_addr + + buf_cmd.y_len + buf_cmd.cbcr_off; + else + buf_p->cbcr_buffer_addr = 0x0; + + if (buf_cmd.pln2_len) + buf_p->pln2_addr = buf_p->cbcr_buffer_addr + + buf_cmd.cbcr_len + buf_cmd.pln2_off; + else + buf_p->pln2_addr = 0x0; + + JPEG_DBG("%s: y_addr=%x, y_len=%x, cbcr_addr=%x, cbcr_len=%d", + __func__, buf_p->y_buffer_addr, buf_p->y_len, + buf_p->cbcr_buffer_addr, buf_p->cbcr_len); + JPEG_DBG("pln2_addr = %x, pln2_len = %d, fd =%d\n", + buf_p->pln2_addr, buf_p->pln2_len, buf_cmd.fd); + + buf_p->vbuf = buf_cmd; + + msm_jpeg_q_in(&pgmn_dev->input_buf_q, buf_p); + + return 0; +} + +int msm_jpeg_irq(int event, void *context, void *data) +{ + struct msm_jpeg_device *pgmn_dev = + (struct msm_jpeg_device *) context; + + switch (event) { + case MSM_JPEG_EVT_SESSION_DONE: + msm_jpeg_framedone_irq(pgmn_dev, data); + msm_jpeg_we_pingpong_irq(pgmn_dev, data); + break; + + case MSM_JPEG_HW_MASK_COMP_FE: + msm_jpeg_fe_pingpong_irq(pgmn_dev, data); + break; + + case MSM_JPEG_HW_MASK_COMP_WE: + msm_jpeg_we_pingpong_irq(pgmn_dev, data); + break; + + case MSM_JPEG_HW_MASK_COMP_RESET_ACK: + msm_jpeg_reset_ack_irq(pgmn_dev); + break; + + case MSM_JPEG_HW_MASK_COMP_ERR: + default: + msm_jpeg_err_irq(pgmn_dev, event); + break; + } + + return 0; +} + +int __msm_jpeg_open(struct msm_jpeg_device *pgmn_dev) +{ + int rc; + irqreturn_t (*core_irq)(int, void *); + mutex_lock(&pgmn_dev->lock); + if (pgmn_dev->open_count) { + /* only open once */ + JPEG_PR_ERR("%s:%d] busy\n", __func__, __LINE__); + mutex_unlock(&pgmn_dev->lock); + return -EBUSY; + } + pgmn_dev->open_count++; + if (pgmn_dev->open_count == 1) + pgmn_dev->state = MSM_JPEG_INIT; + + mutex_unlock(&pgmn_dev->lock); + + rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_JPEG, + CAM_AHB_SVS_VOTE); + if (rc < 0) { + pr_err("%s: failed to vote for AHB\n", __func__); + return rc; + } + + msm_jpeg_core_irq_install(msm_jpeg_irq); + if (pgmn_dev->core_type == MSM_JPEG_CORE_CODEC) + core_irq = msm_jpeg_core_irq; + else + core_irq = msm_jpegdma_core_irq; + + /* initialize the platform resources */ + rc = msm_jpeg_platform_init(core_irq, pgmn_dev); + if (rc) { + JPEG_PR_ERR("%s:%d] platform_init fail %d\n", __func__, + __LINE__, rc); + goto platform_init_fail; + } + JPEG_DBG("%s:%d] platform resources - base %p, irq %d\n", + __func__, __LINE__, + pgmn_dev->base, (int)pgmn_dev->jpeg_irq_res->start); + msm_jpeg_q_cleanup(&pgmn_dev->evt_q); + msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q); + msm_jpeg_outbuf_q_cleanup(pgmn_dev, &pgmn_dev->output_buf_q); + msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q); + msm_jpeg_q_cleanup(&pgmn_dev->input_buf_q); + msm_jpeg_core_init(pgmn_dev); + + JPEG_DBG("%s:%d] success\n", __func__, __LINE__); + return rc; + +platform_init_fail: + if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_JPEG, + CAM_AHB_SUSPEND_VOTE) < 0) + pr_err("%s: failed to remove vote for AHB\n", __func__); + return rc; +} + +int __msm_jpeg_release(struct msm_jpeg_device *pgmn_dev) +{ + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + mutex_lock(&pgmn_dev->lock); + if (!pgmn_dev->open_count) { + JPEG_PR_ERR(KERN_ERR "%s: not opened\n", __func__); + mutex_unlock(&pgmn_dev->lock); + return -EINVAL; + } + pgmn_dev->open_count--; + mutex_unlock(&pgmn_dev->lock); + + msm_jpeg_core_release(pgmn_dev); + msm_jpeg_q_cleanup(&pgmn_dev->evt_q); + msm_jpeg_q_cleanup(&pgmn_dev->output_rtn_q); + msm_jpeg_outbuf_q_cleanup(pgmn_dev, &pgmn_dev->output_buf_q); + msm_jpeg_q_cleanup(&pgmn_dev->input_rtn_q); + msm_jpeg_outbuf_q_cleanup(pgmn_dev, &pgmn_dev->input_buf_q); + + JPEG_DBG("%s:%d]\n", __func__, __LINE__); + if (pgmn_dev->open_count) + JPEG_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__); + + /* release the platform resources */ + msm_jpeg_platform_release(pgmn_dev); + + JPEG_DBG("%s:%d]\n", __func__, __LINE__); + + if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_JPEG, + CAM_AHB_SUSPEND_VOTE) < 0) + pr_err("%s: failed to remove vote for AHB\n", __func__); + + return 0; +} + +int msm_jpeg_ioctl_hw_cmd(struct msm_jpeg_device *pgmn_dev, + void * __user arg) +{ + struct msm_jpeg_hw_cmd hw_cmd; + int is_copy_to_user; + + if (copy_from_user(&hw_cmd, arg, sizeof(struct msm_jpeg_hw_cmd))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + is_copy_to_user = msm_jpeg_hw_exec_cmds(&hw_cmd, 1, + pgmn_dev->res_size, pgmn_dev->base); + JPEG_DBG( + "%s:%d] type %d, n %d, offset %d, mask %x, data %x, pdata %lx\n", + __func__, __LINE__, hw_cmd.type, hw_cmd.n, hw_cmd.offset, + hw_cmd.mask, hw_cmd.data, (unsigned long) hw_cmd.pdata); + + if (is_copy_to_user >= 0) { + if (copy_to_user(arg, &hw_cmd, sizeof(hw_cmd))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + } else { + return is_copy_to_user; + } + + return 0; +} + +int msm_jpeg_ioctl_hw_cmds(struct msm_jpeg_device *pgmn_dev, + void * __user arg) +{ + int is_copy_to_user; + uint32_t len; + uint32_t m; + struct msm_jpeg_hw_cmds *hw_cmds_p; + struct msm_jpeg_hw_cmd *hw_cmd_p; + + if (copy_from_user(&m, arg, sizeof(m))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + if ((m == 0) || (m > ((UINT32_MAX - sizeof(struct msm_jpeg_hw_cmds)) / + sizeof(struct msm_jpeg_hw_cmd)))) { + JPEG_PR_ERR("%s:%d] m_cmds out of range\n", __func__, __LINE__); + return -EFAULT; + } + + len = sizeof(struct msm_jpeg_hw_cmds) + + sizeof(struct msm_jpeg_hw_cmd) * (m - 1); + hw_cmds_p = kmalloc(len, GFP_KERNEL); + if (!hw_cmds_p) { + JPEG_PR_ERR("%s:%d] no mem %d\n", __func__, __LINE__, len); + return -EFAULT; + } + + if (copy_from_user(hw_cmds_p, arg, len)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + kfree(hw_cmds_p); + return -EFAULT; + } + + hw_cmd_p = (struct msm_jpeg_hw_cmd *) &(hw_cmds_p->hw_cmd); + + is_copy_to_user = msm_jpeg_hw_exec_cmds(hw_cmd_p, m, + pgmn_dev->res_size, pgmn_dev->base); + + if (is_copy_to_user >= 0) { + if (copy_to_user(arg, hw_cmds_p, len)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + kfree(hw_cmds_p); + return -EFAULT; + } + } else { + kfree(hw_cmds_p); + return is_copy_to_user; + } + kfree(hw_cmds_p); + return 0; +} + +int msm_jpeg_start(struct msm_jpeg_device *pgmn_dev, void * __user arg, + int (*hw_ioctl)(struct msm_jpeg_device *, void * __user)) +{ + struct msm_jpeg_core_buf *buf_out; + struct msm_jpeg_core_buf *buf_out_free[2] = {NULL, NULL}; + int i, rc; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + + msm_jpeg_platform_set_dt_config(pgmn_dev); + + /* update the bw with vector index "1" */ + msm_camera_update_bus_vector(pgmn_dev->bus_client, 1); + JPEG_BUS_VOTED(pgmn_dev); + JPEG_DBG("%s:%d] Bus Voted\n", __func__, __LINE__); + + pgmn_dev->release_buf = 1; + for (i = 0; i < 2; i++) { + buf_out = msm_jpeg_q_out(&pgmn_dev->input_buf_q); + + if (buf_out) { + msm_jpeg_core_fe_buf_update(pgmn_dev, buf_out); + kfree(buf_out); + } else { + JPEG_DBG("%s:%d] no input buffer\n", __func__, + __LINE__); + break; + } + } + + for (i = 0; i < 2; i++) { + buf_out_free[i] = msm_jpeg_q_out(&pgmn_dev->output_buf_q); + + if (buf_out_free[i]) { + msm_jpeg_core_we_buf_update(pgmn_dev, buf_out_free[i]); + pgmn_dev->release_buf = 0; + } else { + JPEG_DBG("%s:%d] no output buffer\n", + __func__, __LINE__); + break; + } + } + + for (i = 0; i < 2; i++) + kfree(buf_out_free[i]); + + JPEG_DBG_HIGH("%s:%d] START\n", __func__, __LINE__); + pgmn_dev->state = MSM_JPEG_EXECUTING; + /* ensure write is done */ + wmb(); + rc = hw_ioctl(pgmn_dev, arg); + /* ensure write is done */ + wmb(); + JPEG_DBG("%s:%d]", __func__, __LINE__); + return rc; +} + +int msm_jpeg_ioctl_reset(struct msm_jpeg_device *pgmn_dev, void * __user arg) +{ + int rc; + struct msm_jpeg_ctrl_cmd ctrl_cmd, *p_ctrl_cmd; + + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + p_ctrl_cmd = &ctrl_cmd; + + if (pgmn_dev->state == MSM_JPEG_INIT) { + if (copy_from_user(&ctrl_cmd, arg, sizeof(ctrl_cmd))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + pgmn_dev->op_mode = p_ctrl_cmd->type; + + rc = msm_jpeg_core_reset(pgmn_dev, pgmn_dev->op_mode, + pgmn_dev->base, pgmn_dev->res_size); + } else { + JPEG_PR_ERR("%s:%d] JPEG not been initialized Wrong state\n", + __func__, __LINE__); + rc = -1; + } + return rc; +} + +int msm_jpeg_ioctl_test_dump_region(struct msm_jpeg_device *pgmn_dev, + unsigned long arg) +{ + JPEG_DBG("%s:%d] Enter\n", __func__, __LINE__); + msm_jpeg_io_dump(pgmn_dev->base, JPEG_REG_SIZE); + return 0; +} + +int msm_jpeg_ioctl_set_clk_rate(struct msm_jpeg_device *pgmn_dev, + void * __user arg) +{ + long clk_rate; + int rc; + + if ((pgmn_dev->state != MSM_JPEG_INIT) && + (pgmn_dev->state != MSM_JPEG_RESET)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + if (get_user(clk_rate, (unsigned int __user *)arg)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + JPEG_DBG("%s:%d] Requested clk rate %ld\n", __func__, __LINE__, + clk_rate); + if (clk_rate < 0) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + rc = msm_jpeg_platform_set_clk_rate(pgmn_dev, clk_rate); + if (rc < 0) { + JPEG_PR_ERR("%s: clk failed rc = %d\n", __func__, rc); + return -EFAULT; + } + + return 0; +} +#ifdef CONFIG_COMPAT +int msm_jpeg_get_ctrl_cmd32(struct msm_jpeg_ctrl_cmd *ctrl_cmd, + void __user *arg) +{ + struct msm_jpeg_ctrl_cmd32 ctrl_cmd32; + unsigned long temp; + if (copy_from_user(&ctrl_cmd32, arg, + sizeof(struct msm_jpeg_ctrl_cmd32))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + ctrl_cmd->type = ctrl_cmd32.type; + ctrl_cmd->len = ctrl_cmd32.len; + temp = (unsigned long) ctrl_cmd32.value; + ctrl_cmd->value = (void *) temp; + + return 0; +} +int msm_jpeg_put_ctrl_cmd32(struct msm_jpeg_ctrl_cmd *ctrl_cmd, + void __user *arg) +{ + struct msm_jpeg_ctrl_cmd32 ctrl_cmd32; + unsigned long temp; + + ctrl_cmd32.type = ctrl_cmd->type; + ctrl_cmd32.len = ctrl_cmd->len; + temp = (unsigned long) ctrl_cmd->value; + ctrl_cmd32.value = (compat_uptr_t) temp; + + if (copy_to_user(arg, &ctrl_cmd32, + sizeof(struct msm_jpeg_ctrl_cmd32))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + return 0; +} + +int msm_jpeg_get_jpeg_buf32(struct msm_jpeg_buf *jpeg_buf, + void __user *arg) +{ + struct msm_jpeg_buf32 jpeg_buf32; + unsigned long temp; + if (copy_from_user(&jpeg_buf32, arg, sizeof(struct msm_jpeg_buf32))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + jpeg_buf->type = jpeg_buf32.type; + jpeg_buf->fd = jpeg_buf32.fd; + temp = (unsigned long) jpeg_buf32.vaddr; + jpeg_buf->vaddr = (void *) temp; + jpeg_buf->y_off = jpeg_buf32.y_off; + jpeg_buf->y_len = jpeg_buf32.y_len; + jpeg_buf->framedone_len = jpeg_buf32.framedone_len; + jpeg_buf->cbcr_off = jpeg_buf32.cbcr_off; + jpeg_buf->cbcr_len = jpeg_buf32.cbcr_len; + jpeg_buf->num_of_mcu_rows = jpeg_buf32.num_of_mcu_rows; + jpeg_buf->offset = jpeg_buf32.offset; + jpeg_buf->pln2_off = jpeg_buf32.pln2_off; + jpeg_buf->pln2_len = jpeg_buf32.pln2_len; + + return 0; +} +int msm_jpeg_put_jpeg_buf32(struct msm_jpeg_buf *jpeg_buf, + void __user *arg) +{ + struct msm_jpeg_buf32 jpeg_buf32; + unsigned long temp; + + jpeg_buf32.type = jpeg_buf->type; + jpeg_buf32.fd = jpeg_buf->fd; + temp = (unsigned long) jpeg_buf->vaddr; + jpeg_buf32.vaddr = (compat_uptr_t) temp; + jpeg_buf32.y_off = jpeg_buf->y_off; + jpeg_buf32.y_len = jpeg_buf->y_len; + jpeg_buf32.framedone_len = jpeg_buf->framedone_len; + jpeg_buf32.cbcr_off = jpeg_buf->cbcr_off; + jpeg_buf32.cbcr_len = jpeg_buf->cbcr_len; + jpeg_buf32.num_of_mcu_rows = jpeg_buf->num_of_mcu_rows; + jpeg_buf32.offset = jpeg_buf->offset; + jpeg_buf32.pln2_off = jpeg_buf->pln2_off; + jpeg_buf32.pln2_len = jpeg_buf->pln2_len; + + if (copy_to_user(arg, &jpeg_buf32, sizeof(struct msm_jpeg_buf32))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + return 0; +} + +int msm_jpeg_put_hw_cmd32(void __user *arg, + struct msm_jpeg_hw_cmd *phw_cmd, int copy) +{ + struct msm_jpeg_hw_cmd32 hw_cmd32; + struct msm_jpeg_hw_cmd32 *phw_cmd32; + + phw_cmd32 = (struct msm_jpeg_hw_cmd32 *) arg; + if (copy) + phw_cmd32 = &hw_cmd32; + + + phw_cmd32->type = phw_cmd->type; + phw_cmd32->n = phw_cmd->n; + phw_cmd32->offset = phw_cmd->offset; + phw_cmd32->mask = phw_cmd->mask; + phw_cmd32->data = phw_cmd->data; + + if (copy && copy_to_user(arg, &hw_cmd32, sizeof(hw_cmd32))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + return 0; +} +int msm_jpeg_get_hw_cmd32(struct msm_jpeg_hw_cmd *phw_cmd, + void __user *arg, int copy) +{ + struct msm_jpeg_hw_cmd32 hw_cmd32; + struct msm_jpeg_hw_cmd32 *phw_cmd32; + + if (copy) { + phw_cmd32 = &hw_cmd32; + if (copy_from_user(&hw_cmd32, arg, sizeof(hw_cmd32))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + } else { + phw_cmd32 = (struct msm_jpeg_hw_cmd32 *) arg; + } + phw_cmd->type = phw_cmd32->type; + phw_cmd->n = phw_cmd32->n; + phw_cmd->offset = phw_cmd32->offset; + phw_cmd->mask = phw_cmd32->mask; + phw_cmd->data = phw_cmd32->data; + + return 0; +} +int msm_jpeg_ioctl_hw_cmds32(struct msm_jpeg_device *pgmn_dev, + void __user *arg) +{ + int is_copy_to_user; + uint32_t len, len32; + uint32_t m; + struct msm_jpeg_hw_cmds32 *phw_cmds32; + struct msm_jpeg_hw_cmds *phw_cmds; + + if (copy_from_user(&m, arg, sizeof(m))) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + if ((m == 0) || (m > ((UINT32_MAX - sizeof(struct msm_jpeg_hw_cmds32)) / + sizeof(struct msm_jpeg_hw_cmd32)))) { + JPEG_PR_ERR("%s:%d] m_cmds out of range\n", __func__, __LINE__); + return -EFAULT; + } + + len32 = sizeof(struct msm_jpeg_hw_cmds32) + + sizeof(struct msm_jpeg_hw_cmd32) * (m - 1); + phw_cmds32 = kmalloc(len32, GFP_KERNEL); + if (!phw_cmds32) { + JPEG_PR_ERR("%s:%d] no mem %d\n", __func__, __LINE__, len32); + return -EFAULT; + } + + if (copy_from_user(phw_cmds32, arg, len32)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + kfree(phw_cmds32); + return -EFAULT; + } + len = sizeof(struct msm_jpeg_hw_cmds) + + sizeof(struct msm_jpeg_hw_cmd) * (m - 1); + phw_cmds = kmalloc(len, GFP_KERNEL); + if (!phw_cmds) { + JPEG_PR_ERR("%s:%d] no mem %d\n", __func__, __LINE__, len); + kfree(phw_cmds32); + return -EFAULT; + } + (phw_cmds)->m = m; + while (m--) { + struct msm_jpeg_hw_cmd32 *src; + struct msm_jpeg_hw_cmd *dst; + src = &phw_cmds32->hw_cmd[m]; + dst = &(phw_cmds)->hw_cmd[m]; + msm_jpeg_get_hw_cmd32(dst, src, 0); + } + + is_copy_to_user = msm_jpeg_hw_exec_cmds(phw_cmds->hw_cmd, phw_cmds->m, + pgmn_dev->res_size, pgmn_dev->base); + + if (is_copy_to_user >= 0) { + m = phw_cmds->m; + while (m--) { + struct msm_jpeg_hw_cmd *src; + struct msm_jpeg_hw_cmd32 *dst; + dst = &phw_cmds32->hw_cmd[m]; + src = &phw_cmds->hw_cmd[m]; + + msm_jpeg_put_hw_cmd32(dst, src, 0); + } + if (copy_to_user(arg, phw_cmds32, len32)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + kfree(phw_cmds); + kfree(phw_cmds32); + return -EFAULT; + } + + } else { + kfree(phw_cmds); + kfree(phw_cmds32); + return is_copy_to_user; + } + kfree(phw_cmds); + kfree(phw_cmds32); + + return 0; +} +int msm_jpeg_ioctl_hw_cmd32(struct msm_jpeg_device *pgmn_dev, + void * __user arg) +{ + struct msm_jpeg_hw_cmd hw_cmd; + int is_copy_to_user; + + if (msm_jpeg_get_hw_cmd32(&hw_cmd, arg, 1)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + + is_copy_to_user = msm_jpeg_hw_exec_cmds(&hw_cmd, 1, + pgmn_dev->res_size, pgmn_dev->base); + JPEG_DBG("%s:%d] type %d, n %d, offst %d, mask %x, data %x pdata %lx\n", + __func__, __LINE__, hw_cmd.type, hw_cmd.n, hw_cmd.offset, + hw_cmd.mask, hw_cmd.data, (unsigned long) hw_cmd.pdata); + + if (is_copy_to_user >= 0) { + if (msm_jpeg_put_hw_cmd32(arg, &hw_cmd, 1)) { + JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__); + return -EFAULT; + } + } else + return is_copy_to_user; + + + return 0; +} + +long __msm_jpeg_compat_ioctl(struct msm_jpeg_device *pgmn_dev, + unsigned int cmd, unsigned long arg) +{ + int rc = 0; + struct msm_jpeg_ctrl_cmd *pctrl_cmd = NULL, ctrl_cmd; + struct msm_jpeg_buf jpeg_buf; + mm_segment_t old_fs; + + old_fs = get_fs(); + + switch (cmd) { + case MSM_JPEG_IOCTL_GET_HW_VERSION: + JPEG_DBG("%s:%d] VERSION 1\n", __func__, __LINE__); + rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg); + break; + case MSM_JPEG_IOCTL_GET_HW_VERSION32: + JPEG_DBG("%s:%d] VERSION 1 32bit\n", __func__, __LINE__); + rc = msm_jpeg_ioctl_hw_cmd32(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_RESET: + rc = msm_jpeg_ioctl_reset(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_RESET32: + rc = msm_jpeg_get_ctrl_cmd32(&ctrl_cmd, + (void __user *) arg); + if (rc < 0) + break; + + set_fs(KERNEL_DS); + rc = msm_jpeg_ioctl_reset(pgmn_dev, (void __user *) &ctrl_cmd); + set_fs(old_fs); + kfree(pctrl_cmd); + break; + + case MSM_JPEG_IOCTL_STOP: + rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg); + pgmn_dev->state = MSM_JPEG_STOPPED; + break; + + case MSM_JPEG_IOCTL_STOP32: + rc = msm_jpeg_ioctl_hw_cmds32(pgmn_dev, (void __user *) arg); + pgmn_dev->state = MSM_JPEG_STOPPED; + break; + + case MSM_JPEG_IOCTL_START: + rc = msm_jpeg_start(pgmn_dev, (void __user *) arg, + msm_jpeg_ioctl_hw_cmds); + break; + + case MSM_JPEG_IOCTL_START32: + rc = msm_jpeg_start(pgmn_dev, (void __user *) arg, + msm_jpeg_ioctl_hw_cmds32); + break; + + case MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE: + rc = msm_jpeg_input_buf_enqueue(pgmn_dev, + (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE32: + rc = msm_jpeg_get_jpeg_buf32(&jpeg_buf, (void __user *) arg); + if (rc < 0) + break; + set_fs(KERNEL_DS); + rc = msm_jpeg_input_buf_enqueue(pgmn_dev, + (void __user *) &jpeg_buf); + set_fs(old_fs); + break; + + case MSM_JPEG_IOCTL_INPUT_GET: + rc = msm_jpeg_input_get(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_INPUT_GET32: + set_fs(KERNEL_DS); + rc = msm_jpeg_input_get(pgmn_dev, (void __user *) &jpeg_buf); + set_fs(old_fs); + if (rc < 0) + break; + rc = msm_jpeg_put_jpeg_buf32(&jpeg_buf, (void __user *) arg); + + break; + + case MSM_JPEG_IOCTL_INPUT_GET_UNBLOCK: + rc = msm_jpeg_input_get_unblock(pgmn_dev); + break; + + case MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE: + rc = msm_jpeg_output_buf_enqueue(pgmn_dev, + (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE32: + rc = msm_jpeg_get_jpeg_buf32(&jpeg_buf, (void __user *) arg); + if (rc < 0) + break; + set_fs(KERNEL_DS); + rc = msm_jpeg_output_buf_enqueue(pgmn_dev, + (void __user *) &jpeg_buf); + set_fs(old_fs); + break; + + case MSM_JPEG_IOCTL_OUTPUT_GET: + rc = msm_jpeg_output_get(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_OUTPUT_GET32: + set_fs(KERNEL_DS); + rc = msm_jpeg_output_get(pgmn_dev, (void __user *) &jpeg_buf); + set_fs(old_fs); + if (rc < 0) + break; + rc = msm_jpeg_put_jpeg_buf32(&jpeg_buf, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_OUTPUT_GET_UNBLOCK: + rc = msm_jpeg_output_get_unblock(pgmn_dev); + break; + + case MSM_JPEG_IOCTL_EVT_GET: + rc = msm_jpeg_evt_get(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_EVT_GET32: + set_fs(KERNEL_DS); + rc = msm_jpeg_evt_get(pgmn_dev, (void __user *) &ctrl_cmd); + set_fs(old_fs); + if (rc < 0) + break; + msm_jpeg_put_ctrl_cmd32(&ctrl_cmd, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_EVT_GET_UNBLOCK: + rc = msm_jpeg_evt_get_unblock(pgmn_dev); + break; + + case MSM_JPEG_IOCTL_HW_CMD32: + rc = msm_jpeg_ioctl_hw_cmd32(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_HW_CMD: + rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_HW_CMDS32: + rc = msm_jpeg_ioctl_hw_cmds32(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_HW_CMDS: + rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_TEST_DUMP_REGION: + rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg); + break; + + case MSM_JPEG_IOCTL_TEST_DUMP_REGION32: + rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg); + break; + + case MSM_JPEG_IOCTL_SET_CLK_RATE: + rc = msm_jpeg_ioctl_set_clk_rate(pgmn_dev, + (void __user *) arg); + break; + + default: + JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n", + __func__, __LINE__, _IOC_NR(cmd)); + rc = -EINVAL; + break; + } + return rc; +} +#else +long __msm_jpeg_compat_ioctl(struct msm_jpeg_device *pgmn_dev, + unsigned int cmd, unsigned long arg) +{ + return 0; +} +#endif + +long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev, + unsigned int cmd, unsigned long arg) +{ + int rc = 0; + switch (cmd) { + case MSM_JPEG_IOCTL_GET_HW_VERSION: + JPEG_DBG("%s:%d] VERSION 1\n", __func__, __LINE__); + rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_RESET: + rc = msm_jpeg_ioctl_reset(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_STOP: + rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg); + pgmn_dev->state = MSM_JPEG_STOPPED; + break; + + case MSM_JPEG_IOCTL_START: + rc = msm_jpeg_start(pgmn_dev, (void __user *) arg, + msm_jpeg_ioctl_hw_cmds); + break; + + case MSM_JPEG_IOCTL_INPUT_BUF_ENQUEUE: + rc = msm_jpeg_input_buf_enqueue(pgmn_dev, + (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_INPUT_GET: + rc = msm_jpeg_input_get(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_INPUT_GET_UNBLOCK: + rc = msm_jpeg_input_get_unblock(pgmn_dev); + break; + + case MSM_JPEG_IOCTL_OUTPUT_BUF_ENQUEUE: + rc = msm_jpeg_output_buf_enqueue(pgmn_dev, + (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_OUTPUT_GET: + rc = msm_jpeg_output_get(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_OUTPUT_GET_UNBLOCK: + rc = msm_jpeg_output_get_unblock(pgmn_dev); + break; + + case MSM_JPEG_IOCTL_EVT_GET: + rc = msm_jpeg_evt_get(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_EVT_GET_UNBLOCK: + rc = msm_jpeg_evt_get_unblock(pgmn_dev); + break; + + case MSM_JPEG_IOCTL_HW_CMD: + rc = msm_jpeg_ioctl_hw_cmd(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_HW_CMDS: + rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, (void __user *) arg); + break; + + case MSM_JPEG_IOCTL_TEST_DUMP_REGION: + rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg); + break; + + case MSM_JPEG_IOCTL_SET_CLK_RATE: + rc = msm_jpeg_ioctl_set_clk_rate(pgmn_dev, (void __user *) arg); + break; + default: + pr_err_ratelimited("%s:%d] cmd = %d not supported\n", + __func__, __LINE__, _IOC_NR(cmd)); + rc = -EINVAL; + break; + } + return rc; +} + +int __msm_jpeg_init(struct msm_jpeg_device *pgmn_dev) +{ + int rc = 0; + int idx = 0; + + char *iommu_name[JPEG_DEV_CNT] = {"jpeg_enc0", "jpeg_enc1", + "jpeg_dec", "jpeg_dma"}; + + + mutex_init(&pgmn_dev->lock); + + pr_err("%s:%d] Jpeg Device id %d", __func__, __LINE__, + pgmn_dev->pdev->id); + idx = pgmn_dev->pdev->id; + pgmn_dev->idx = idx; + pgmn_dev->decode_flag = (idx == JPEG_DEC_ID); + + msm_jpeg_q_init("evt_q", &pgmn_dev->evt_q); + msm_jpeg_q_init("output_rtn_q", &pgmn_dev->output_rtn_q); + msm_jpeg_q_init("output_buf_q", &pgmn_dev->output_buf_q); + msm_jpeg_q_init("input_rtn_q", &pgmn_dev->input_rtn_q); + msm_jpeg_q_init("input_buf_q", &pgmn_dev->input_buf_q); + + /*get device context for IOMMU*/ + rc = cam_smmu_get_handle(iommu_name[idx], &pgmn_dev->iommu_hdl); + JPEG_DBG("%s:%d] hdl %d", __func__, __LINE__, + pgmn_dev->iommu_hdl); + if (rc < 0) { + JPEG_PR_ERR("%s: No iommu fw context found\n", + __func__); + goto err_smmu; + } + + /* setup all the resources for the jpeg driver */ + rc = msm_jpeg_platform_setup(pgmn_dev); + if (rc < 0) { + JPEG_PR_ERR("%s: setup failed\n", + __func__); + goto err_setup; + } + + return rc; +err_setup: +err_smmu: + mutex_destroy(&pgmn_dev->lock); + return -EFAULT; +} + +int __msm_jpeg_exit(struct msm_jpeg_device *pgmn_dev) +{ + msm_jpeg_platform_cleanup(pgmn_dev); + mutex_destroy(&pgmn_dev->lock); + kfree(pgmn_dev); + return 0; +} |
