aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch
diff options
context:
space:
mode:
authorÁlvaro Fernández Rojas <noltari@gmail.com>2021-08-21 10:54:34 +0200
committerÁlvaro Fernández Rojas <noltari@gmail.com>2021-08-21 19:07:07 +0200
commit8299d1f057439f94c6a4412e2e5c5082b82a30c9 (patch)
tree1bf678d61f11f7394493be464c7876e496f7faed /target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch
parent33b6885975ce376ff075362b7f0890326043111b (diff)
downloadupstream-8299d1f057439f94c6a4412e2e5c5082b82a30c9.tar.gz
upstream-8299d1f057439f94c6a4412e2e5c5082b82a30c9.tar.bz2
upstream-8299d1f057439f94c6a4412e2e5c5082b82a30c9.zip
bcm27xx: add kernel 5.10 support
Rebased RPi foundation patches on linux 5.10.59, removed applied and reverted patches, wireless patches and defconfig patches. bcm2708: boot tested on RPi B+ v1.2 bcm2709: boot tested on RPi 4B v1.1 4G bcm2711: boot tested on RPi 4B v1.1 4G Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch190
1 files changed, 190 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch b/target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch
new file mode 100644
index 0000000000..bbb5afae9e
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.10/950-0659-media-i2c-imx477-Extend-driver-to-support-imx378-sen.patch
@@ -0,0 +1,190 @@
+From c298f9514f99b9dfde64bb5f07fe09ee8dfdcd48 Mon Sep 17 00:00:00 2001
+From: David Plowman <david.plowman@raspberrypi.com>
+Date: Tue, 29 Jun 2021 14:43:01 +0100
+Subject: [PATCH] media: i2c: imx477: Extend driver to support imx378
+ sensor
+
+The imx378 sensor is almost identical to the imx477 and can be
+supported as a "compatible" sensor with just a few extra register
+writes.
+
+Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+---
+ drivers/media/i2c/Kconfig | 2 +-
+ drivers/media/i2c/imx477.c | 68 +++++++++++++++++++++++++++++++++-----
+ 2 files changed, 60 insertions(+), 10 deletions(-)
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -807,7 +807,7 @@ config VIDEO_IMX477
+ depends on MEDIA_CAMERA_SUPPORT
+ help
+ This is a Video4Linux2 sensor driver for the Sony
+- IMX477 camera.
++ IMX477 camera. Also supports the Sony IMX378.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx477.
+--- a/drivers/media/i2c/imx477.c
++++ b/drivers/media/i2c/imx477.c
+@@ -12,6 +12,7 @@
+ #include <linux/gpio/consumer.h>
+ #include <linux/i2c.h>
+ #include <linux/module.h>
++#include <linux/of_device.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <media/v4l2-ctrls.h>
+@@ -26,6 +27,7 @@
+ /* Chip ID */
+ #define IMX477_REG_CHIP_ID 0x0016
+ #define IMX477_CHIP_ID 0x0477
++#define IMX378_CHIP_ID 0x0378
+
+ #define IMX477_REG_MODE_SELECT 0x0100
+ #define IMX477_MODE_STANDBY 0x00
+@@ -1069,6 +1071,11 @@ static const char * const imx477_supply_
+ #define IMX477_XCLR_MIN_DELAY_US 8000
+ #define IMX477_XCLR_DELAY_RANGE_US 1000
+
++struct imx477_compatible_data {
++ unsigned int chip_id;
++ struct imx477_reg_list extra_regs;
++};
++
+ struct imx477 {
+ struct v4l2_subdev sd;
+ struct media_pad pad[NUM_PADS];
+@@ -1107,6 +1114,9 @@ struct imx477 {
+
+ /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
+ unsigned int long_exp_shift;
++
++ /* Any extra information related to different compatible sensors */
++ const struct imx477_compatible_data *compatible_data;
+ };
+
+ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
+@@ -1673,11 +1683,18 @@ static int imx477_start_streaming(struct
+ {
+ struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
+ const struct imx477_reg_list *reg_list;
++ const struct imx477_reg_list *extra_regs;
+ int ret;
+
+ if (!imx477->common_regs_written) {
+ ret = imx477_write_regs(imx477, mode_common_regs,
+ ARRAY_SIZE(mode_common_regs));
++ if (!ret) {
++ extra_regs = &imx477->compatible_data->extra_regs;
++ ret = imx477_write_regs(imx477, extra_regs->regs,
++ extra_regs->num_of_regs);
++ }
++
+ if (ret) {
+ dev_err(&client->dev, "%s failed to set common settings\n",
+ __func__);
+@@ -1863,7 +1880,7 @@ static int imx477_get_regulators(struct
+ }
+
+ /* Verify chip ID */
+-static int imx477_identify_module(struct imx477 *imx477)
++static int imx477_identify_module(struct imx477 *imx477, u32 expected_id)
+ {
+ struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
+ int ret;
+@@ -1873,16 +1890,18 @@ static int imx477_identify_module(struct
+ IMX477_REG_VALUE_16BIT, &val);
+ if (ret) {
+ dev_err(&client->dev, "failed to read chip id %x, with error %d\n",
+- IMX477_CHIP_ID, ret);
++ expected_id, ret);
+ return ret;
+ }
+
+- if (val != IMX477_CHIP_ID) {
++ if (val != expected_id) {
+ dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
+- IMX477_CHIP_ID, val);
++ expected_id, val);
+ return -EIO;
+ }
+
++ dev_info(&client->dev, "Device found is imx%x\n", val);
++
+ return 0;
+ }
+
+@@ -2078,10 +2097,39 @@ error_out:
+ return ret;
+ }
+
++static const struct imx477_compatible_data imx477_compatible = {
++ .chip_id = IMX477_CHIP_ID,
++ .extra_regs = {
++ .num_of_regs = 0,
++ .regs = NULL
++ }
++};
++
++static const struct imx477_reg imx378_regs[] = {
++ {0x3e35, 0x01},
++ {0x4421, 0x08},
++ {0x3ff9, 0x00},
++};
++
++static const struct imx477_compatible_data imx378_compatible = {
++ .chip_id = IMX378_CHIP_ID,
++ .extra_regs = {
++ .num_of_regs = ARRAY_SIZE(imx378_regs),
++ .regs = imx378_regs
++ }
++};
++
++static const struct of_device_id imx477_dt_ids[] = {
++ { .compatible = "sony,imx477", .data = &imx477_compatible },
++ { .compatible = "sony,imx378", .data = &imx378_compatible },
++ { /* sentinel */ }
++};
++
+ static int imx477_probe(struct i2c_client *client)
+ {
+ struct device *dev = &client->dev;
+ struct imx477 *imx477;
++ const struct of_device_id *match;
+ int ret;
+
+ imx477 = devm_kzalloc(&client->dev, sizeof(*imx477), GFP_KERNEL);
+@@ -2090,6 +2138,12 @@ static int imx477_probe(struct i2c_clien
+
+ v4l2_i2c_subdev_init(&imx477->sd, client, &imx477_subdev_ops);
+
++ match = of_match_device(imx477_dt_ids, dev);
++ if (!match)
++ return -ENODEV;
++ imx477->compatible_data =
++ (const struct imx477_compatible_data *)match->data;
++
+ /* Check the hardware configuration in device tree */
+ if (imx477_check_hwcfg(dev))
+ return -EINVAL;
+@@ -2126,7 +2180,7 @@ static int imx477_probe(struct i2c_clien
+ if (ret)
+ return ret;
+
+- ret = imx477_identify_module(imx477);
++ ret = imx477_identify_module(imx477, imx477->compatible_data->chip_id);
+ if (ret)
+ goto error_power_off;
+
+@@ -2198,10 +2252,6 @@ static int imx477_remove(struct i2c_clie
+ return 0;
+ }
+
+-static const struct of_device_id imx477_dt_ids[] = {
+- { .compatible = "sony,imx477" },
+- { /* sentinel */ }
+-};
+ MODULE_DEVICE_TABLE(of, imx477_dt_ids);
+
+ static const struct dev_pm_ops imx477_pm_ops = {