M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@ -0,0 +1,3 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
EXTRA_CFLAGS += -Idrivers/media/platform/msm/camera_v1
obj-$(CONFIG_MSM_GEMINI) += msm_gemini_dev.o msm_gemini_sync.o msm_gemini_core.o msm_gemini_hw.o msm_gemini_platform.o

View File

@ -0,0 +1,39 @@
/* Copyright (c) 2010, 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.
*/
#ifndef MSM_GEMINI_COMMON_H
#define MSM_GEMINI_COMMON_H
#define MSM_GEMINI_DEBUG
#ifdef MSM_GEMINI_DEBUG
#define GMN_DBG(fmt, args...) pr_debug(fmt, ##args)
#else
#define GMN_DBG(fmt, args...) do { } while (0)
#endif
#define GMN_PR_ERR pr_err
enum GEMINI_MODE {
GEMINI_MODE_DISABLE,
GEMINI_MODE_OFFLINE,
GEMINI_MODE_REALTIME,
GEMINI_MODE_REALTIME_ROTATION
};
enum GEMINI_ROTATION {
GEMINI_ROTATION_0,
GEMINI_ROTATION_90,
GEMINI_ROTATION_180,
GEMINI_ROTATION_270
};
#endif /* MSM_GEMINI_COMMON_H */

View File

@ -0,0 +1,250 @@
/* Copyright (c) 2010-2013, 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 "msm_gemini_hw.h"
#include "msm_gemini_core.h"
#include "msm_gemini_platform.h"
#include "msm_gemini_common.h"
static struct msm_gemini_hw_pingpong fe_pingpong_buf;
static struct msm_gemini_hw_pingpong we_pingpong_buf;
static int we_pingpong_index;
static int reset_done_ack;
static spinlock_t reset_lock;
static wait_queue_head_t reset_wait;
int msm_gemini_core_reset(uint8_t op_mode, void *base, int size)
{
unsigned long flags;
int rc = 0;
int tm = 500; /*500ms*/
memset(&fe_pingpong_buf, 0, sizeof(fe_pingpong_buf));
fe_pingpong_buf.is_fe = 1;
we_pingpong_index = 0;
memset(&we_pingpong_buf, 0, sizeof(we_pingpong_buf));
spin_lock_irqsave(&reset_lock, flags);
reset_done_ack = 0;
msm_gemini_hw_reset(base, size);
spin_unlock_irqrestore(&reset_lock, flags);
rc = wait_event_interruptible_timeout(
reset_wait,
reset_done_ack,
msecs_to_jiffies(tm));
if (!reset_done_ack) {
GMN_DBG("%s: reset ACK failed %d", __func__, rc);
return -EBUSY;
}
GMN_DBG("%s: reset_done_ack rc %d", __func__, rc);
spin_lock_irqsave(&reset_lock, flags);
reset_done_ack = 0;
spin_unlock_irqrestore(&reset_lock, flags);
if (op_mode == MSM_GEMINI_MODE_REALTIME_ENCODE) {
/* Nothing needed for fe buffer cfg, config we only */
msm_gemini_hw_we_buffer_cfg(1);
} else {
/* Nothing needed for fe buffer cfg, config we only */
msm_gemini_hw_we_buffer_cfg(0);
}
/* @todo wait for reset done irq */
return 0;
}
void msm_gemini_core_release(int release_buf)
{
int i = 0;
for (i = 0; i < 2; i++) {
if (we_pingpong_buf.buf_status[i] && release_buf)
msm_gemini_platform_p2v(we_pingpong_buf.buf[i].file,
&we_pingpong_buf.buf[i].handle);
we_pingpong_buf.buf_status[i] = 0;
}
}
void msm_gemini_core_init(void)
{
init_waitqueue_head(&reset_wait);
spin_lock_init(&reset_lock);
}
int msm_gemini_core_fe_start(void)
{
msm_gemini_hw_fe_start();
return 0;
}
/* fetch engine */
int msm_gemini_core_fe_buf_update(struct msm_gemini_core_buf *buf)
{
GMN_DBG("%s:%d] 0x%08x %d 0x%08x %d\n", __func__, __LINE__,
(int) buf->y_buffer_addr, buf->y_len,
(int) buf->cbcr_buffer_addr, buf->cbcr_len);
return msm_gemini_hw_pingpong_update(&fe_pingpong_buf, buf);
}
void *msm_gemini_core_fe_pingpong_irq(int gemini_irq_status, void *context)
{
return msm_gemini_hw_pingpong_irq(&fe_pingpong_buf);
}
/* write engine */
int msm_gemini_core_we_buf_update(struct msm_gemini_core_buf *buf)
{
int rc;
GMN_DBG("%s:%d] 0x%08x 0x%08x %d\n", __func__, __LINE__,
(int) buf->y_buffer_addr, (int) buf->cbcr_buffer_addr,
buf->y_len);
we_pingpong_buf.buf_status[we_pingpong_index] = 0;
we_pingpong_index = (we_pingpong_index + 1)%2;
rc = msm_gemini_hw_pingpong_update(&we_pingpong_buf, buf);
return 0;
}
int msm_gemini_core_we_buf_reset(struct msm_gemini_hw_buf *buf)
{
int i = 0;
for (i = 0; i < 2; i++) {
if (we_pingpong_buf.buf[i].y_buffer_addr
== buf->y_buffer_addr)
we_pingpong_buf.buf_status[i] = 0;
}
return 0;
}
void *msm_gemini_core_we_pingpong_irq(int gemini_irq_status, void *context)
{
GMN_DBG("%s:%d]\n", __func__, __LINE__);
return msm_gemini_hw_pingpong_irq(&we_pingpong_buf);
}
void *msm_gemini_core_framedone_irq(int gemini_irq_status, void *context)
{
struct msm_gemini_hw_buf *buf_p;
GMN_DBG("%s:%d]\n", __func__, __LINE__);
buf_p = msm_gemini_hw_pingpong_active_buffer(&we_pingpong_buf);
if (buf_p) {
buf_p->framedone_len = msm_gemini_hw_encode_output_size();
pr_debug("%s:%d] framedone_len %d\n", __func__, __LINE__,
buf_p->framedone_len);
}
return buf_p;
}
void *msm_gemini_core_reset_ack_irq(int gemini_irq_status, void *context)
{
/* @todo return the status back to msm_gemini_core_reset */
GMN_DBG("%s:%d]\n", __func__, __LINE__);
return NULL;
}
void *msm_gemini_core_err_irq(int gemini_irq_status, void *context)
{
GMN_PR_ERR("%s:%d]\n", __func__, gemini_irq_status);
return NULL;
}
static int (*msm_gemini_irq_handler) (int, void *, void *);
irqreturn_t msm_gemini_core_irq(int irq_num, void *context)
{
void *data = NULL;
unsigned long flags;
int gemini_irq_status;
GMN_DBG("%s:%d] irq_num = %d\n", __func__, __LINE__, irq_num);
spin_lock_irqsave(&reset_lock, flags);
reset_done_ack = 1;
spin_unlock_irqrestore(&reset_lock, flags);
gemini_irq_status = msm_gemini_hw_irq_get_status();
GMN_DBG("%s:%d] gemini_irq_status = %0x\n", __func__, __LINE__,
gemini_irq_status);
/*For reset and framedone IRQs, clear all bits*/
if (gemini_irq_status & 0x400) {
wake_up(&reset_wait);
msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK,
JPEG_IRQ_CLEAR_ALL);
} else if (gemini_irq_status & 0x1) {
msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK,
JPEG_IRQ_CLEAR_ALL);
} else {
msm_gemini_hw_irq_clear(HWIO_JPEG_IRQ_CLEAR_RMSK,
gemini_irq_status);
}
if (msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) {
data = msm_gemini_core_framedone_irq(gemini_irq_status,
context);
if (msm_gemini_irq_handler)
msm_gemini_irq_handler(
MSM_GEMINI_HW_MASK_COMP_FRAMEDONE,
context, data);
}
if (msm_gemini_hw_irq_is_fe_pingpong(gemini_irq_status)) {
data = msm_gemini_core_fe_pingpong_irq(gemini_irq_status,
context);
if (msm_gemini_irq_handler)
msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_FE,
context, data);
}
if (msm_gemini_hw_irq_is_we_pingpong(gemini_irq_status) &&
!msm_gemini_hw_irq_is_frame_done(gemini_irq_status)) {
data = msm_gemini_core_we_pingpong_irq(gemini_irq_status,
context);
if (msm_gemini_irq_handler)
msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_WE,
context, data);
}
if (msm_gemini_hw_irq_is_reset_ack(gemini_irq_status)) {
data = msm_gemini_core_reset_ack_irq(gemini_irq_status,
context);
if (msm_gemini_irq_handler)
msm_gemini_irq_handler(
MSM_GEMINI_HW_MASK_COMP_RESET_ACK,
context, data);
}
/* Unexpected/unintended HW interrupt */
if (msm_gemini_hw_irq_is_err(gemini_irq_status)) {
data = msm_gemini_core_err_irq(gemini_irq_status, context);
if (msm_gemini_irq_handler)
msm_gemini_irq_handler(MSM_GEMINI_HW_MASK_COMP_ERR,
context, data);
}
return IRQ_HANDLED;
}
void msm_gemini_core_irq_install(int (*irq_handler) (int, void *, void *))
{
msm_gemini_irq_handler = irq_handler;
}
void msm_gemini_core_irq_remove(void)
{
msm_gemini_irq_handler = NULL;
}

