diff options
author | Charlie Huang <chahuang@nvidia.com> | 2014-04-10 11:30:37 -0700 |
---|---|---|
committer | Seema Khowala <seemaj@nvidia.com> | 2014-04-23 14:06:39 -0700 |
commit | e3a89886d876620f3988ca4e0f79dfdcbe8505a8 (patch) | |
tree | b51e18901b1f252b812db2ee6eeb1ce8f5cec301 /drivers/media | |
parent | a959153e145161d591085367c1d1da092f3f9170 (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')
-rw-r--r-- | drivers/media/platform/tegra/cam_dev/dev_access.c | 31 | ||||
-rw-r--r-- | drivers/media/platform/tegra/camera.c | 176 |
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(¶ms, (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, ¶ms, (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(¶ms, (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, ¶ms, 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(¶m, (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), ¶m, (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, ¶m, (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(¶m, (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, ¶m, &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(¶m, (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, ¶m, 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, ¶m, 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(¶m, (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, ¶m, NULL); + if (err) + return err; + if (param.param == 0) return camera_add_drv_by_sensor_name(cam, ¶m); return camera_add_drv_by_module(cam, ¶m); @@ -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) { |