aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch181
1 files changed, 181 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch b/target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch
new file mode 100644
index 0000000000..9e9b2729cc
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0793-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch
@@ -0,0 +1,181 @@
+From be2df6c864ba668364011301530372f5b8798593 Mon Sep 17 00:00:00 2001
+From: Markus Proeller <markus.proeller@pieye.org>
+Date: Tue, 16 Jun 2020 13:33:56 +0200
+Subject: [PATCH] media: irs1125: Keep HW in sync after imager reset
+
+When closing the video device, the irs1125 is put in power down state.
+To keep V4L2 ctrls and the HW in sync, v4l2_ctrl_handler_setup is
+called after power up.
+
+The compound ctrl IRS1125_CID_MOD_PLL however has a default value
+of all zeros, which puts the imager into a non responding state.
+Thus, this ctrl is not written by the driver into HW after power up.
+The userspace has to take care to write senseful data.
+
+Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
+---
+ drivers/media/i2c/irs1125.c | 121 +++++++++++++++++-------------------
+ 1 file changed, 58 insertions(+), 63 deletions(-)
+
+--- a/drivers/media/i2c/irs1125.c
++++ b/drivers/media/i2c/irs1125.c
+@@ -82,6 +82,7 @@ struct irs1125 {
+ struct v4l2_ctrl *ctrl_numseq;
+
+ int power_count;
++ bool mod_pll_init;
+ };
+
+ static inline struct irs1125 *to_state(struct v4l2_subdev *sd)
+@@ -276,8 +277,7 @@ static struct regval_list irs1125_seq_cf
+ {0xC039, 0x0000},
+ {0xC401, 0x0002},
+
+- {0xFFFF, 1},
+- {0xA87C, 0x0001}
++ {0xFFFF, 1}
+ };
+
+ static int irs1125_write(struct v4l2_subdev *sd, u16 reg, u16 val)
+@@ -471,7 +471,11 @@ static int __sensor_init(struct v4l2_sub
+ return ret;
+ }
+
+- return 0;
++ irs1125->mod_pll_init = true;
++ v4l2_ctrl_handler_setup(&irs1125->ctrl_handler);
++ irs1125->mod_pll_init = false;
++
++ return irs1125_write(sd, 0xA87C, 0x0001);
+ }
+
+ static int irs1125_sensor_power(struct v4l2_subdev *sd, int on)
+@@ -607,8 +611,6 @@ static int irs1125_s_ctrl(struct v4l2_ct
+ struct irs1125 *dev = container_of(ctrl->handler,
+ struct irs1125, ctrl_handler);
+ struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
+- struct irs1125_mod_pll *mod_cur, *mod_new;
+- u16 addr, val;
+ int err = 0, i;
+
+ switch (ctrl->id) {
+@@ -660,68 +662,61 @@ static int irs1125_s_ctrl(struct v4l2_ct
+ ctrl->val);
+ break;
+ }
+- case IRS1125_CID_MOD_PLL:
++ case IRS1125_CID_MOD_PLL: {
++ struct irs1125_mod_pll *mod_new;
++
++ if (dev->mod_pll_init)
++ break;
++
+ mod_new = (struct irs1125_mod_pll *)ctrl->p_new.p;
+- mod_cur = (struct irs1125_mod_pll *)ctrl->p_cur.p;
+ for (i = 0; i < IRS1125_NUM_MOD_PLLS; i++) {
+- if (mod_cur[i].pllcfg1 != mod_new[i].pllcfg1) {
+- addr = 0xC3A0 + i * 3;
+- val = mod_new[i].pllcfg1;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg2 != mod_new[i].pllcfg2) {
+- addr = 0xC3A1 + i * 3;
+- val = mod_new[i].pllcfg2;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg3 != mod_new[i].pllcfg3) {
+- addr = 0xC3A2 + i * 3;
+- val = mod_new[i].pllcfg3;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg4 != mod_new[i].pllcfg4) {
+- addr = 0xC24C + i * 5;
+- val = mod_new[i].pllcfg4;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg5 != mod_new[i].pllcfg5) {
+- addr = 0xC24D + i * 5;
+- val = mod_new[i].pllcfg5;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg6 != mod_new[i].pllcfg6) {
+- addr = 0xC24E + i * 5;
+- val = mod_new[i].pllcfg6;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg7 != mod_new[i].pllcfg7) {
+- addr = 0xC24F + i * 5;
+- val = mod_new[i].pllcfg7;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
+- if (mod_cur[i].pllcfg8 != mod_new[i].pllcfg8) {
+- addr = 0xC250 + i * 5;
+- val = mod_new[i].pllcfg8;
+- err = irs1125_write(&dev->sd, addr, val);
+- if (err < 0)
+- break;
+- }
++ unsigned int pll_offset, ssc_offset;
++
++ pll_offset = i * 3;
++ ssc_offset = i * 5;
++
++ err = irs1125_write(&dev->sd, 0xC3A0 + pll_offset,
++ mod_new[i].pllcfg1);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC3A1 + pll_offset,
++ mod_new[i].pllcfg2);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC3A2 + pll_offset,
++ mod_new[i].pllcfg3);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC24C + ssc_offset,
++ mod_new[i].pllcfg4);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC24D + ssc_offset,
++ mod_new[i].pllcfg5);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC24E + ssc_offset,
++ mod_new[i].pllcfg6);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC24F + ssc_offset,
++ mod_new[i].pllcfg7);
++ if (err < 0)
++ break;
++
++ err = irs1125_write(&dev->sd, 0xC250 + ssc_offset,
++ mod_new[i].pllcfg8);
++ if (err < 0)
++ break;
+ }
+ break;
++ }
+ case IRS1125_CID_SEQ_CONFIG: {
+ struct irs1125_seq_cfg *cfg_new;
+