View File

@ -0,0 +1,35 @@
/* Copyright (c) 2010, 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.
*/
#ifndef MSM_GEMINI_CORE_H
#define MSM_GEMINI_CORE_H
#include <linux/interrupt.h>
#include "msm_gemini_hw.h"
#define msm_gemini_core_buf msm_gemini_hw_buf
irqreturn_t msm_gemini_core_irq(int irq_num, void *context);
void msm_gemini_core_irq_install(int (*irq_handler) (int, void *, void *));
void msm_gemini_core_irq_remove(void);
int msm_gemini_core_fe_buf_update(struct msm_gemini_core_buf *buf);
int msm_gemini_core_we_buf_update(struct msm_gemini_core_buf *buf);
int msm_gemini_core_we_buf_reset(struct msm_gemini_hw_buf *buf);
int msm_gemini_core_reset(uint8_t op_mode, void *base, int size);
int msm_gemini_core_fe_start(void);
void msm_gemini_core_release(int);
void msm_gemini_core_init(void);
#endif /* MSM_GEMINI_CORE_H */

View File

@ -0,0 +1,266 @@
/* Copyright (c) 2010-2011, 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/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <mach/board.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <media/msm_gemini.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include "msm.h"
#include "msm_gemini_sync.h"
#include "msm_gemini_common.h"
#define MSM_GEMINI_NAME "gemini"
static int msm_gemini_open(struct inode *inode, struct file *filp)
{
int rc;
struct msm_gemini_device *pgmn_dev = container_of(inode->i_cdev,
struct msm_gemini_device, cdev);
filp->private_data = pgmn_dev;
GMN_DBG("%s:%d]\n", __func__, __LINE__);
rc = __msm_gemini_open(pgmn_dev);
GMN_DBG(KERN_INFO "%s:%d] %s open_count = %d\n", __func__, __LINE__,
filp->f_path.dentry->d_name.name, pgmn_dev->open_count);
return rc;
}
static int msm_gemini_release(struct inode *inode, struct file *filp)
{
int rc;
struct msm_gemini_device *pgmn_dev = filp->private_data;
GMN_DBG(KERN_INFO "%s:%d]\n", __func__, __LINE__);
rc = __msm_gemini_release(pgmn_dev);
GMN_DBG(KERN_INFO "%s:%d] %s open_count = %d\n", __func__, __LINE__,
filp->f_path.dentry->d_name.name, pgmn_dev->open_count);
return rc;
}
static long msm_gemini_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int rc;
struct msm_gemini_device *pgmn_dev = filp->private_data;
GMN_DBG("%s:%d] cmd=%d pgmn_dev=0x%x arg=0x%x\n", __func__,
__LINE__, _IOC_NR(cmd), (uint32_t)pgmn_dev, (uint32_t)arg);
rc = __msm_gemini_ioctl(pgmn_dev, cmd, arg);
GMN_DBG("%s:%d]\n", __func__, __LINE__);
return rc;
}
static const struct file_operations msm_gemini_fops = {
.owner = THIS_MODULE,
.open = msm_gemini_open,
.release = msm_gemini_release,
.unlocked_ioctl = msm_gemini_ioctl,
};
static struct class *msm_gemini_class;
static dev_t msm_gemini_devno;
struct msm_gemini_device *msm_gemini_device_p;
int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd)
{
int rc;
struct msm_gemini_device *pgmn_dev =
(struct msm_gemini_device *)gemini_sd->host_priv;
GMN_DBG("%s:%d: gemini_sd=0x%x pgmn_dev=0x%x\n",
__func__, __LINE__, (uint32_t)gemini_sd, (uint32_t)pgmn_dev);
rc = __msm_gemini_open(pgmn_dev);
GMN_DBG("%s:%d: rc=%d\n",
__func__, __LINE__, rc);
return rc;
}
static long msm_gemini_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
long rc;
struct msm_gemini_device *pgmn_dev =
(struct msm_gemini_device *)sd->host_priv;
GMN_DBG("%s: cmd=%d\n", __func__, cmd);
GMN_DBG("%s: pgmn_dev 0x%x", __func__, (uint32_t)pgmn_dev);
GMN_DBG("%s: Calling __msm_gemini_ioctl\n", __func__);
rc = __msm_gemini_ioctl(pgmn_dev, cmd, (unsigned long)arg);
pr_debug("%s: X\n", __func__);
return rc;
}
void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd)
{
int rc;
struct msm_gemini_device *pgmn_dev =
(struct msm_gemini_device *)gemini_sd->host_priv;
GMN_DBG("%s:pgmn_dev=0x%x", __func__, (uint32_t)pgmn_dev);
rc = __msm_gemini_release(pgmn_dev);
GMN_DBG("%s:rc=%d", __func__, rc);
}
static const struct v4l2_subdev_core_ops msm_gemini_subdev_core_ops = {
.ioctl = msm_gemini_subdev_ioctl,
};
static const struct v4l2_subdev_ops msm_gemini_subdev_ops = {
.core = &msm_gemini_subdev_core_ops,
};
static int msm_gemini_init(struct platform_device *pdev)
{
int rc = -1;
struct device *dev;
GMN_DBG("%s:\n", __func__);
msm_gemini_device_p = __msm_gemini_init(pdev);
if (msm_gemini_device_p == NULL) {
GMN_PR_ERR("%s: initialization failed\n", __func__);
goto fail;
}
v4l2_subdev_init(&msm_gemini_device_p->subdev, &msm_gemini_subdev_ops);
v4l2_set_subdev_hostdata(&msm_gemini_device_p->subdev,
msm_gemini_device_p);
pr_debug("%s: msm_gemini_device_p 0x%x", __func__,
(uint32_t)msm_gemini_device_p);
GMN_DBG("%s:gemini: platform_set_drvdata\n", __func__);
platform_set_drvdata(pdev, &msm_gemini_device_p->subdev);
rc = alloc_chrdev_region(&msm_gemini_devno, 0, 1, MSM_GEMINI_NAME);
if (rc < 0) {
GMN_PR_ERR("%s: failed to allocate chrdev\n", __func__);
goto fail_1;
}
if (!msm_gemini_class) {
msm_gemini_class = class_create(THIS_MODULE, MSM_GEMINI_NAME);
if (IS_ERR(msm_gemini_class)) {
rc = PTR_ERR(msm_gemini_class);
GMN_PR_ERR("%s: create device class failed\n",
__func__);
goto fail_2;
}
}
dev = device_create(msm_gemini_class, NULL,
MKDEV(MAJOR(msm_gemini_devno), MINOR(msm_gemini_devno)), NULL,
"%s%d", MSM_GEMINI_NAME, 0);
if (IS_ERR(dev)) {
GMN_PR_ERR("%s: error creating device\n", __func__);
rc = -ENODEV;
goto fail_3;
}
cdev_init(&msm_gemini_device_p->cdev, &msm_gemini_fops);
msm_gemini_device_p->cdev.owner = THIS_MODULE;
msm_gemini_device_p->cdev.ops =
(const struct file_operations *) &msm_gemini_fops;
rc = cdev_add(&msm_gemini_device_p->cdev, msm_gemini_devno, 1);
if (rc < 0) {
GMN_PR_ERR("%s: error adding cdev\n", __func__);
rc = -ENODEV;
goto fail_4;
}
GMN_DBG("%s %s: success\n", __func__, MSM_GEMINI_NAME);
return rc;
fail_4:
device_destroy(msm_gemini_class, msm_gemini_devno);
fail_3:
class_destroy(msm_gemini_class);
fail_2:
unregister_chrdev_region(msm_gemini_devno, 1);
fail_1:
__msm_gemini_exit(msm_gemini_device_p);
fail:
return rc;
}
static void msm_gemini_exit(void)
{
cdev_del(&msm_gemini_device_p->cdev);
device_destroy(msm_gemini_class, msm_gemini_devno);
class_destroy(msm_gemini_class);
unregister_chrdev_region(msm_gemini_devno, 1);
__msm_gemini_exit(msm_gemini_device_p);
}
static int __msm_gemini_probe(struct platform_device *pdev)
{
return msm_gemini_init(pdev);
}
static int __msm_gemini_remove(struct platform_device *pdev)
{
msm_gemini_exit();
return 0;
}
static struct platform_driver msm_gemini_driver = {
.probe = __msm_gemini_probe,
.remove = __msm_gemini_remove,
.driver = {
.name = MSM_GEMINI_DRV_NAME,
.owner = THIS_MODULE,
},
};
static int __init msm_gemini_driver_init(void)
{
int rc;
rc = platform_driver_register(&msm_gemini_driver);
return rc;
}
static void __exit msm_gemini_driver_exit(void)
{
platform_driver_unregister(&msm_gemini_driver);
}
MODULE_DESCRIPTION("msm gemini jpeg driver");
MODULE_VERSION("msm gemini 0.1");
module_init(msm_gemini_driver_init);
module_exit(msm_gemini_driver_exit);

View File

@ -0,0 +1,525 @@
/* Copyright (c) 2010,2013 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/delay.h>
#include "msm_gemini_hw.h"
#include "msm_gemini_common.h"
#include <linux/io.h>
static void *gemini_region_base;
static uint32_t gemini_region_size;
int msm_gemini_hw_pingpong_update(struct msm_gemini_hw_pingpong *pingpong_hw,
struct msm_gemini_hw_buf *buf)
{
int buf_free_index = -1;
if (!pingpong_hw->buf_status[0]) {
buf_free_index = 0;
} else if (!pingpong_hw->buf_status[1]) {
buf_free_index = 1;
} else {
GMN_PR_ERR("%s:%d: pingpong buffer busy\n", __func__, __LINE__);
return -1;
}
pingpong_hw->buf[buf_free_index] = *buf;
pingpong_hw->buf_status[buf_free_index] = 1;
if (pingpong_hw->is_fe) {
/* it is fe */
msm_gemini_hw_fe_buffer_update(
&pingpong_hw->buf[buf_free_index], buf_free_index);
} else {
/* it is we */
msm_gemini_hw_we_buffer_update(
&pingpong_hw->buf[buf_free_index], buf_free_index);
}
return 0;
}
void *msm_gemini_hw_pingpong_irq(struct msm_gemini_hw_pingpong *pingpong_hw)
{
struct msm_gemini_hw_buf *buf_p = NULL;
if (pingpong_hw->buf_status[pingpong_hw->buf_active_index]) {
buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
pingpong_hw->buf_status[pingpong_hw->buf_active_index] = 0;
}
pingpong_hw->buf_active_index = !pingpong_hw->buf_active_index;
return (void *) buf_p;
}
void *msm_gemini_hw_pingpong_active_buffer(
struct msm_gemini_hw_pingpong *pingpong_hw)
{
struct msm_gemini_hw_buf *buf_p = NULL;
if (pingpong_hw->buf_status[pingpong_hw->buf_active_index])
buf_p = &pingpong_hw->buf[pingpong_hw->buf_active_index];
return (void *) buf_p;
}
struct msm_gemini_hw_cmd hw_cmd_irq_get_status[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_READ, 1, HWIO_JPEG_IRQ_STATUS_ADDR,
HWIO_JPEG_IRQ_STATUS_RMSK, {0} },
};
int msm_gemini_hw_irq_get_status(void)
{
uint32_t n_irq_status = 0;
rmb();
n_irq_status = msm_gemini_hw_read(&hw_cmd_irq_get_status[0]);
rmb();
return n_irq_status;
}
struct msm_gemini_hw_cmd hw_cmd_encode_output_size[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_READ, 1,
HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_ADDR,
HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_RMSK, {0} },
};
long msm_gemini_hw_encode_output_size(void)
{
uint32_t encode_output_size = 0;
encode_output_size = msm_gemini_hw_read(&hw_cmd_encode_output_size[0]);
return encode_output_size;
}
struct msm_gemini_hw_cmd hw_cmd_irq_clear[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_IRQ_CLEAR_ADDR,
HWIO_JPEG_IRQ_CLEAR_RMSK, {JPEG_IRQ_CLEAR_ALL} },
};
void msm_gemini_hw_irq_clear(uint32_t mask, uint32_t data)
{
GMN_DBG("%s:%d] mask %0x data %0x", __func__, __LINE__, mask, data);
hw_cmd_irq_clear[0].mask = mask;
hw_cmd_irq_clear[0].data = data;
msm_gemini_hw_write(&hw_cmd_irq_clear[0]);
}
struct msm_gemini_hw_cmd hw_cmd_fe_ping_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_BUFFER_CFG_ADDR,
HWIO_JPEG_FE_BUFFER_CFG_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_Y_PING_ADDR_ADDR,
HWIO_JPEG_FE_Y_PING_ADDR_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_CBCR_PING_ADDR_ADDR,
HWIO_JPEG_FE_CBCR_PING_ADDR_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_CMD_ADDR,
HWIO_JPEG_FE_CMD_RMSK, {JPEG_FE_CMD_BUFFERRELOAD} },
};
struct msm_gemini_hw_cmd hw_cmd_fe_pong_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_BUFFER_CFG_ADDR,
HWIO_JPEG_FE_BUFFER_CFG_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_Y_PONG_ADDR_ADDR,
HWIO_JPEG_FE_Y_PONG_ADDR_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_CBCR_PONG_ADDR_ADDR,
HWIO_JPEG_FE_CBCR_PONG_ADDR_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_CMD_ADDR,
HWIO_JPEG_FE_CMD_RMSK, {JPEG_FE_CMD_BUFFERRELOAD} },
};
void msm_gemini_hw_fe_buffer_update(struct msm_gemini_hw_buf *p_input,
uint8_t pingpong_index)
{
uint32_t n_reg_val = 0;
struct msm_gemini_hw_cmd *hw_cmd_p;
if (pingpong_index == 0) {
hw_cmd_p = &hw_cmd_fe_ping_update[0];
n_reg_val = ((((p_input->num_of_mcu_rows - 1) <<
HWIO_JPEG_FE_BUFFER_CFG_CBCR_MCU_ROWS_SHFT) &
HWIO_JPEG_FE_BUFFER_CFG_CBCR_MCU_ROWS_BMSK) |
(((p_input->num_of_mcu_rows - 1) <<
HWIO_JPEG_FE_BUFFER_CFG_Y_MCU_ROWS_SHFT) &
HWIO_JPEG_FE_BUFFER_CFG_Y_MCU_ROWS_BMSK));
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
n_reg_val = ((p_input->y_buffer_addr <<
HWIO_JPEG_FE_Y_PING_ADDR_FE_Y_PING_START_ADDR_SHFT) &
HWIO_JPEG_FE_Y_PING_ADDR_FE_Y_PING_START_ADDR_BMSK);
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
n_reg_val = ((p_input->cbcr_buffer_addr<<
HWIO_JPEG_FE_CBCR_PING_ADDR_FE_CBCR_PING_START_ADDR_SHFT) &
HWIO_JPEG_FE_CBCR_PING_ADDR_FE_CBCR_PING_START_ADDR_BMSK);
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
msm_gemini_hw_write(hw_cmd_p);
} else if (pingpong_index == 1) {
hw_cmd_p = &hw_cmd_fe_pong_update[0];
n_reg_val = ((((p_input->num_of_mcu_rows - 1) <<
HWIO_JPEG_FE_BUFFER_CFG_CBCR_MCU_ROWS_SHFT) &
HWIO_JPEG_FE_BUFFER_CFG_CBCR_MCU_ROWS_BMSK) |
(((p_input->num_of_mcu_rows - 1) <<
HWIO_JPEG_FE_BUFFER_CFG_Y_MCU_ROWS_SHFT) &
HWIO_JPEG_FE_BUFFER_CFG_Y_MCU_ROWS_BMSK));
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
n_reg_val = ((p_input->y_buffer_addr <<
HWIO_JPEG_FE_Y_PONG_ADDR_FE_Y_PONG_START_ADDR_SHFT) &
HWIO_JPEG_FE_Y_PONG_ADDR_FE_Y_PONG_START_ADDR_BMSK);
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
n_reg_val = ((p_input->cbcr_buffer_addr<<
HWIO_JPEG_FE_CBCR_PONG_ADDR_FE_CBCR_PONG_START_ADDR_SHFT) &
HWIO_JPEG_FE_CBCR_PONG_ADDR_FE_CBCR_PONG_START_ADDR_BMSK);
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
msm_gemini_hw_write(hw_cmd_p);
} else {
/* shall not get to here */
}
return;
}
struct msm_gemini_hw_cmd hw_cmd_fe_start[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_FE_CMD_ADDR,
HWIO_JPEG_FE_CMD_RMSK, {JPEG_OFFLINE_CMD_START} },
};
void msm_gemini_hw_fe_start(void)
{
msm_gemini_hw_write(&hw_cmd_fe_start[0]);
return;
}
struct msm_gemini_hw_cmd hw_cmd_we_buffer_cfg[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_Y_THRESHOLD_ADDR,
HWIO_JPEG_WE_Y_THRESHOLD_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_Y_UB_CFG_ADDR,
HWIO_JPEG_WE_Y_UB_CFG_RMSK, {JPEG_WE_YUB_ENCODE} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_CBCR_THRESHOLD_ADDR,
HWIO_JPEG_WE_CBCR_THRESHOLD_RMSK, {0} },
};
/* first dimension is WE_ASSERT_STALL_TH and WE_DEASSERT_STALL_TH
second dimension is for offline and real-time settings
*/
static const uint32_t GEMINI_WE_Y_THRESHOLD[2][2] = {
{ 0x00000190, 0x000001ff },
{ 0x0000016a, 0x000001ff }
};
/* first dimension is WE_ASSERT_STALL_TH and WE_DEASSERT_STALL_TH
second dimension is for offline and real-time settings
*/
static const uint32_t GEMINI_WE_CBCR_THRESHOLD[2][2] = {
{ 0x00000190, 0x000001ff },
{ 0x0000016a, 0x000001ff }
};
void msm_gemini_hw_we_buffer_cfg(uint8_t is_realtime)
{
uint32_t n_reg_val = 0;
struct msm_gemini_hw_cmd *hw_cmd_p = &hw_cmd_we_buffer_cfg[0];
n_reg_val = (((GEMINI_WE_Y_THRESHOLD[1][is_realtime] <<
HWIO_JPEG_WE_Y_THRESHOLD_WE_DEASSERT_STALL_TH_SHFT) &
HWIO_JPEG_WE_Y_THRESHOLD_WE_DEASSERT_STALL_TH_BMSK) |
((GEMINI_WE_Y_THRESHOLD[0][is_realtime] <<
HWIO_JPEG_WE_Y_THRESHOLD_WE_ASSERT_STALL_TH_SHFT) &
HWIO_JPEG_WE_Y_THRESHOLD_WE_ASSERT_STALL_TH_BMSK));
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
msm_gemini_hw_write(hw_cmd_p++);
/* @todo maybe not for realtime? */
n_reg_val = (((GEMINI_WE_CBCR_THRESHOLD[1][is_realtime] <<
HWIO_JPEG_WE_CBCR_THRESHOLD_WE_DEASSERT_STALL_TH_SHFT) &
HWIO_JPEG_WE_CBCR_THRESHOLD_WE_DEASSERT_STALL_TH_BMSK) |
((GEMINI_WE_CBCR_THRESHOLD[0][is_realtime] <<
HWIO_JPEG_WE_CBCR_THRESHOLD_WE_ASSERT_STALL_TH_SHFT) &
HWIO_JPEG_WE_CBCR_THRESHOLD_WE_ASSERT_STALL_TH_BMSK));
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p);
return;
}
struct msm_gemini_hw_cmd hw_cmd_we_ping_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_Y_PING_BUFFER_CFG_ADDR,
HWIO_JPEG_WE_Y_PING_BUFFER_CFG_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_Y_PING_ADDR_ADDR,
HWIO_JPEG_WE_Y_PING_ADDR_RMSK, {0} },
};
struct msm_gemini_hw_cmd hw_cmd_we_pong_update[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_ADDR,
HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_RMSK, {0} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_WE_Y_PONG_ADDR_ADDR,
HWIO_JPEG_WE_Y_PONG_ADDR_RMSK, {0} },
};
void msm_gemini_hw_we_buffer_update(struct msm_gemini_hw_buf *p_input,
uint8_t pingpong_index)
{
uint32_t n_reg_val = 0;
struct msm_gemini_hw_cmd *hw_cmd_p;
pr_debug("%s:%d] pingpong index %d", __func__, __LINE__,
pingpong_index);
if (pingpong_index == 0) {
hw_cmd_p = &hw_cmd_we_ping_update[0];
n_reg_val = ((p_input->y_len <<
HWIO_JPEG_WE_Y_PING_BUFFER_CFG_WE_BUFFER_LENGTH_SHFT) &
HWIO_JPEG_WE_Y_PING_BUFFER_CFG_WE_BUFFER_LENGTH_BMSK);
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
n_reg_val = p_input->y_buffer_addr;
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
} else if (pingpong_index == 1) {
hw_cmd_p = &hw_cmd_we_pong_update[0];
n_reg_val = ((p_input->y_len <<
HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_WE_BUFFER_LENGTH_SHFT) &
HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_WE_BUFFER_LENGTH_BMSK);
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
n_reg_val = p_input->y_buffer_addr;
hw_cmd_p->data = n_reg_val;
msm_gemini_hw_write(hw_cmd_p++);
} else {
/* shall not get to here */
}
return;
}
struct msm_gemini_hw_cmd hw_cmd_reset[] = {
/* type, repeat n times, offset, mask, data or pdata */
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_IRQ_MASK_ADDR,
HWIO_JPEG_IRQ_MASK_RMSK, {JPEG_IRQ_DISABLE_ALL} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_IRQ_CLEAR_ADDR,
HWIO_JPEG_IRQ_MASK_RMSK, {JPEG_IRQ_CLEAR_ALL} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_IRQ_MASK_ADDR,
HWIO_JPEG_IRQ_MASK_RMSK, {JPEG_IRQ_ALLSOURCES_ENABLE} },
{MSM_GEMINI_HW_CMD_TYPE_WRITE, 1, HWIO_JPEG_RESET_CMD_ADDR,
HWIO_JPEG_RESET_CMD_RMSK, {JPEG_RESET_DEFAULT} },
};
void msm_gemini_hw_init(void *base, int size)
{
gemini_region_base = base;
gemini_region_size = size;
}
void msm_gemini_hw_reset(void *base, int size)
{
struct msm_gemini_hw_cmd *hw_cmd_p;
hw_cmd_p = &hw_cmd_reset[0];
wmb();
msm_gemini_hw_write(hw_cmd_p++);
msm_gemini_hw_write(hw_cmd_p++);
msm_gemini_hw_write(hw_cmd_p++);
msm_gemini_hw_write(hw_cmd_p);
wmb();
return;
}
uint32_t msm_gemini_hw_read(struct msm_gemini_hw_cmd *hw_cmd_p)
{
uint32_t *paddr;
uint32_t data;
paddr = gemini_region_base + hw_cmd_p->offset;
data = readl(paddr);
data &= hw_cmd_p->mask;
GMN_DBG("%s:%d] type-%d n-%d offset-0x%4x mask-0x%8x data-0x%8x\n",
__func__, __LINE__, hw_cmd_p->type, hw_cmd_p->n,
hw_cmd_p->offset, hw_cmd_p->mask, data);
return data;
}
void msm_gemini_hw_write(struct msm_gemini_hw_cmd *hw_cmd_p)
{
uint32_t *paddr;
uint32_t old_data, new_data;
/* type, repeat n times, offset, mask, data or pdata */
GMN_DBG("%s:%d] type-%d n-%d offset-0x%4x mask-0x%8x data-0x%8x\n",
__func__, __LINE__, hw_cmd_p->type, hw_cmd_p->n,
hw_cmd_p->offset, hw_cmd_p->mask, hw_cmd_p->data);
paddr = gemini_region_base + hw_cmd_p->offset;
if (hw_cmd_p->mask == 0xffffffff) {
old_data = 0;
} else {
old_data = readl(paddr);
old_data &= ~hw_cmd_p->mask;
}
new_data = hw_cmd_p->data & hw_cmd_p->mask;
new_data |= old_data;
writel(new_data, paddr);
}
int msm_gemini_hw_wait(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us)
{
int tm = hw_cmd_p->n;
uint32_t data;
uint32_t wait_data = hw_cmd_p->data & hw_cmd_p->mask;
data = msm_gemini_hw_read(hw_cmd_p);
if (data != wait_data) {
while (tm) {
udelay(m_us);
data = msm_gemini_hw_read(hw_cmd_p);
if (data == wait_data)
break;
tm--;
}
}
hw_cmd_p->data = data;
return tm;
}
void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us)
{
int tm = hw_cmd_p->n;
while (tm) {
udelay(m_us);
tm--;
}
}
int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds)
{
int is_copy_to_user = -1;
uint32_t data;
while (m_cmds--) {
if (hw_cmd_p->offset > gemini_region_size) {
GMN_PR_ERR("%s:%d] %d exceed hw region %d\n", __func__,
__LINE__, hw_cmd_p->offset, gemini_region_size);
return -EFAULT;
}
switch (hw_cmd_p->type) {
case MSM_GEMINI_HW_CMD_TYPE_READ:
hw_cmd_p->data = msm_gemini_hw_read(hw_cmd_p);
is_copy_to_user = 1;
break;
case MSM_GEMINI_HW_CMD_TYPE_WRITE:
msm_gemini_hw_write(hw_cmd_p);
break;
case MSM_GEMINI_HW_CMD_TYPE_WRITE_OR:
data = msm_gemini_hw_read(hw_cmd_p);
hw_cmd_p->data = (hw_cmd_p->data & hw_cmd_p->mask) |
data;
msm_gemini_hw_write(hw_cmd_p);
break;
case MSM_GEMINI_HW_CMD_TYPE_UWAIT:
msm_gemini_hw_wait(hw_cmd_p, 1);
break;
case MSM_GEMINI_HW_CMD_TYPE_MWAIT:
msm_gemini_hw_wait(hw_cmd_p, 1000);
break;
case MSM_GEMINI_HW_CMD_TYPE_UDELAY:
msm_gemini_hw_delay(hw_cmd_p, 1);
break;
case MSM_GEMINI_HW_CMD_TYPE_MDELAY:
msm_gemini_hw_delay(hw_cmd_p, 1000);
break;
default:
GMN_PR_ERR("wrong hw command type\n");
break;
}
hw_cmd_p++;
}
return is_copy_to_user;
}
#ifdef MSM_GMN_DBG_DUMP
void msm_gemini_io_dump(int size)
{
char line_str[128], *p_str;
void __iomem *addr = gemini_region_base;
int i;
u32 *p = (u32 *) addr;
u32 data;
pr_info("%s: %p %d reg_size %d\n", __func__, addr, size,
gemini_region_size);
line_str[0] = '\0';
p_str = line_str;
for (i = 0; i < size/4; i++) {
if (i % 4 == 0) {
snprintf(p_str, 12, "%08x: ", (u32) p);
p_str += 10;
}
data = readl_relaxed(p++);
snprintf(p_str, 12, "%08x ", data);
p_str += 9;
if ((i + 1) % 4 == 0) {
pr_info("%s\n", line_str);
line_str[0] = '\0';
p_str = line_str;
}
}
if (line_str[0] != '\0')
pr_info("%s\n", line_str);
}
#else
void msm_gemini_io_dump(int size)
{
}
#endif

