]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
drivers: media: tegra: camera: auto-detect notice
authorCharlie Huang <chahuang@nvidia.com>
Thu, 10 Apr 2014 18:30:37 +0000 (11:30 -0700)
committerSeema Khowala <seemaj@nvidia.com>
Wed, 23 Apr 2014 21:06:39 +0000 (14:06 -0700)
- 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>
drivers/media/platform/tegra/cam_dev/dev_access.c
drivers/media/platform/tegra/camera.c
include/media/camera.h

index e237208b2249d475184691b9c2171d612341476e..35bcc90616c794d261e8b66d587e3c0a6d329f5a 100644 (file)
@@ -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;
 }
 
index 4a85fbc315c3fd457f1a84df87b01316e4e01b39..d79afcfd8f998ac706ffe14c1ebbf4047fd55760 100644 (file)
@@ -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) {
index 16f9d6499221430d3fcb75f28af38eff244ed20f..a0381f371cc0d876422e4c678ef8096a23242307 100644 (file)
@@ -43,6 +43,8 @@
 #define CAMERA_TABLE_INX_CGATE         (CAMERA_INT_MASK | 51)
 #define CAMERA_TABLE_EDP_STATE         (CAMERA_INT_MASK | 60)
 
+#define CAMERA_TABLE_DEV_READ          0xe0000000
+
 #define CAMERA_TABLE_PWR_FLAG_MASK     0xf0000000
 #define CAMERA_TABLE_PWR_FLAG_ON       0x80000000
 #define CAMERA_TABLE_PINMUX_FLAG_MASK  0xf0000000
@@ -69,6 +71,7 @@
 #define PCLLK_IOCTL_PARAM_RD   _IOWR('o', 141, struct nvc_param)
 #define PCLLK_IOCTL_DRV_ADD    _IOW('o', 150, struct nvc_param)
 #define PCLLK_IOCTL_DT_GET     _IOWR('o', 160, struct nvc_param)
+#define PCLLK_IOCTL_MSG                _IOWR('o', 170, struct nvc_param)
 
 #define CAMERA_MAX_EDP_ENTRIES  16
 #define CAMERA_MAX_NAME_LENGTH 32
@@ -356,7 +359,7 @@ int camera_regulator_get(struct device *, struct nvc_regulator *, char *);
 
 /* device access functions */
 int camera_dev_parser(
-       struct camera_device *, u32, u32, struct camera_seq_status *
+       struct camera_device *, u32, u32 *, struct camera_seq_status *
 );
 int camera_dev_wr_table(
        struct camera_device *, struct camera_reg *, struct camera_seq_status *