This is an automatic generated email to let you know that the following patch 
were queued:

Subject: media: imx074: deprecate, move to staging
Author:  Hans Verkuil <hans.verk...@cisco.com>
Date:    Tue Jan 16 06:02:44 2018 -0500

This driver is unused and depends on the deprecated soc-camera framework.
Move it to staging in preparation for being removed unless someone does
the work to convert it to a proper V4L2 subdev driver.

Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>
Signed-off-by: Sakari Ailus <sakari.ai...@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mche...@s-opensource.com>

 drivers/media/i2c/soc_camera/Kconfig  |   6 -
 drivers/media/i2c/soc_camera/Makefile |   1 -
 drivers/media/i2c/soc_camera/imx074.c | 497 ----------------------------------
 drivers/staging/media/Kconfig         |   2 +
 drivers/staging/media/Makefile        |   1 +
 drivers/staging/media/imx074/Kconfig  |   5 +
 drivers/staging/media/imx074/Makefile |   1 +
 drivers/staging/media/imx074/TODO     |   5 +
 drivers/staging/media/imx074/imx074.c | 497 ++++++++++++++++++++++++++++++++++
 9 files changed, 511 insertions(+), 504 deletions(-)

---

diff --git a/drivers/media/i2c/soc_camera/Kconfig 
b/drivers/media/i2c/soc_camera/Kconfig
index 72b369895b37..d7136f2c2b20 100644
--- a/drivers/media/i2c/soc_camera/Kconfig
+++ b/drivers/media/i2c/soc_camera/Kconfig
@@ -1,11 +1,5 @@
 comment "soc_camera sensor drivers"
 
-config SOC_CAMERA_IMX074
-       tristate "imx074 support"
-       depends on SOC_CAMERA && I2C
-       help
-         This driver supports IMX074 cameras from Sony
-
 config SOC_CAMERA_MT9M001
        tristate "mt9m001 support"
        depends on SOC_CAMERA && I2C
diff --git a/drivers/media/i2c/soc_camera/Makefile 
b/drivers/media/i2c/soc_camera/Makefile
index faa2df8901d2..a489b00e43b5 100644
--- a/drivers/media/i2c/soc_camera/Makefile
+++ b/drivers/media/i2c/soc_camera/Makefile
@@ -1,5 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
 obj-$(CONFIG_SOC_CAMERA_MT9T031)       += mt9t031.o
 obj-$(CONFIG_SOC_CAMERA_MT9T112)       += mt9t112.o