View File

@ -0,0 +1,104 @@
/* Copyright (c) 2010-2013, 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.
*/
#ifndef MSM_GEMINI_HW_H
#define MSM_GEMINI_HW_H
#include <media/msm_gemini.h>
#include "msm_gemini_hw_reg.h"
#include <linux/msm_ion.h>
#include <mach/iommu_domains.h>
struct msm_gemini_hw_buf {
struct msm_gemini_buf vbuf;
struct file *file;
uint32_t framedone_len;
uint32_t y_buffer_addr;
uint32_t y_len;
uint32_t cbcr_buffer_addr;
uint32_t cbcr_len;
uint32_t num_of_mcu_rows;
struct ion_handle *handle;
};
struct msm_gemini_hw_pingpong {
uint8_t is_fe; /* 1: fe; 0: we */
struct msm_gemini_hw_buf buf[2];
int buf_status[2];
int buf_active_index;
};
int msm_gemini_hw_pingpong_update(struct msm_gemini_hw_pingpong *pingpong_hw,
struct msm_gemini_hw_buf *buf);
void *msm_gemini_hw_pingpong_irq(struct msm_gemini_hw_pingpong *pingpong_hw);
void *msm_gemini_hw_pingpong_active_buffer(struct msm_gemini_hw_pingpong
*pingpong_hw);
void msm_gemini_hw_irq_clear(uint32_t, uint32_t);
int msm_gemini_hw_irq_get_status(void);
long msm_gemini_hw_encode_output_size(void);
#define MSM_GEMINI_HW_MASK_COMP_FRAMEDONE \
MSM_GEMINI_HW_IRQ_STATUS_FRAMEDONE_MASK
#define MSM_GEMINI_HW_MASK_COMP_FE \
MSM_GEMINI_HW_IRQ_STATUS_FE_RD_DONE_MASK
#define MSM_GEMINI_HW_MASK_COMP_WE \
(MSM_GEMINI_HW_IRQ_STATUS_WE_Y_PINGPONG_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK)
#define MSM_GEMINI_HW_MASK_COMP_RESET_ACK \
MSM_GEMINI_HW_IRQ_STATUS_RESET_ACK_MASK
#define MSM_GEMINI_HW_MASK_COMP_ERR \
(MSM_GEMINI_HW_IRQ_STATUS_FE_RTOVF_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_BUS_ERROR_MASK | \
MSM_GEMINI_HW_IRQ_STATUS_VIOLATION_MASK)
#define msm_gemini_hw_irq_is_frame_done(gemini_irq_status) \
(gemini_irq_status & MSM_GEMINI_HW_MASK_COMP_FRAMEDONE)
#define msm_gemini_hw_irq_is_fe_pingpong(gemini_irq_status) \
(gemini_irq_status & MSM_GEMINI_HW_MASK_COMP_FE)
#define msm_gemini_hw_irq_is_we_pingpong(gemini_irq_status) \
(gemini_irq_status & MSM_GEMINI_HW_MASK_COMP_WE)
#define msm_gemini_hw_irq_is_reset_ack(gemini_irq_status) \
(gemini_irq_status & MSM_GEMINI_HW_MASK_COMP_RESET_ACK)
#define msm_gemini_hw_irq_is_err(gemini_irq_status) \
(gemini_irq_status & MSM_GEMINI_HW_MASK_COMP_ERR)
void msm_gemini_hw_fe_buffer_update(struct msm_gemini_hw_buf *p_input,
uint8_t pingpong_index);
void msm_gemini_hw_we_buffer_update(struct msm_gemini_hw_buf *p_input,
uint8_t pingpong_index);
void msm_gemini_hw_we_buffer_cfg(uint8_t is_realtime);
void msm_gemini_hw_fe_start(void);
void msm_gemini_hw_clk_cfg(void);
void msm_gemini_hw_reset(void *base, int size);
void msm_gemini_hw_irq_cfg(void);
void msm_gemini_hw_init(void *base, int size);
uint32_t msm_gemini_hw_read(struct msm_gemini_hw_cmd *hw_cmd_p);
void msm_gemini_hw_write(struct msm_gemini_hw_cmd *hw_cmd_p);
int msm_gemini_hw_wait(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us);
void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us);
int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds);
void msm_gemini_io_dump(int size);
#define MSM_GEMINI_PIPELINE_CLK_128MHZ 128 /* 8MP 128MHz */
#define MSM_GEMINI_PIPELINE_CLK_140MHZ 140 /* 9MP 140MHz */
#define MSM_GEMINI_PIPELINE_CLK_200MHZ 153 /* 12MP 153MHz */
#endif /* MSM_GEMINI_HW_H */

