summaryrefslogtreecommitdiff
path: root/drivers/media/platform/tegra
diff options
context:
space:
mode:
authorCharlie Huang <chahuang@nvidia.com>2014-04-10 11:30:37 -0700
committerSeema Khowala <seemaj@nvidia.com>2014-04-23 14:06:39 -0700
commite3a89886d876620f3988ca4e0f79dfdcbe8505a8 (patch)
treeb51e18901b1f252b812db2ee6eeb1ce8f5cec301 /drivers/media/platform/tegra
parenta959153e145161d591085367c1d1da092f3f9170 (diff)
drivers: media: tegra: camera: auto-detect notice
- display notice, for auto detect showing the begin of auto-detect. - add read-in-write feature, camera_dev_wr_table can read device while parsing scripts. - return error state in table write. - camera_app_remove will not throw out warnings when shutdown. - code optimization, add camera_get_params to replace duplicated code. bug 1472043 Change-Id: I9ee683bade00ea738a1c8edc282c40ad30d57c7f Signed-off-by: Charlie Huang <chahuang@nvidia.com> Reviewed-on: http://git-master/r/394834 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Frank Chen <frankc@nvidia.com> Reviewed-by: Gary Fitzer <gfitzer@nvidia.com> Reviewed-by: David Wang (SW-TEGRA) <davidw@nvidia.com> Reviewed-by: Thomas Cherry <tcherry@nvidia.com>
Diffstat (limited to 'drivers/media/platform/tegra')
-rw-r--r--drivers/media/platform/tegra/cam_dev/dev_access.c31
-rw-r--r--drivers/media/platform/tegra/camera.c176
2 files changed, 121 insertions, 86 deletions
diff --git a/drivers/media/platform/tegra/cam_dev/dev_access.c b/drivers/media/platform/tegra/cam_dev/dev_access.c
index e237208b2249..35bcc90616c7 100644
--- a/drivers/media/platform/tegra/cam_dev/dev_access.c
+++ b/drivers/media/platform/tegra/cam_dev/dev_access.c
@@ -257,9 +257,10 @@ static int camera_dev_wr_blk(
int camera_dev_parser(
struct camera_device *cdev,
- u32 command, u32 val,
+ u32 command, u32 *pdat,
struct camera_seq_status *pst)
{
+ u32 val = *pdat;
int err = 0;
u8 flag = 0;
@@ -416,6 +417,19 @@ int camera_dev_parser(
usleep_range(val, val + 20);
break;
default:
+ if ((command & CAMERA_INT_MASK) == CAMERA_TABLE_DEV_READ) {
+ /* feature: read data in table write function */
+ struct camera_reg regs[2];
+ regs[0].addr = command & ~CAMERA_INT_MASK;
+ regs[1].addr = CAMERA_TABLE_END;
+ err = camera_dev_rd_table(cdev, regs);
+ if (err < 0)
+ return err;
+ *pdat = regs[0].val;
+ if (pst)
+ pst->status = command;
+ break;
+ }
dev_err(cdev->dev, "unrecognized cmd %x.\n", command);
return -ENODEV;
}
@@ -428,7 +442,7 @@ int camera_dev_wr_table(
struct camera_reg *table,
struct camera_seq_status *pst)
{
- const struct camera_reg *next;
+ struct camera_reg *next, *blk_start = NULL;
u8 *b_ptr = cdev->i2c_buf;
u8 byte_num;
u16 buf_count = 0;
@@ -452,13 +466,13 @@ int camera_dev_wr_table(
dev_dbg(cdev->dev, "%x - %x\n", next->addr, next->val);
if (next->addr & CAMERA_INT_MASK) {
err = camera_dev_parser(
- cdev, next->addr, next->val, pst);
+ cdev, next->addr, &next->val, pst);
if (err > 0) { /* special cmd executed */
err = 0;
continue;
}
if (err < 0) { /* this is a real error */
- if (pst)
+ if (pst) /* store where the error happened */
pst->idx = (next - table) /
sizeof(*table) + 1;
break;
@@ -468,6 +482,7 @@ int camera_dev_wr_table(
if (!buf_count) {
b_ptr = cdev->i2c_buf;
addr = next->addr;
+ blk_start = next;
}
switch (byte_num) {
case 2:
@@ -487,12 +502,18 @@ int camera_dev_wr_table(
}
err = camera_dev_wr_blk(cdev, addr, cdev->i2c_buf, buf_count);
- if (err)
+ if (err) {
+ if (pst) /* store the index which caused the error */
+ pst->idx = (blk_start - table) /
+ sizeof(*table) + 1;
break;
+ }
buf_count = 0;
}
+ if (!err && pst && pst->status)
+ err = 1;
return err;
}
diff --git a/drivers/media/platform/tegra/camera.c b/drivers/media/platform/tegra/camera.c
index 4a85fbc315c3..d79afcfd8f99 100644
--- a/drivers/media/platform/tegra/camera.c
+++ b/drivers/media/platform/tegra/camera.c
@@ -68,33 +68,48 @@ static struct camera_platform_info cam_desc = {
.chip_list = &chip_list,
};
-static int camera_seq_rd(struct camera_info *cam, unsigned long arg)
+static int camera_get_params(
+ struct camera_info *cam, unsigned long arg, int u_size,
+ struct nvc_param *prm, void **data)
{
- struct nvc_param params;
- struct camera_reg *p_i2c_table;
- int err;
+ void *buf;
+ unsigned size;
- dev_dbg(cam->dev, "%s %lx\n", __func__, arg);
- if (copy_from_user(&params, (const void __user *)arg,
- sizeof(struct nvc_param))) {
+ if (copy_from_user(prm, (const void __user *)arg, sizeof(*prm))) {
dev_err(cam->dev, "%s copy_from_user err line %d\n",
__func__, __LINE__);
return -EFAULT;
}
+ if (!data)
+ return 0;
- p_i2c_table = kzalloc(sizeof(params.sizeofvalue), GFP_KERNEL);
- if (p_i2c_table == NULL) {
- dev_err(cam->dev, "%s: kzalloc error\n", __func__);
+ size = prm->sizeofvalue * u_size;
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf) {
+ dev_err(cam->dev, "%s allocate memory failed!\n", __func__);
return -ENOMEM;
}
-
- if (copy_from_user(p_i2c_table, MAKE_CONSTUSER_PTR(params.p_value),
- params.sizeofvalue)) {
+ if (copy_from_user(buf, MAKE_CONSTUSER_PTR(prm->p_value), size)) {
dev_err(cam->dev, "%s copy_from_user err line %d\n",
__func__, __LINE__);
- kfree(p_i2c_table);
- return -EINVAL;
+ kfree(buf);
+ return -EFAULT;
}
+ *data = buf;
+
+ return 0;
+}
+
+static int camera_seq_rd(struct camera_info *cam, unsigned long arg)
+{
+ struct nvc_param params;
+ struct camera_reg *p_i2c_table;
+ int err;
+
+ dev_dbg(cam->dev, "%s %lx\n", __func__, arg);
+ err = camera_get_params(cam, arg, 1, &params, (void **)&p_i2c_table);
+ if (err)
+ return err;
err = camera_dev_rd_table(cam->cdev, p_i2c_table);
if (!err && copy_to_user(MAKE_USER_PTR(params.p_value),
@@ -120,12 +135,9 @@ static int camera_seq_wr(struct camera_info *cam, unsigned long arg)
dev_dbg(cam->dev, "%s %lx", __func__, arg);
- if (copy_from_user(&params, (const void __user *)arg,
- sizeof(struct nvc_param))) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- return -EFAULT;
- }
+ err = camera_get_params(cam, arg, 0, &params, NULL);
+ if (err)
+ return err;
dev_dbg(cam->dev, "param: %x, size %d\n", params.param,
params.sizeofvalue);
@@ -190,6 +202,7 @@ seq_wr_table:
if (err < 0)
goto seq_wr_end;
+ memset(&seqs, 0, sizeof(seqs));
mutex_lock(&cdev->mutex);
err = camera_dev_wr_table(cdev, p_i2c_table, &seqs);
mutex_unlock(&cdev->mutex);
@@ -207,8 +220,16 @@ seq_wr_upd:
}
seq_wr_end:
- if (pfree)
+ if (pfree) {
+ /* if table has been updated, send it back */
+ if (err > 0 && copy_to_user(MAKE_USER_PTR(params.p_value),
+ p_i2c_table, params.sizeofvalue)) {
+ dev_err(cam->dev, "%s copy_to_user err line %d\n",
+ __func__, __LINE__);
+ err = -EFAULT;
+ }
devm_kfree(cdev->dev, p_i2c_table);
+ }
return err;
}
@@ -360,9 +381,10 @@ static int camera_new_device(struct camera_info *cam, unsigned long arg)
&dev_info, (const void __user *)arg, sizeof(dev_info))) {
dev_err(cam_desc.dev, "%s copy_from_user err line %d\n",
__func__, __LINE__);
- err = -EFAULT;
- goto new_device_end;
+ err = -EFAULT;
+ goto new_device_end;
}
+
dev_dbg(cam->dev, "%s - %d %d %x\n",
dev_info.name, dev_info.type, dev_info.bus, dev_info.addr);
@@ -463,13 +485,15 @@ new_device_end:
return err;
}
-static void camera_app_remove(struct camera_info *cam)
+static void camera_app_remove(struct camera_info *cam, bool ref_chk)
{
dev_dbg(cam->dev, "%s\n", __func__);
- WARN_ON(atomic_xchg(&cam->in_use, 0));
+ if (ref_chk)
+ WARN_ON(atomic_xchg(&cam->in_use, 0));
if (cam->cdev) {
- WARN_ON(atomic_xchg(&cam->cdev->in_use, 0));
+ if (ref_chk)
+ WARN_ON(atomic_xchg(&cam->cdev->in_use, 0));
cam->cdev->cam = NULL;
}
kfree(cam);
@@ -486,36 +510,37 @@ static int camera_update(struct camera_info *cam, unsigned long arg)
dev_dbg(cam->dev, "%s %lx", __func__, arg);
if (!chip->update) {
dev_dbg(cam->dev, "no update pointer.\n");
- goto update_end;
+ return err;
}
- if (copy_from_user(&param, (const void __user *)arg, sizeof(param))) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- err = -EFAULT;
- goto update_end;
- }
- upd = kzalloc(param.sizeofvalue * sizeof(*upd), GFP_KERNEL);
- if (!upd) {
- dev_err(cam->dev, "%s allocate memory failed!\n", __func__);
- err = -ENOMEM;
- goto update_end;
- }
- if (copy_from_user(upd, MAKE_CONSTUSER_PTR(param.p_value),
- param.sizeofvalue * sizeof(*upd))) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- err = -EFAULT;
- goto update_end;
- }
+ err = camera_get_params(cam, arg, sizeof(*upd), &param, (void **)&upd);
+ if (err)
+ return err;
err = chip->update(cdev, upd, param.sizeofvalue);
-update_end:
kfree(upd);
return err;
}
+/* need this feature for auto detect to display notifications */
+static int camera_msg(struct camera_info *cam, unsigned long arg)
+{
+ struct nvc_param param;
+ char *str;
+ int err = 0;
+
+ dev_dbg(cam->dev, "%s %lx", __func__, arg);
+ err = camera_get_params(cam, arg, 1, &param, (void **)&str);
+ if (err)
+ return err;
+ if (str[param.sizeofvalue - 1] == '\0')
+ dev_info(cam->dev, "%s\n", str);
+ kfree(str);
+
+ return 0;
+}
+
static int camera_layout_update(struct camera_info *cam, unsigned long arg)
{
struct nvc_param param;
@@ -530,27 +555,9 @@ static int camera_layout_update(struct camera_info *cam, unsigned long arg)
goto layout_end;
}
- if (copy_from_user(&param, (const void __user *)arg, sizeof(param))) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- err = -EFAULT;
- goto layout_end;
- }
-
- upd = kzalloc(param.sizeofvalue, GFP_KERNEL);
- if (!upd) {
- dev_err(cam->dev, "%s allocate memory failed!\n", __func__);
- err = -ENOMEM;
- goto layout_end;
- }
- if (copy_from_user(upd, MAKE_CONSTUSER_PTR(param.p_value),
- param.sizeofvalue)) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- kfree(upd);
- err = -EFAULT;
+ err = camera_get_params(cam, arg, 1, &param, &upd);
+ if (err)
goto layout_end;
- }
cam_desc.layout = upd;
cam_desc.size_layout = param.sizeofvalue;
@@ -573,14 +580,17 @@ static int camera_layout_get(struct camera_info *cam, unsigned long arg)
goto getlayout_end;
}
- if (copy_from_user(&param, (const void __user *)arg, sizeof(param))) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- err = -EFAULT;
- goto getlayout_end;
- }
+ err = camera_get_params(cam, arg, 0, &param, NULL);
+ if (err)
+ return err;
len = (int)cam_desc.size_layout - param.variant;
+ if (len <= 0) {
+ dev_err(cam->dev, "%s invalid offset %d\n",
+ __func__, param.variant);
+ err = -EINVAL;
+ goto getlayout_end;
+ }
if (len > param.sizeofvalue) {
len = param.sizeofvalue;
err = -EAGAIN;
@@ -594,6 +604,7 @@ static int camera_layout_get(struct camera_info *cam, unsigned long arg)
}
param.sizeofvalue = len;
+ param.variant = cam_desc.size_layout;
if (copy_to_user((void __user *)arg, &param, sizeof(param))) {
dev_err(cam->dev, "%s copy_to_user err line %d\n",
__func__, __LINE__);
@@ -712,13 +723,13 @@ static int camera_add_drv_by_module(
static int camera_add_drivers(struct camera_info *cam, unsigned long arg)
{
struct nvc_param param;
+ int err;
dev_dbg(cam->dev, "%s %lx", __func__, arg);
- if (copy_from_user(&param, (const void __user *)arg, sizeof(param))) {
- dev_err(cam->dev, "%s copy_from_user err line %d\n",
- __func__, __LINE__);
- return -EFAULT;
- }
+ err = camera_get_params(cam, arg, 0, &param, NULL);
+ if (err)
+ return err;
+
if (param.param == 0)
return camera_add_drv_by_sensor_name(cam, &param);
return camera_add_drv_by_module(cam, &param);
@@ -789,6 +800,9 @@ static long camera_ioctl(struct file *file,
case _IOC_NR(PCLLK_IOCTL_DT_GET):
err = of_camera_get_property(cam, arg);
break;
+ case _IOC_NR(PCLLK_IOCTL_MSG):
+ err = camera_msg(cam, arg);
+ break;
default:
dev_err(cam->dev, "%s unsupported ioctl: %x\n",
__func__, cmd);
@@ -837,7 +851,7 @@ static int camera_release(struct inode *inode, struct file *file)
list_del(&cam->list);
mutex_unlock(cam_desc.u_mutex);
- camera_app_remove(cam);
+ camera_app_remove(cam, true);
file->private_data = NULL;
return 0;
@@ -865,7 +879,7 @@ static int camera_remove(struct platform_device *dev)
mutex_lock(cam_desc.u_mutex);
list_del(&cam->list);
mutex_unlock(cam_desc.u_mutex);
- camera_app_remove(cam);
+ camera_app_remove(cam, false);
}
list_for_each_entry(cdev, cam_desc.dev_list, list) {