diff --git a/drivers/media/i2c/soc_camera/imx074.c 
b/drivers/media/i2c/soc_camera/imx074.c
deleted file mode 100644
index 77f1e0243d6e..000000000000
--- a/drivers/media/i2c/soc_camera/imx074.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Driver for IMX074 CMOS Image Sensor from Sony
- *
- * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovet...@gmx.de>
- *
- * Partially inspired by the IMX074 driver from the Android / MSM tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/v4l2-mediabus.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <linux/module.h>
-
-#include <media/soc_camera.h>
-#include <media/v4l2-async.h>
-#include <media/v4l2-clk.h>
-#include <media/v4l2-subdev.h>
-
-/* IMX074 registers */
-
-#define MODE_SELECT                    0x0100
-#define IMAGE_ORIENTATION              0x0101
-#define GROUPED_PARAMETER_HOLD         0x0104
-
-/* Integration Time */
-#define COARSE_INTEGRATION_TIME_HI     0x0202
-#define COARSE_INTEGRATION_TIME_LO     0x0203
-/* Gain */
-#define ANALOGUE_GAIN_CODE_GLOBAL_HI   0x0204
-#define ANALOGUE_GAIN_CODE_GLOBAL_LO   0x0205
-
-/* PLL registers */
-#define PRE_PLL_CLK_DIV                        0x0305
-#define PLL_MULTIPLIER                 0x0307
-#define PLSTATIM                       0x302b
-#define VNDMY_ABLMGSHLMT               0x300a
-#define Y_OPBADDR_START_DI             0x3014
-/* mode setting */
-#define FRAME_LENGTH_LINES_HI          0x0340
-#define FRAME_LENGTH_LINES_LO          0x0341
-#define LINE_LENGTH_PCK_HI             0x0342
-#define LINE_LENGTH_PCK_LO             0x0343
-#define YADDR_START                    0x0347
-#define YADDR_END                      0x034b
-#define X_OUTPUT_SIZE_MSB              0x034c
-#define X_OUTPUT_SIZE_LSB              0x034d
-#define Y_OUTPUT_SIZE_MSB              0x034e
-#define Y_OUTPUT_SIZE_LSB              0x034f
-#define X_EVEN_INC                     0x0381
-#define X_ODD_INC                      0x0383
-#define Y_EVEN_INC                     0x0385
-#define Y_ODD_INC                      0x0387
-
-#define HMODEADD                       0x3001
-#define VMODEADD                       0x3016
-#define VAPPLINE_START                 0x3069
-#define VAPPLINE_END                   0x306b
-#define SHUTTER                                0x3086
-#define HADDAVE                                0x30e8
-#define LANESEL                                0x3301
-
-/* IMX074 supported geometry */
-#define IMX074_WIDTH                   1052
-#define IMX074_HEIGHT                  780
-
-/* IMX074 has only one fixed colorspace per pixelcode */
-struct imx074_datafmt {
-       u32     code;
-       enum v4l2_colorspace            colorspace;
-};
-
-struct imx074 {
-       struct v4l2_subdev              subdev;
-       const struct imx074_datafmt     *fmt;
-       struct v4l2_clk                 *clk;
-};
-
-static const struct imx074_datafmt imx074_colour_fmts[] = {
-       {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
-};
-
-static struct imx074 *to_imx074(const struct i2c_client *client)
-{
-       return container_of(i2c_get_clientdata(client), struct imx074, subdev);
-}
-
-/* Find a data format by a pixel code in an array */
-static const struct imx074_datafmt *imx074_find_datafmt(u32 code)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(imx074_colour_fmts); i++)
-               if (imx074_colour_fmts[i].code == code)
-                       return imx074_colour_fmts + i;
-
-       return NULL;
-}
-
-static int reg_write(struct i2c_client *client, const u16 addr, const u8 data)
-{
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msg;
-       unsigned char tx[3];
-       int ret;
-
-       msg.addr = client->addr;
-       msg.buf = tx;
-       msg.len = 3;
-       msg.flags = 0;
-
-       tx[0] = addr >> 8;
-       tx[1] = addr & 0xff;
-       tx[2] = data;
-
-       ret = i2c_transfer(adap, &msg, 1);
-
-       mdelay(2);
-
-       return ret == 1 ? 0 : -EIO;
-}
-
-static int reg_read(struct i2c_client *client, const u16 addr)
-{
-       u8 buf[2] = {addr >> 8, addr & 0xff};
-       int ret;
-       struct i2c_msg msgs[] = {
-               {
-                       .addr  = client->addr,
-                       .flags = 0,
-                       .len   = 2,
-                       .buf   = buf,
-               }, {
-                       .addr  = client->addr,
-                       .flags = I2C_M_RD,
-                       .len   = 2,
-                       .buf   = buf,
-               },
-       };
-
-       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-       if (ret < 0) {
-               dev_warn(&client->dev, "Reading register %x from %x failed\n",
-                        addr, client->addr);
-               return ret;
-       }
-
-       return buf[0] & 0xff; /* no sign-extension */
-}
-
-static int imx074_set_fmt(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct imx074 *priv = to_imx074(client);
-
-       if (format->pad)
-               return -EINVAL;
-
-       dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
-
-       if (!fmt) {
-               /* MIPI CSI could have changed the format, double-check */
-               if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-                       return -EINVAL;
-               mf->code        = imx074_colour_fmts[0].code;
-               mf->colorspace  = imx074_colour_fmts[0].colorspace;
-       }
-
-       mf->width       = IMX074_WIDTH;
-       mf->height      = IMX074_HEIGHT;
-       mf->field       = V4L2_FIELD_NONE;
-
-       if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-               priv->fmt = fmt;
-       else
-               cfg->try_fmt = *mf;
-
-       return 0;
-}
-
-static int imx074_get_fmt(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_format *format)
-{
-       struct v4l2_mbus_framefmt *mf = &format->format;
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct imx074 *priv = to_imx074(client);
-
-       const struct imx074_datafmt *fmt = priv->fmt;
-
-       if (format->pad)
-               return -EINVAL;
-
-       mf->code        = fmt->code;
-       mf->colorspace  = fmt->colorspace;
-       mf->width       = IMX074_WIDTH;
-       mf->height      = IMX074_HEIGHT;
-       mf->field       = V4L2_FIELD_NONE;
-
-       return 0;
-}
-
-static int imx074_get_selection(struct v4l2_subdev *sd,
-                               struct v4l2_subdev_pad_config *cfg,
-                               struct v4l2_subdev_selection *sel)
-{
-       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
-               return -EINVAL;
-
-       sel->r.left = 0;
-       sel->r.top = 0;
-       sel->r.width = IMX074_WIDTH;
-       sel->r.height = IMX074_HEIGHT;
-
-       switch (sel->target) {
-       case V4L2_SEL_TGT_CROP_BOUNDS:
-       case V4L2_SEL_TGT_CROP_DEFAULT:
-       case V4L2_SEL_TGT_CROP:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-static int imx074_enum_mbus_code(struct v4l2_subdev *sd,
-               struct v4l2_subdev_pad_config *cfg,
-               struct v4l2_subdev_mbus_code_enum *code)
-{
-       if (code->pad ||
-           (unsigned int)code->index >= ARRAY_SIZE(imx074_colour_fmts))
-               return -EINVAL;
-
-       code->code = imx074_colour_fmts[code->index].code;
-       return 0;
-}
-
-static int imx074_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-       /* MODE_SELECT: stream or standby */
-       return reg_write(client, MODE_SELECT, !!enable);
-}
-
-static int imx074_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
-       struct imx074 *priv = to_imx074(client);
-
-       return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
-}
-
-static int imx074_g_mbus_config(struct v4l2_subdev *sd,
-                               struct v4l2_mbus_config *cfg)
-{
-       cfg->type = V4L2_MBUS_CSI2;
-       cfg->flags = V4L2_MBUS_CSI2_2_LANE |
-               V4L2_MBUS_CSI2_CHANNEL_0 |
-               V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
-
-       return 0;
-}
-
-static const struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
-       .s_stream       = imx074_s_stream,
-       .g_mbus_config  = imx074_g_mbus_config,
-};
-
-static const struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
-       .s_power        = imx074_s_power,
-};
-
-static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
-       .enum_mbus_code = imx074_enum_mbus_code,
-       .get_selection  = imx074_get_selection,
-       .get_fmt        = imx074_get_fmt,
-       .set_fmt        = imx074_set_fmt,
-};
-
-static const struct v4l2_subdev_ops imx074_subdev_ops = {
-       .core   = &imx074_subdev_core_ops,
-       .video  = &imx074_subdev_video_ops,
-       .pad    = &imx074_subdev_pad_ops,
-};
-
-static int imx074_video_probe(struct i2c_client *client)
-{
-       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
-       int ret;
-       u16 id;
-
-       ret = imx074_s_power(subdev, 1);
-       if (ret < 0)
-               return ret;
-
-       /* Read sensor Model ID */
-       ret = reg_read(client, 0);
-       if (ret < 0)
-               goto done;
-
-       id = ret << 8;
-
-       ret = reg_read(client, 1);
-       if (ret < 0)
-               goto done;
-
-       id |= ret;
-
-       dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
-
-       if (id != 0x74) {
-               ret = -ENODEV;
-               goto done;
-       }
-
-       /* PLL Setting EXTCLK=24MHz, 22.5times */
-       reg_write(client, PLL_MULTIPLIER, 0x2D);
-       reg_write(client, PRE_PLL_CLK_DIV, 0x02);
-       reg_write(client, PLSTATIM, 0x4B);
-
-       /* 2-lane mode */
-       reg_write(client, 0x3024, 0x00);
-
-       reg_write(client, IMAGE_ORIENTATION, 0x00);
-
-       /* select RAW mode:
-        * 0x08+0x08 = top 8 bits
-        * 0x0a+0x08 = compressed 8-bits
-        * 0x0a+0x0a = 10 bits
-        */
-       reg_write(client, 0x0112, 0x08);
-       reg_write(client, 0x0113, 0x08);
-
-       /* Base setting for High frame mode */
-       reg_write(client, VNDMY_ABLMGSHLMT, 0x80);
-       reg_write(client, Y_OPBADDR_START_DI, 0x08);
-       reg_write(client, 0x3015, 0x37);
-       reg_write(client, 0x301C, 0x01);
-       reg_write(client, 0x302C, 0x05);
-       reg_write(client, 0x3031, 0x26);
-       reg_write(client, 0x3041, 0x60);
-       reg_write(client, 0x3051, 0x24);
-       reg_write(client, 0x3053, 0x34);
-       reg_write(client, 0x3057, 0xC0);
-       reg_write(client, 0x305C, 0x09);
-       reg_write(client, 0x305D, 0x07);
-       reg_write(client, 0x3060, 0x30);
-       reg_write(client, 0x3065, 0x00);
-       reg_write(client, 0x30AA, 0x08);
-       reg_write(client, 0x30AB, 0x1C);
-       reg_write(client, 0x30B0, 0x32);
-       reg_write(client, 0x30B2, 0x83);
-       reg_write(client, 0x30D3, 0x04);
-       reg_write(client, 0x3106, 0x78);
-       reg_write(client, 0x310C, 0x82);
-       reg_write(client, 0x3304, 0x05);
-       reg_write(client, 0x3305, 0x04);
-       reg_write(client, 0x3306, 0x11);
-       reg_write(client, 0x3307, 0x02);
-       reg_write(client, 0x3308, 0x0C);
-       reg_write(client, 0x3309, 0x06);
-       reg_write(client, 0x330A, 0x08);
-       reg_write(client, 0x330B, 0x04);
-       reg_write(client, 0x330C, 0x08);
-       reg_write(client, 0x330D, 0x06);
-       reg_write(client, 0x330E, 0x01);
-       reg_write(client, 0x3381, 0x00);
-
-       /* V : 1/2V-addition (1,3), H : 1/2H-averaging (1,3) -> Full HD */
-       /* 1608 = 1560 + 48 (black lines) */
-       reg_write(client, FRAME_LENGTH_LINES_HI, 0x06);
-       reg_write(client, FRAME_LENGTH_LINES_LO, 0x48);
-       reg_write(client, YADDR_START, 0x00);
-       reg_write(client, YADDR_END, 0x2F);
-       /* 0x838 == 2104 */
-       reg_write(client, X_OUTPUT_SIZE_MSB, 0x08);
-       reg_write(client, X_OUTPUT_SIZE_LSB, 0x38);
-       /* 0x618 == 1560 */
-       reg_write(client, Y_OUTPUT_SIZE_MSB, 0x06);
-       reg_write(client, Y_OUTPUT_SIZE_LSB, 0x18);
-       reg_write(client, X_EVEN_INC, 0x01);
-       reg_write(client, X_ODD_INC, 0x03);
-       reg_write(client, Y_EVEN_INC, 0x01);
-       reg_write(client, Y_ODD_INC, 0x03);
-       reg_write(client, HMODEADD, 0x00);
-       reg_write(client, VMODEADD, 0x16);
-       reg_write(client, VAPPLINE_START, 0x24);
-       reg_write(client, VAPPLINE_END, 0x53);
-       reg_write(client, SHUTTER, 0x00);
-       reg_write(client, HADDAVE, 0x80);
-
-       reg_write(client, LANESEL, 0x00);
-
-       reg_write(client, GROUPED_PARAMETER_HOLD, 0x00);        /* off */
-
-       ret = 0;
-
-done:
-       imx074_s_power(subdev, 0);
-       return ret;
-}
-
-static int imx074_probe(struct i2c_client *client,
-                       const struct i2c_device_id *did)
-{
-       struct imx074 *priv;
-       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
-       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
-       int ret;
-
-       if (!ssdd) {
-               dev_err(&client->dev, "IMX074: missing platform data!\n");
-               return -EINVAL;
-       }
-
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
-               dev_warn(&adapter->dev,
-                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
-               return -EIO;
-       }
-
-       priv = devm_kzalloc(&client->dev, sizeof(struct imx074), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
-
-       priv->fmt       = &imx074_colour_fmts[0];
-
-       priv->clk = v4l2_clk_get(&client->dev, "mclk");
-       if (IS_ERR(priv->clk)) {
-               dev_info(&client->dev, "Error %ld getting clock\n", 
PTR_ERR(priv->clk));
-               return -EPROBE_DEFER;
-       }
-
-       ret = soc_camera_power_init(&client->dev, ssdd);
-       if (ret < 0)
-               goto epwrinit;
-
-       ret = imx074_video_probe(client);
-       if (ret < 0)
-               goto eprobe;
-
-       ret = v4l2_async_register_subdev(&priv->subdev);
-       if (!ret)
-               return 0;
-
-epwrinit:
-eprobe:
-       v4l2_clk_put(priv->clk);
-       return ret;
-}
-
-static int imx074_remove(struct i2c_client *client)
-{
-       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
-       struct imx074 *priv = to_imx074(client);
-
-       v4l2_async_unregister_subdev(&priv->subdev);
-       v4l2_clk_put(priv->clk);
-
-       if (ssdd->free_bus)
-               ssdd->free_bus(ssdd);
-
-       return 0;
-}
-
-static const struct i2c_device_id imx074_id[] = {
-       { "imx074", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, imx074_id);
-
-static struct i2c_driver imx074_i2c_driver = {
-       .driver = {
-               .name = "imx074",
-       },
-       .probe          = imx074_probe,
-       .remove         = imx074_remove,
-       .id_table       = imx074_id,
-};
-
-module_i2c_driver(imx074_i2c_driver);
-
-MODULE_DESCRIPTION("Sony IMX074 Camera driver");
-MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovet...@gmx.de>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index e68e1d343d53..9afdb2e279cc 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -29,6 +29,8 @@ source "drivers/staging/media/davinci_vpfe/Kconfig"
 
 source "drivers/staging/media/imx/Kconfig"
 
+source "drivers/staging/media/imx074/Kconfig"
+
 source "drivers/staging/media/omap4iss/Kconfig"
 
 source "drivers/staging/media/tegra-vde/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 59a47f69884f..9958466524ed 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -2,6 +2,7 @@
 obj-$(CONFIG_I2C_BCM2048)      += bcm2048/
 obj-$(CONFIG_DVB_CXD2099)      += cxd2099/
 obj-$(CONFIG_VIDEO_IMX_MEDIA)  += imx/
+obj-$(CONFIG_SOC_CAMERA_IMX074)        += imx074/
 obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
 obj-$(CONFIG_VIDEO_OMAP4)      += omap4iss/
 obj-$(CONFIG_INTEL_ATOMISP)     += atomisp/
diff --git a/drivers/staging/media/imx074/Kconfig 
b/drivers/staging/media/imx074/Kconfig
new file mode 100644
index 000000000000..229cbeea580b
--- /dev/null
+++ b/drivers/staging/media/imx074/Kconfig
@@ -0,0 +1,5 @@
+config SOC_CAMERA_IMX074
+       tristate "imx074 support (DEPRECATED)"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports IMX074 cameras from Sony
diff --git a/drivers/staging/media/imx074/Makefile 
b/drivers/staging/media/imx074/Makefile
new file mode 100644
index 000000000000..7d183574aa84
--- /dev/null
+++ b/drivers/staging/media/imx074/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
diff --git a/drivers/staging/media/imx074/TODO 
b/drivers/staging/media/imx074/TODO
new file mode 100644
index 000000000000..15580a4f950c
--- /dev/null
+++ b/drivers/staging/media/imx074/TODO
@@ -0,0 +1,5 @@
+This sensor driver needs to be converted to a regular
+v4l2 subdev driver. The soc_camera framework is deprecated and
+will be removed in the future. Unless someone does this work this
+sensor driver will be deleted when the soc_camera framework is
+deleted.
diff --git a/drivers/staging/media/imx074/imx074.c 
b/drivers/staging/media/imx074/imx074.c
new file mode 100644
index 000000000000..77f1e0243d6e
--- /dev/null
+++ b/drivers/staging/media/imx074/imx074.c
@@ -0,0 +1,497 @@
+/*
+ * Driver for IMX074 CMOS Image Sensor from Sony
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovet...@gmx.de>
+ *
+ * Partially inspired by the IMX074 driver from the Android / MSM tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-clk.h>
+#include <media/v4l2-subdev.h>
+
+/* IMX074 registers */
+
+#define MODE_SELECT                    0x0100
+#define IMAGE_ORIENTATION              0x0101
+#define GROUPED_PARAMETER_HOLD         0x0104
+
+/* Integration Time */
+#define COARSE_INTEGRATION_TIME_HI     0x0202
+#define COARSE_INTEGRATION_TIME_LO     0x0203
+/* Gain */
+#define ANALOGUE_GAIN_CODE_GLOBAL_HI   0x0204
+#define ANALOGUE_GAIN_CODE_GLOBAL_LO   0x0205
+
+/* PLL registers */
+#define PRE_PLL_CLK_DIV                        0x0305
+#define PLL_MULTIPLIER                 0x0307
+#define PLSTATIM                       0x302b
+#define VNDMY_ABLMGSHLMT               0x300a
+#define Y_OPBADDR_START_DI             0x3014
+/* mode setting */
+#define FRAME_LENGTH_LINES_HI          0x0340
+#define FRAME_LENGTH_LINES_LO          0x0341
+#define LINE_LENGTH_PCK_HI             0x0342
+#define LINE_LENGTH_PCK_LO             0x0343
+#define YADDR_START                    0x0347
+#define YADDR_END                      0x034b
+#define X_OUTPUT_SIZE_MSB              0x034c
+#define X_OUTPUT_SIZE_LSB              0x034d
+#define Y_OUTPUT_SIZE_MSB              0x034e
+#define Y_OUTPUT_SIZE_LSB              0x034f
+#define X_EVEN_INC                     0x0381
+#define X_ODD_INC                      0x0383
+#define Y_EVEN_INC                     0x0385
+#define Y_ODD_INC                      0x0387
+
+#define HMODEADD                       0x3001
+#define VMODEADD                       0x3016
+#define VAPPLINE_START                 0x3069
+#define VAPPLINE_END                   0x306b
+#define SHUTTER                                0x3086
+#define HADDAVE                                0x30e8
+#define LANESEL                                0x3301
+
+/* IMX074 supported geometry */
+#define IMX074_WIDTH                   1052
+#define IMX074_HEIGHT                  780
+
+/* IMX074 has only one fixed colorspace per pixelcode */
+struct imx074_datafmt {
+       u32     code;
+       enum v4l2_colorspace            colorspace;
+};
+
+struct imx074 {
+       struct v4l2_subdev              subdev;
+       const struct imx074_datafmt     *fmt;
+       struct v4l2_clk                 *clk;
+};
+
+static const struct imx074_datafmt imx074_colour_fmts[] = {
+       {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+};
+
+static struct imx074 *to_imx074(const struct i2c_client *client)
+{
+       return container_of(i2c_get_clientdata(client), struct imx074, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct imx074_datafmt *imx074_find_datafmt(u32 code)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(imx074_colour_fmts); i++)
+               if (imx074_colour_fmts[i].code == code)
+                       return imx074_colour_fmts + i;
+
+       return NULL;
+}
+
+static int reg_write(struct i2c_client *client, const u16 addr, const u8 data)
+{
+       struct i2c_adapter *adap = client->adapter;
+       struct i2c_msg msg;
+       unsigned char tx[3];
+       int ret;
+
+       msg.addr = client->addr;
+       msg.buf = tx;
+       msg.len = 3;
+       msg.flags = 0;
+
+       tx[0] = addr >> 8;
+       tx[1] = addr & 0xff;
+       tx[2] = data;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       mdelay(2);
+
+       return ret == 1 ? 0 : -EIO;
+}
+
+static int reg_read(struct i2c_client *client, const u16 addr)
+{
+       u8 buf[2] = {addr >> 8, addr & 0xff};
+       int ret;
+       struct i2c_msg msgs[] = {
+               {
+                       .addr  = client->addr,
+                       .flags = 0,
+                       .len   = 2,
+                       .buf   = buf,
+               }, {
+                       .addr  = client->addr,
+                       .flags = I2C_M_RD,
+                       .len   = 2,
+                       .buf   = buf,
+               },
+       };
+
+       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (ret < 0) {
+               dev_warn(&client->dev, "Reading register %x from %x failed\n",
+                        addr, client->addr);
+               return ret;
+       }
+
+       return buf[0] & 0xff; /* no sign-extension */
+}
+
+static int imx074_set_fmt(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct imx074 *priv = to_imx074(client);
+
+       if (format->pad)
+               return -EINVAL;
+
+       dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
+
+       if (!fmt) {
+               /* MIPI CSI could have changed the format, double-check */
+               if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+                       return -EINVAL;
+               mf->code        = imx074_colour_fmts[0].code;
+               mf->colorspace  = imx074_colour_fmts[0].colorspace;
+       }
+
+       mf->width       = IMX074_WIDTH;
+       mf->height      = IMX074_HEIGHT;
+       mf->field       = V4L2_FIELD_NONE;
+
+       if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               priv->fmt = fmt;
+       else
+               cfg->try_fmt = *mf;
+
+       return 0;
+}
+
+static int imx074_get_fmt(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_format *format)
+{
+       struct v4l2_mbus_framefmt *mf = &format->format;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct imx074 *priv = to_imx074(client);
+
+       const struct imx074_datafmt *fmt = priv->fmt;
+
+       if (format->pad)
+               return -EINVAL;
+
+       mf->code        = fmt->code;
+       mf->colorspace  = fmt->colorspace;
+       mf->width       = IMX074_WIDTH;
+       mf->height      = IMX074_HEIGHT;
+       mf->field       = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static int imx074_get_selection(struct v4l2_subdev *sd,
+                               struct v4l2_subdev_pad_config *cfg,
+                               struct v4l2_subdev_selection *sel)
+{
+       if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+               return -EINVAL;
+
+       sel->r.left = 0;
+       sel->r.top = 0;
+       sel->r.width = IMX074_WIDTH;
+       sel->r.height = IMX074_HEIGHT;
+
+       switch (sel->target) {
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_CROP:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int imx074_enum_mbus_code(struct v4l2_subdev *sd,
+               struct v4l2_subdev_pad_config *cfg,
+               struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->pad ||
+           (unsigned int)code->index >= ARRAY_SIZE(imx074_colour_fmts))
+               return -EINVAL;
+
+       code->code = imx074_colour_fmts[code->index].code;
+       return 0;
+}
+
+static int imx074_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       /* MODE_SELECT: stream or standby */
+       return reg_write(client, MODE_SELECT, !!enable);
+}
+
+static int imx074_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
+       struct imx074 *priv = to_imx074(client);
+
+       return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
+}
+
+static int imx074_g_mbus_config(struct v4l2_subdev *sd,
+                               struct v4l2_mbus_config *cfg)
+{
+       cfg->type = V4L2_MBUS_CSI2;
+       cfg->flags = V4L2_MBUS_CSI2_2_LANE |
+               V4L2_MBUS_CSI2_CHANNEL_0 |
+               V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
+       .s_stream       = imx074_s_stream,
+       .g_mbus_config  = imx074_g_mbus_config,
+};
+
+static const struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
+       .s_power        = imx074_s_power,
+};
+
+static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
+       .enum_mbus_code = imx074_enum_mbus_code,
+       .get_selection  = imx074_get_selection,
+       .get_fmt        = imx074_get_fmt,
+       .set_fmt        = imx074_set_fmt,
+};
+
+static const struct v4l2_subdev_ops imx074_subdev_ops = {
+       .core   = &imx074_subdev_core_ops,
+       .video  = &imx074_subdev_video_ops,
+       .pad    = &imx074_subdev_pad_ops,
+};
+
+static int imx074_video_probe(struct i2c_client *client)
+{
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+       int ret;
+       u16 id;
+
+       ret = imx074_s_power(subdev, 1);
+       if (ret < 0)
+               return ret;
+
+       /* Read sensor Model ID */
+       ret = reg_read(client, 0);
+       if (ret < 0)
+               goto done;
+
+       id = ret << 8;
+
+       ret = reg_read(client, 1);
+       if (ret < 0)
+               goto done;
+
+       id |= ret;
+
+       dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
+
+       if (id != 0x74) {
+               ret = -ENODEV;
+               goto done;
+       }
+
+       /* PLL Setting EXTCLK=24MHz, 22.5times */
+       reg_write(client, PLL_MULTIPLIER, 0x2D);
+       reg_write(client, PRE_PLL_CLK_DIV, 0x02);
+       reg_write(client, PLSTATIM, 0x4B);
+
+       /* 2-lane mode */
+       reg_write(client, 0x3024, 0x00);
+
+       reg_write(client, IMAGE_ORIENTATION, 0x00);
+
+       /* select RAW mode:
+        * 0x08+0x08 = top 8 bits
+        * 0x0a+0x08 = compressed 8-bits
+        * 0x0a+0x0a = 10 bits
+        */
+       reg_write(client, 0x0112, 0x08);
+       reg_write(client, 0x0113, 0x08);
+
+       /* Base setting for High frame mode */
+       reg_write(client, VNDMY_ABLMGSHLMT, 0x80);
+       reg_write(client, Y_OPBADDR_START_DI, 0x08);
+       reg_write(client, 0x3015, 0x37);
+       reg_write(client, 0x301C, 0x01);
+       reg_write(client, 0x302C, 0x05);
+       reg_write(client, 0x3031, 0x26);
+       reg_write(client, 0x3041, 0x60);
+       reg_write(client, 0x3051, 0x24);
+       reg_write(client, 0x3053, 0x34);
+       reg_write(client, 0x3057, 0xC0);
+       reg_write(client, 0x305C, 0x09);
+       reg_write(client, 0x305D, 0x07);
+       reg_write(client, 0x3060, 0x30);
+       reg_write(client, 0x3065, 0x00);
+       reg_write(client, 0x30AA, 0x08);
+       reg_write(client, 0x30AB, 0x1C);
+       reg_write(client, 0x30B0, 0x32);
+       reg_write(client, 0x30B2, 0x83);
+       reg_write(client, 0x30D3, 0x04);
+       reg_write(client, 0x3106, 0x78);
+       reg_write(client, 0x310C, 0x82);
+       reg_write(client, 0x3304, 0x05);
+       reg_write(client, 0x3305, 0x04);
+       reg_write(client, 0x3306, 0x11);
+       reg_write(client, 0x3307, 0x02);
+       reg_write(client, 0x3308, 0x0C);
+       reg_write(client, 0x3309, 0x06);
+       reg_write(client, 0x330A, 0x08);
+       reg_write(client, 0x330B, 0x04);
+       reg_write(client, 0x330C, 0x08);
+       reg_write(client, 0x330D, 0x06);
+       reg_write(client, 0x330E, 0x01);
+       reg_write(client, 0x3381, 0x00);
+
+       /* V : 1/2V-addition (1,3), H : 1/2H-averaging (1,3) -> Full HD */
+       /* 1608 = 1560 + 48 (black lines) */
+       reg_write(client, FRAME_LENGTH_LINES_HI, 0x06);
+       reg_write(client, FRAME_LENGTH_LINES_LO, 0x48);
+       reg_write(client, YADDR_START, 0x00);
+       reg_write(client, YADDR_END, 0x2F);
+       /* 0x838 == 2104 */
+       reg_write(client, X_OUTPUT_SIZE_MSB, 0x08);
+       reg_write(client, X_OUTPUT_SIZE_LSB, 0x38);
+       /* 0x618 == 1560 */
+       reg_write(client, Y_OUTPUT_SIZE_MSB, 0x06);
+       reg_write(client, Y_OUTPUT_SIZE_LSB, 0x18);
+       reg_write(client, X_EVEN_INC, 0x01);
+       reg_write(client, X_ODD_INC, 0x03);
+       reg_write(client, Y_EVEN_INC, 0x01);
+       reg_write(client, Y_ODD_INC, 0x03);
+       reg_write(client, HMODEADD, 0x00);
+       reg_write(client, VMODEADD, 0x16);
+       reg_write(client, VAPPLINE_START, 0x24);
+       reg_write(client, VAPPLINE_END, 0x53);
+       reg_write(client, SHUTTER, 0x00);
+       reg_write(client, HADDAVE, 0x80);
+
+       reg_write(client, LANESEL, 0x00);
+
+       reg_write(client, GROUPED_PARAMETER_HOLD, 0x00);        /* off */
+
+       ret = 0;
+
+done:
+       imx074_s_power(subdev, 0);
+       return ret;
+}
+
+static int imx074_probe(struct i2c_client *client,
+                       const struct i2c_device_id *did)
+{
+       struct imx074 *priv;
+       struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
+       int ret;
+
+       if (!ssdd) {
+               dev_err(&client->dev, "IMX074: missing platform data!\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_warn(&adapter->dev,
+                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
+               return -EIO;
+       }
+
+       priv = devm_kzalloc(&client->dev, sizeof(struct imx074), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
+
+       priv->fmt       = &imx074_colour_fmts[0];
+
+       priv->clk = v4l2_clk_get(&client->dev, "mclk");
+       if (IS_ERR(priv->clk)) {
+               dev_info(&client->dev, "Error %ld getting clock\n", 
PTR_ERR(priv->clk));
+               return -EPROBE_DEFER;
+       }
+
+       ret = soc_camera_power_init(&client->dev, ssdd);
+       if (ret < 0)
+               goto epwrinit;
+
+       ret = imx074_video_probe(client);
+       if (ret < 0)
+               goto eprobe;
+
+       ret = v4l2_async_register_subdev(&priv->subdev);
+       if (!ret)
+               return 0;
+
+epwrinit:
+eprobe:
+       v4l2_clk_put(priv->clk);
+       return ret;
+}
+
+static int imx074_remove(struct i2c_client *client)
+{
+       struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
+       struct imx074 *priv = to_imx074(client);
+
+       v4l2_async_unregister_subdev(&priv->subdev);
+       v4l2_clk_put(priv->clk);
+
+       if (ssdd->free_bus)
+               ssdd->free_bus(ssdd);
+
+       return 0;
+}
+
+static const struct i2c_device_id imx074_id[] = {
+       { "imx074", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, imx074_id);
+
+static struct i2c_driver imx074_i2c_driver = {
+       .driver = {
+               .name = "imx074",
+       },
+       .probe          = imx074_probe,
+       .remove         = imx074_remove,
+       .id_table       = imx074_id,
+};
+
+module_i2c_driver(imx074_i2c_driver);
+
+MODULE_DESCRIPTION("Sony IMX074 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovet...@gmx.de>");
+MODULE_LICENSE("GPL v2");

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
https://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to