View File

@ -0,0 +1,176 @@
/* Copyright (c) 2010, 2013, 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.
*/
#ifndef MSM_GEMINI_HW_REG_H
#define MSM_GEMINI_HW_REG_H
#define GEMINI_REG_BASE 0
#define MSM_GEMINI_HW_IRQ_MASK_ADDR 0x00000014
#define MSM_GEMINI_HW_IRQ_MASK_RMSK 0xffffffff
#define MSM_GEMINI_HW_IRQ_MASK_SHFT 0
#define MSM_GEMINI_HW_IRQ_DISABLE 0
#define MSM_GEMINI_HW_IRQ_ENABLE 0xffffffff
#define MSM_GEMINI_HW_IRQ_CLEAR_ADDR 0x00000018
#define MSM_GEMINI_HW_IRQ_CLEAR_RMSK 0xffffffff
#define MSM_GEMINI_HW_IRQ_CLEAR_SHFT 0
#define MSM_GEMINI_HW_IRQ_CLEAR 0xffffffff
#define MSM_GEMINI_HW_IRQ_STATUS_FRAMEDONE_MASK 0x00000001
#define MSM_GEMINI_HW_IRQ_STATUS_FRAMEDONE_SHIFT 0x00000000
#define MSM_GEMINI_HW_IRQ_STATUS_FE_RD_DONE_MASK 0x00000002
#define MSM_GEMINI_HW_IRQ_STATUS_FE_RD_DONE_SHIFT 0x00000001
#define MSM_GEMINI_HW_IRQ_STATUS_FE_RTOVF_MASK 0x00000004
#define MSM_GEMINI_HW_IRQ_STATUS_FE_RTOVF_SHIFT 0x00000002
#define MSM_GEMINI_HW_IRQ_STATUS_FE_VFE_OVERFLOW_MASK 0x00000008
#define MSM_GEMINI_HW_IRQ_STATUS_FE_VFE_OVERFLOW_SHIFT 0x00000003
#define MSM_GEMINI_HW_IRQ_STATUS_WE_Y_PINGPONG_MASK 0x00000010
#define MSM_GEMINI_HW_IRQ_STATUS_WE_Y_PINGPONG_SHIFT 0x00000004
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CBCR_PINGPONG_MASK 0x00000020
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CBCR_PINGPONG_SHIFT 0x00000005
#define MSM_GEMINI_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_MASK 0x00000040
#define MSM_GEMINI_HW_IRQ_STATUS_WE_Y_BUFFER_OVERFLOW_SHIFT 0x00000006
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_MASK 0x00000080
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CBCR_BUFFER_OVERFLOW_SHIFT 0x00000007
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_MASK 0x00000100
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CH0_DATAFIFO_OVERFLOW_SHIFT 0x00000008
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_MASK 0x00000200
#define MSM_GEMINI_HW_IRQ_STATUS_WE_CH1_DATAFIFO_OVERFLOW_SHIFT 0x00000009
#define MSM_GEMINI_HW_IRQ_STATUS_RESET_ACK_MASK 0x00000400
#define MSM_GEMINI_HW_IRQ_STATUS_RESET_ACK_SHIFT 0x0000000a
#define MSM_GEMINI_HW_IRQ_STATUS_BUS_ERROR_MASK 0x00000800
#define MSM_GEMINI_HW_IRQ_STATUS_BUS_ERROR_SHIFT 0x0000000b
#define MSM_GEMINI_HW_IRQ_STATUS_VIOLATION_MASK 0x00001000
#define MSM_GEMINI_HW_IRQ_STATUS_VIOLATION_SHIFT 0x0000000c
#define JPEG_BUS_CMD_HALT_REQ 0x00000001
#define JPEG_REALTIME_CMD_STOP_FB 0x00000000
#define JPEG_REALTIME_CMD_STOP_IM 0x00000003
#define JPEG_REALTIME_CMD_START 0x00000001
#define JPEG_OFFLINE_CMD_START 0x00000003
#define JPEG_DMI_CFG_DISABLE 0x00000000
#define JPEG_DMI_ADDR_START 0x00000000
#define JPEG_FE_CMD_BUFFERRELOAD 0x00000001
#define JPEG_WE_YUB_ENCODE 0x01ff0000
#define JPEG_RESET_DEFAULT 0x0004ffff /* cfff? */
#define JPEG_IRQ_DISABLE_ALL 0x00000000
#define JPEG_IRQ_CLEAR_ALL 0xffffffff
#define JPEG_IRQ_ALLSOURCES_ENABLE 0xffffffff
#define HWIO_JPEG_FE_BUFFER_CFG_ADDR (GEMINI_REG_BASE + 0x00000080)
#define HWIO_JPEG_FE_BUFFER_CFG_RMSK 0x1fff1fff
#define HWIO_JPEG_FE_Y_PING_ADDR_ADDR (GEMINI_REG_BASE + 0x00000084)
#define HWIO_JPEG_FE_Y_PING_ADDR_RMSK 0xffffffff
#define HWIO_JPEG_FE_Y_PONG_ADDR_ADDR (GEMINI_REG_BASE + 0x00000088)
#define HWIO_JPEG_FE_Y_PONG_ADDR_RMSK 0xffffffff
#define HWIO_JPEG_FE_CBCR_PING_ADDR_ADDR (GEMINI_REG_BASE + 0x0000008c)
#define HWIO_JPEG_FE_CBCR_PING_ADDR_RMSK 0xffffffff
#define HWIO_JPEG_FE_CBCR_PONG_ADDR_ADDR (GEMINI_REG_BASE + 0x00000090)
#define HWIO_JPEG_FE_CBCR_PONG_ADDR_RMSK 0xffffffff
#define HWIO_JPEG_FE_CMD_ADDR (GEMINI_REG_BASE + 0x00000094)
#define HWIO_JPEG_FE_CMD_RMSK 0x3
#define HWIO_JPEG_FE_BUFFER_CFG_CBCR_MCU_ROWS_BMSK 0x1fff0000
#define HWIO_JPEG_FE_BUFFER_CFG_CBCR_MCU_ROWS_SHFT 0x10
#define HWIO_JPEG_FE_BUFFER_CFG_Y_MCU_ROWS_BMSK 0x1fff
#define HWIO_JPEG_FE_BUFFER_CFG_Y_MCU_ROWS_SHFT 0
#define HWIO_JPEG_FE_Y_PING_ADDR_FE_Y_PING_START_ADDR_BMSK 0xffffffff
#define HWIO_JPEG_FE_Y_PING_ADDR_FE_Y_PING_START_ADDR_SHFT 0
#define HWIO_JPEG_FE_CBCR_PING_ADDR_FE_CBCR_PING_START_ADDR_BMSK 0xffffffff
#define HWIO_JPEG_FE_CBCR_PING_ADDR_FE_CBCR_PING_START_ADDR_SHFT 0
#define HWIO_JPEG_FE_Y_PONG_ADDR_FE_Y_PONG_START_ADDR_BMSK 0xffffffff
#define HWIO_JPEG_FE_Y_PONG_ADDR_FE_Y_PONG_START_ADDR_SHFT 0
#define HWIO_JPEG_FE_CBCR_PONG_ADDR_FE_CBCR_PONG_START_ADDR_BMSK 0xffffffff
#define HWIO_JPEG_FE_CBCR_PONG_ADDR_FE_CBCR_PONG_START_ADDR_SHFT 0
#define HWIO_JPEG_WE_Y_THRESHOLD_ADDR (GEMINI_REG_BASE + 0x000000c0)
#define HWIO_JPEG_WE_Y_THRESHOLD_RMSK 0x1ff01ff
#define HWIO_JPEG_WE_CBCR_THRESHOLD_ADDR (GEMINI_REG_BASE + 0x000000c4)
#define HWIO_JPEG_WE_CBCR_THRESHOLD_RMSK 0x1ff01ff
#define HWIO_JPEG_WE_Y_UB_CFG_ADDR (GEMINI_REG_BASE + 0x000000e8)
#define HWIO_JPEG_WE_Y_UB_CFG_RMSK 0x1ff01ff
#define HWIO_JPEG_WE_Y_THRESHOLD_WE_DEASSERT_STALL_TH_BMSK 0x1ff0000
#define HWIO_JPEG_WE_Y_THRESHOLD_WE_DEASSERT_STALL_TH_SHFT 0x10
#define HWIO_JPEG_WE_Y_THRESHOLD_WE_ASSERT_STALL_TH_BMSK 0x1ff
#define HWIO_JPEG_WE_Y_THRESHOLD_WE_ASSERT_STALL_TH_SHFT 0
#define HWIO_JPEG_WE_CBCR_THRESHOLD_WE_DEASSERT_STALL_TH_BMSK 0x1ff0000
#define HWIO_JPEG_WE_CBCR_THRESHOLD_WE_DEASSERT_STALL_TH_SHFT 0x10
#define HWIO_JPEG_WE_CBCR_THRESHOLD_WE_ASSERT_STALL_TH_BMSK 0x1ff
#define HWIO_JPEG_WE_CBCR_THRESHOLD_WE_ASSERT_STALL_TH_SHFT 0
#define HWIO_JPEG_WE_Y_PING_BUFFER_CFG_ADDR (GEMINI_REG_BASE + 0x000000c8)
#define HWIO_JPEG_WE_Y_PING_BUFFER_CFG_RMSK 0x7fffff
#define HWIO_JPEG_WE_Y_PING_ADDR_ADDR (GEMINI_REG_BASE + 0x000000d8)
#define HWIO_JPEG_WE_Y_PING_ADDR_RMSK 0xfffffff8
#define HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_ADDR (GEMINI_REG_BASE + 0x000000cc)
#define HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_RMSK 0x7fffff
#define HWIO_JPEG_WE_Y_PONG_ADDR_ADDR (GEMINI_REG_BASE + 0x000000dc)
#define HWIO_JPEG_WE_Y_PONG_ADDR_RMSK 0xfffffff8
#define HWIO_JPEG_WE_Y_PING_BUFFER_CFG_WE_BUFFER_LENGTH_BMSK 0x7fffff
#define HWIO_JPEG_WE_Y_PING_BUFFER_CFG_WE_BUFFER_LENGTH_SHFT 0
#define HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_WE_BUFFER_LENGTH_BMSK 0x7fffff
#define HWIO_JPEG_WE_Y_PONG_BUFFER_CFG_WE_BUFFER_LENGTH_SHFT 0
#define HWIO_JPEG_IRQ_MASK_ADDR (GEMINI_REG_BASE + 0x00000014)
#define HWIO_JPEG_IRQ_MASK_RMSK 0xffffffff
#define HWIO_JPEG_IRQ_CLEAR_ADDR (GEMINI_REG_BASE + 0x00000018)
#define HWIO_JPEG_IRQ_CLEAR_RMSK 0xffffffff
#define HWIO_JPEG_RESET_CMD_ADDR (GEMINI_REG_BASE + 0x00000004)
#define HWIO_JPEG_RESET_CMD_RMSK 0xe004ffff
#define HWIO_JPEG_IRQ_STATUS_ADDR (GEMINI_REG_BASE + 0x0000001c)
#define HWIO_JPEG_IRQ_STATUS_RMSK 0xffffffff
#define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_ADDR (GEMINI_REG_BASE + 0x00000034)
#define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_RMSK 0xffffffff
#endif /* MSM_GEMINI_HW_REG_H */

View File

@ -0,0 +1,250 @@
/* Copyright (c) 2010-2012, 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/pm_qos.h>
#include <linux/clk.h>
#include <mach/clk.h>
#include <linux/io.h>
#include <mach/camera.h>
#include <mach/iommu_domains.h>
#include "msm_gemini_platform.h"
#include "msm_gemini_sync.h"
#include "msm_gemini_common.h"
#include "msm_gemini_hw.h"
/* AXI rate in KHz */
#define MSM_SYSTEM_BUS_RATE 160000
struct ion_client *gemini_client;
void msm_gemini_platform_p2v(struct file *file,
struct ion_handle **ionhandle)
{
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL);
ion_free(gemini_client, *ionhandle);
*ionhandle = NULL;
#endif
}
uint32_t msm_gemini_platform_v2p(int fd, uint32_t len, struct file **file_p,
struct ion_handle **ionhandle)
{
unsigned long paddr;
unsigned long size;
int rc;
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
*ionhandle = ion_import_dma_buf(gemini_client, fd);
if (IS_ERR_OR_NULL(*ionhandle))
return 0;
rc = ion_map_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL,
SZ_4K, 0, &paddr, (unsigned long *)&size, 0, 0);
#else
rc = 0;
paddr = 0;
size = 0;
#endif
if (rc < 0) {
GMN_PR_ERR("%s: get_pmem_file fd %d error %d\n", __func__, fd,
rc);
goto error1;
}
/* validate user input */
if (len > size) {
GMN_PR_ERR("%s: invalid offset + len\n", __func__);
goto error1;
}
return paddr;
error1:
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_free(gemini_client, *ionhandle);
#endif
return 0;
}
static struct msm_cam_clk_info gemini_8x_clk_info[] = {
{"core_clk", 228571000},
{"iface_clk", -1},
};
static struct msm_cam_clk_info gemini_7x_clk_info[] = {
{"core_clk", 153600000},
{"iface_clk", -1},
};
static struct msm_cam_clk_info gemini_imem_clk_info[] = {
{"mem_clk", -1},
};
int msm_gemini_platform_init(struct platform_device *pdev,
struct resource **mem,
void **base,
int *irq,
irqreturn_t (*handler) (int, void *),
void *context)
{
int rc = -1;
int gemini_irq;
struct resource *gemini_mem, *gemini_io, *gemini_irq_res;
void *gemini_base;
struct msm_gemini_device *pgmn_dev =
(struct msm_gemini_device *) context;
gemini_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!gemini_mem) {
GMN_PR_ERR("%s: no mem resource?\n", __func__);
return -ENODEV;
}
gemini_irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!gemini_irq_res) {
GMN_PR_ERR("no irq resource?\n");
return -ENODEV;
}
gemini_irq = gemini_irq_res->start;
gemini_io = request_mem_region(gemini_mem->start,
resource_size(gemini_mem), pdev->name);
if (!gemini_io) {
GMN_PR_ERR("%s: region already claimed\n", __func__);
return -EBUSY;
}
gemini_base = ioremap(gemini_mem->start, resource_size(gemini_mem));
if (!gemini_base) {
rc = -ENOMEM;
GMN_PR_ERR("%s: ioremap failed\n", __func__);
goto fail1;
}
pgmn_dev->hw_version = GEMINI_8X60;
rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 1);
if (rc < 0) {
pgmn_dev->hw_version = GEMINI_7X;
rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev,
gemini_7x_clk_info, pgmn_dev->gemini_clk,
ARRAY_SIZE(gemini_7x_clk_info), 1);
if (rc < 0) {
GMN_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
goto fail2;
}
} else {
rc = msm_cam_clk_enable(&pgmn_dev->pdev->dev,
gemini_imem_clk_info, &pgmn_dev->gemini_clk[2],
ARRAY_SIZE(gemini_imem_clk_info), 1);
if (!rc)
pgmn_dev->hw_version = GEMINI_8960;
}
if (pgmn_dev->hw_version != GEMINI_7X) {
if (pgmn_dev->gemini_fs == NULL) {
pgmn_dev->gemini_fs =
regulator_get(&pgmn_dev->pdev->dev, "vdd");
if (IS_ERR(pgmn_dev->gemini_fs)) {
pr_err("%s: Regulator FS_ijpeg get failed %ld\n",
__func__, PTR_ERR(pgmn_dev->gemini_fs));
pgmn_dev->gemini_fs = NULL;
goto gemini_fs_failed;
} else if (regulator_enable(pgmn_dev->gemini_fs)) {
pr_err("%s: Regulator FS_ijpeg enable failed\n",
__func__);
regulator_put(pgmn_dev->gemini_fs);
pgmn_dev->gemini_fs = NULL;
goto gemini_fs_failed;
}
}
}
msm_gemini_hw_init(gemini_base, resource_size(gemini_mem));
rc = request_irq(gemini_irq, handler, IRQF_TRIGGER_RISING, "gemini",
context);
if (rc) {
GMN_PR_ERR("%s: request_irq failed, %d\n", __func__,
gemini_irq);
goto fail3;
}
*mem = gemini_mem;
*base = gemini_base;
*irq = gemini_irq;
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
gemini_client = msm_ion_client_create(-1, "camera/gemini");
#endif
GMN_DBG("%s:%d] success\n", __func__, __LINE__);
return rc;
fail3:
if (pgmn_dev->hw_version != GEMINI_7X) {
regulator_disable(pgmn_dev->gemini_fs);
regulator_put(pgmn_dev->gemini_fs);
pgmn_dev->gemini_fs = NULL;
}
gemini_fs_failed:
if (pgmn_dev->hw_version == GEMINI_8960)
msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info,
&pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0);
if (pgmn_dev->hw_version != GEMINI_7X)
msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0);
else
msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info,
pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0);
fail2:
iounmap(gemini_base);
fail1:
release_mem_region(gemini_mem->start, resource_size(gemini_mem));
GMN_DBG("%s:%d] fail\n", __func__, __LINE__);
return rc;
}
int msm_gemini_platform_release(struct resource *mem, void *base, int irq,
void *context)
{
int result = 0;
struct msm_gemini_device *pgmn_dev =
(struct msm_gemini_device *) context;
free_irq(irq, context);
if (pgmn_dev->hw_version != GEMINI_7X) {
regulator_disable(pgmn_dev->gemini_fs);
regulator_put(pgmn_dev->gemini_fs);
pgmn_dev->gemini_fs = NULL;
}
if (pgmn_dev->hw_version == GEMINI_8960)
msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_imem_clk_info,
&pgmn_dev->gemini_clk[2], ARRAY_SIZE(gemini_imem_clk_info), 0);
if (pgmn_dev->hw_version != GEMINI_7X)
msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_8x_clk_info,
pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_8x_clk_info), 0);
else
msm_cam_clk_enable(&pgmn_dev->pdev->dev, gemini_7x_clk_info,
pgmn_dev->gemini_clk, ARRAY_SIZE(gemini_7x_clk_info), 0);
iounmap(base);
release_mem_region(mem->start, resource_size(mem));
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_client_destroy(gemini_client);
#endif
GMN_DBG("%s:%d] success\n", __func__, __LINE__);
return result;
}

View File

@ -0,0 +1,37 @@
/* Copyright (c) 2010-2012, 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.
*/
#ifndef MSM_GEMINI_PLATFORM_H
#define MSM_GEMINI_PLATFORM_H
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/msm_ion.h>
#include <linux/iommu.h>
void msm_gemini_platform_p2v(struct file *file,
struct ion_handle **ionhandle);
uint32_t msm_gemini_platform_v2p(int fd, uint32_t len, struct file **file,
struct ion_handle **ionhandle);
int msm_gemini_platform_clk_enable(void);
int msm_gemini_platform_clk_disable(void);
int msm_gemini_platform_init(struct platform_device *pdev,
struct resource **mem,
void **base,
int *irq,
irqreturn_t (*handler) (int, void *),
void *context);
int msm_gemini_platform_release(struct resource *mem, void *base, int irq,
void *context);
#endif /* MSM_GEMINI_PLATFORM_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/* Copyright (c) 2010,2013, 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.
*/
#ifndef MSM_GEMINI_SYNC_H
#define MSM_GEMINI_SYNC_H
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include "msm_gemini_core.h"
#define GEMINI_7X 0x1
#define GEMINI_8X60 (0x1 << 1)
#define GEMINI_8960 (0x1 << 2)
struct msm_gemini_q {
char const *name;
struct list_head q;
spinlock_t lck;
wait_queue_head_t wait;
int unblck;
};
struct msm_gemini_q_entry {
struct list_head list;
void *data;
};
struct msm_gemini_device {
struct platform_device *pdev;
struct resource *mem;
int irq;
void *base;
struct clk *gemini_clk[3];
struct regulator *gemini_fs;
uint32_t hw_version;
struct device *device;
struct cdev cdev;
struct mutex lock;
char open_count;
uint8_t op_mode;
/* event queue including frame done & err indications
*/
struct msm_gemini_q evt_q;
/* output return queue
*/
struct msm_gemini_q output_rtn_q;
/* output buf queue
*/
struct msm_gemini_q output_buf_q;
/* input return queue
*/
struct msm_gemini_q input_rtn_q;
/* input buf queue
*/
struct msm_gemini_q input_buf_q;
struct v4l2_subdev subdev;
enum msm_gmn_out_mode out_mode;
/* single out mode parameters */
struct msm_gemini_hw_buf out_buf;
int out_offset;
int out_buf_set;
int max_out_size;
int out_frag_cnt;
uint32_t bus_perf_client;
};
int __msm_gemini_open(struct msm_gemini_device *pgmn_dev);
int __msm_gemini_release(struct msm_gemini_device *pgmn_dev);
long __msm_gemini_ioctl(struct msm_gemini_device *pgmn_dev,
unsigned int cmd, unsigned long arg);
struct msm_gemini_device *__msm_gemini_init(struct platform_device *pdev);
int __msm_gemini_exit(struct msm_gemini_device *pgmn_dev);
#endif /* MSM_GEMINI_SYNC_H */