--- /dev/null
+From c26b5aa8ef0d46035060fded475e6ab957b9f69f Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Sun, 11 Nov 2018 11:15:21 +0000
+Subject: gfs2: Fix iomap buffer head reference counting bug
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+commit c26b5aa8ef0d46035060fded475e6ab957b9f69f upstream.
+
+GFS2 passes the inode buffer head (dibh) from gfs2_iomap_begin to
+gfs2_iomap_end in iomap->private. It sets that private pointer in
+gfs2_iomap_get. Users of gfs2_iomap_get other than gfs2_iomap_begin
+would have to release iomap->private, but this isn't done correctly,
+leading to a leak of buffer head references.
+
+To fix this, move the code for setting iomap->private from
+gfs2_iomap_get to gfs2_iomap_begin.
+
+Fixes: 64bc06bb32 ("gfs2: iomap buffered write support")
+Cc: stable@vger.kernel.org # v4.19+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/gfs2/bmap.c | 40 +++++++++++++++++-----------------------
+ 1 file changed, 17 insertions(+), 23 deletions(-)
+
+--- a/fs/gfs2/bmap.c
++++ b/fs/gfs2/bmap.c
+@@ -826,7 +826,7 @@ static int gfs2_iomap_get(struct inode *
+ ret = gfs2_meta_inode_buffer(ip, &dibh);
+ if (ret)
+ goto unlock;
+- iomap->private = dibh;
++ mp->mp_bh[0] = dibh;
+
+ if (gfs2_is_stuffed(ip)) {
+ if (flags & IOMAP_WRITE) {
+@@ -863,9 +863,6 @@ unstuff:
+ len = lblock_stop - lblock + 1;
+ iomap->length = len << inode->i_blkbits;
+
+- get_bh(dibh);
+- mp->mp_bh[0] = dibh;
+-
+ height = ip->i_height;
+ while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height])
+ height++;
+@@ -898,8 +895,6 @@ out:
+ iomap->bdev = inode->i_sb->s_bdev;
+ unlock:
+ up_read(&ip->i_rw_mutex);
+- if (ret && dibh)
+- brelse(dibh);
+ return ret;
+
+ do_alloc:
+@@ -980,9 +975,9 @@ static void gfs2_iomap_journaled_page_do
+
+ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
+ loff_t length, unsigned flags,
+- struct iomap *iomap)
++ struct iomap *iomap,
++ struct metapath *mp)
+ {
+- struct metapath mp = { .mp_aheight = 1, };
+ struct gfs2_inode *ip = GFS2_I(inode);
+ struct gfs2_sbd *sdp = GFS2_SB(inode);
+ unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
+@@ -996,9 +991,9 @@ static int gfs2_iomap_begin_write(struct
+ unstuff = gfs2_is_stuffed(ip) &&
+ pos + length > gfs2_max_stuffed_size(ip);
+
+- ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
++ ret = gfs2_iomap_get(inode, pos, length, flags, iomap, mp);
+ if (ret)
+- goto out_release;
++ goto out_unlock;
+
+ alloc_required = unstuff || iomap->type == IOMAP_HOLE;
+
+@@ -1013,7 +1008,7 @@ static int gfs2_iomap_begin_write(struct
+
+ ret = gfs2_quota_lock_check(ip, &ap);
+ if (ret)
+- goto out_release;
++ goto out_unlock;
+
+ ret = gfs2_inplace_reserve(ip, &ap);
+ if (ret)
+@@ -1038,17 +1033,15 @@ static int gfs2_iomap_begin_write(struct
+ ret = gfs2_unstuff_dinode(ip, NULL);
+ if (ret)
+ goto out_trans_end;
+- release_metapath(&mp);
+- brelse(iomap->private);
+- iomap->private = NULL;
++ release_metapath(mp);
+ ret = gfs2_iomap_get(inode, iomap->offset, iomap->length,
+- flags, iomap, &mp);
++ flags, iomap, mp);
+ if (ret)
+ goto out_trans_end;
+ }
+
+ if (iomap->type == IOMAP_HOLE) {
+- ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
++ ret = gfs2_iomap_alloc(inode, iomap, flags, mp);
+ if (ret) {
+ gfs2_trans_end(sdp);
+ gfs2_inplace_release(ip);
+@@ -1056,7 +1049,6 @@ static int gfs2_iomap_begin_write(struct
+ goto out_qunlock;
+ }
+ }
+- release_metapath(&mp);
+ if (!gfs2_is_stuffed(ip) && gfs2_is_jdata(ip))
+ iomap->page_done = gfs2_iomap_journaled_page_done;
+ return 0;
+@@ -1069,10 +1061,7 @@ out_trans_fail:
+ out_qunlock:
+ if (alloc_required)
+ gfs2_quota_unlock(ip);
+-out_release:
+- if (iomap->private)
+- brelse(iomap->private);
+- release_metapath(&mp);
++out_unlock:
+ gfs2_write_unlock(inode);
+ return ret;
+ }
+@@ -1088,10 +1077,10 @@ static int gfs2_iomap_begin(struct inode
+
+ trace_gfs2_iomap_start(ip, pos, length, flags);
+ if ((flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT)) {
+- ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap);
++ ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp);
+ } else {
+ ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
+- release_metapath(&mp);
++
+ /*
+ * Silently fall back to buffered I/O for stuffed files or if
+ * we've hot a hole (see gfs2_file_direct_write).
+@@ -1100,6 +1089,11 @@ static int gfs2_iomap_begin(struct inode
+ iomap->type != IOMAP_MAPPED)
+ ret = -ENOTBLK;
+ }
++ if (!ret) {
++ get_bh(mp.mp_bh[0]);
++ iomap->private = mp.mp_bh[0];
++ }
++ release_metapath(&mp);
+ trace_gfs2_iomap_end(ip, iomap, ret);
+ return ret;
+ }
--- /dev/null
+From a8f438c684eaa4cbe6c98828eb996d5ec53e24fb Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:20 -0400
+Subject: media: ov5640: fix auto controls values when switching to manual mode
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+commit a8f438c684eaa4cbe6c98828eb996d5ec53e24fb upstream.
+
+When switching from auto to manual mode, V4L2 core is calling
+g_volatile_ctrl() in manual mode in order to get the manual initial value.
+Remove the manual mode check/return to not break this behaviour.
+
+Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
+Tested-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/i2c/ov5640.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -2337,16 +2337,12 @@ static int ov5640_g_volatile_ctrl(struct
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUTOGAIN:
+- if (!ctrl->val)
+- return 0;
+ val = ov5640_get_gain(sensor);
+ if (val < 0)
+ return val;
+ sensor->ctrls.gain->val = val;
+ break;
+ case V4L2_CID_EXPOSURE_AUTO:
+- if (ctrl->val == V4L2_EXPOSURE_MANUAL)
+- return 0;
+ val = ov5640_get_exposure(sensor);
+ if (val < 0)
+ return val;
--- /dev/null
+From 3cca8ef5f774cbd61c8db05d9aa401de9bb59c66 Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:18 -0400
+Subject: media: ov5640: fix auto gain & exposure when changing mode
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+commit 3cca8ef5f774cbd61c8db05d9aa401de9bb59c66 upstream.
+
+Ensure that auto gain and auto exposure are well restored
+when changing mode.
+
+Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
+Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
+Tested-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/i2c/ov5640.c | 96 +++++++++++++++++++++++++--------------------
+ 1 file changed, 54 insertions(+), 42 deletions(-)
+
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -1022,6 +1022,18 @@ static int ov5640_get_gain(struct ov5640
+ return gain & 0x3ff;
+ }
+
++static int ov5640_set_gain(struct ov5640_dev *sensor, int gain)
++{
++ return ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN,
++ (u16)gain & 0x3ff);
++}
++
++static int ov5640_set_autogain(struct ov5640_dev *sensor, bool on)
++{
++ return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
++ BIT(1), on ? 0 : BIT(1));
++}
++
+ static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on)
+ {
+ int ret;
+@@ -1588,7 +1600,7 @@ static int ov5640_set_mode_exposure_calc
+ }
+
+ /* set capture gain */
+- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.gain, cap_gain16);
++ ret = ov5640_set_gain(sensor, cap_gain16);
+ if (ret)
+ return ret;
+
+@@ -1601,7 +1613,7 @@ static int ov5640_set_mode_exposure_calc
+ }
+
+ /* set exposure */
+- return __v4l2_ctrl_s_ctrl(sensor->ctrls.exposure, cap_shutter);
++ return ov5640_set_exposure(sensor, cap_shutter);
+ }
+
+ /*
+@@ -1609,26 +1621,13 @@ static int ov5640_set_mode_exposure_calc
+ * change mode directly
+ */
+ static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
+- const struct ov5640_mode_info *mode,
+- bool auto_exp)
++ const struct ov5640_mode_info *mode)
+ {
+- int ret;
+-
+ if (!mode->reg_data)
+ return -EINVAL;
+
+ /* Write capture setting */
+- ret = ov5640_load_regs(sensor, mode);
+- if (ret < 0)
+- return ret;
+-
+- /* turn auto gain/exposure back on for direct mode */
+- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1);
+- if (ret)
+- return ret;
+-
+- return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, auto_exp ?
+- V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL);
++ return ov5640_load_regs(sensor, mode);
+ }
+
+ static int ov5640_set_mode(struct ov5640_dev *sensor)
+@@ -1636,6 +1635,7 @@ static int ov5640_set_mode(struct ov5640
+ const struct ov5640_mode_info *mode = sensor->current_mode;
+ const struct ov5640_mode_info *orig_mode = sensor->last_mode;
+ enum ov5640_downsize_mode dn_mode, orig_dn_mode;
++ bool auto_gain = sensor->ctrls.auto_gain->val == 1;
+ bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
+ int ret;
+
+@@ -1643,19 +1643,23 @@ static int ov5640_set_mode(struct ov5640
+ orig_dn_mode = orig_mode->dn_mode;
+
+ /* auto gain and exposure must be turned off when changing modes */
+- ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 0);
+- if (ret)
+- return ret;
++ if (auto_gain) {
++ ret = ov5640_set_autogain(sensor, false);
++ if (ret)
++ return ret;
++ }
+
+- ret = ov5640_set_autoexposure(sensor, false);
+- if (ret)
+- return ret;
++ if (auto_exp) {
++ ret = ov5640_set_autoexposure(sensor, false);
++ if (ret)
++ goto restore_auto_gain;
++ }
+
+ if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
+ (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
+ /*
+ * change between subsampling and scaling
+- * go through exposure calucation
++ * go through exposure calculation
+ */
+ ret = ov5640_set_mode_exposure_calc(sensor, mode);
+ } else {
+@@ -1663,11 +1667,16 @@ static int ov5640_set_mode(struct ov5640
+ * change inside subsampling or scaling
+ * download firmware directly
+ */
+- ret = ov5640_set_mode_direct(sensor, mode, auto_exp);
++ ret = ov5640_set_mode_direct(sensor, mode);
+ }
+-
+ if (ret < 0)
+- return ret;
++ goto restore_auto_exp_gain;
++
++ /* restore auto gain and exposure */
++ if (auto_gain)
++ ov5640_set_autogain(sensor, true);
++ if (auto_exp)
++ ov5640_set_autoexposure(sensor, true);
+
+ ret = ov5640_set_binning(sensor, dn_mode != SCALING);
+ if (ret < 0)
+@@ -1689,6 +1698,15 @@ static int ov5640_set_mode(struct ov5640
+ sensor->last_mode = mode;
+
+ return 0;
++
++restore_auto_exp_gain:
++ if (auto_exp)
++ ov5640_set_autoexposure(sensor, true);
++restore_auto_gain:
++ if (auto_gain)
++ ov5640_set_autogain(sensor, true);
++
++ return ret;
+ }
+
+ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
+@@ -2201,20 +2219,20 @@ static int ov5640_set_ctrl_white_balance
+ return ret;
+ }
+
+-static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor, int exp)
++static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
++ enum v4l2_exposure_auto_type auto_exposure)
+ {
+ struct ov5640_ctrls *ctrls = &sensor->ctrls;
+- bool auto_exposure = (exp == V4L2_EXPOSURE_AUTO);
++ bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO);
+ int ret = 0;
+
+ if (ctrls->auto_exp->is_new) {
+- ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
+- BIT(0), auto_exposure ? 0 : BIT(0));
++ ret = ov5640_set_autoexposure(sensor, auto_exp);
+ if (ret)
+ return ret;
+ }
+
+- if (!auto_exposure && ctrls->exposure->is_new) {
++ if (!auto_exp && ctrls->exposure->is_new) {
+ u16 max_exp;
+
+ ret = ov5640_read_reg16(sensor, OV5640_REG_AEC_PK_VTS,
+@@ -2234,25 +2252,19 @@ static int ov5640_set_ctrl_exposure(stru
+ return ret;
+ }
+
+-static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, int auto_gain)
++static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
+ {
+ struct ov5640_ctrls *ctrls = &sensor->ctrls;
+ int ret = 0;
+
+ if (ctrls->auto_gain->is_new) {
+- ret = ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
+- BIT(1),
+- ctrls->auto_gain->val ? 0 : BIT(1));
++ ret = ov5640_set_autogain(sensor, auto_gain);
+ if (ret)
+ return ret;
+ }
+
+- if (!auto_gain && ctrls->gain->is_new) {
+- u16 gain = (u16)ctrls->gain->val;
+-
+- ret = ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN,
+- gain & 0x3ff);
+- }
++ if (!auto_gain && ctrls->gain->is_new)
++ ret = ov5640_set_gain(sensor, ctrls->gain->val);
+
+ return ret;
+ }
--- /dev/null
+From dc29a1c187eedc1d498cb567c44bbbc832b009cb Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:17 -0400
+Subject: media: ov5640: fix exposure regression
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+commit dc29a1c187eedc1d498cb567c44bbbc832b009cb upstream.
+
+Symptom was black image when capturing HD or 5Mp picture
+due to manual exposure set to 1 while it was intended to
+set autoexposure to "manual", fix this.
+
+Fixes: bf4a4b518c20 ("media: ov5640: Don't force the auto exposure state at start time").
+
+Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/i2c/ov5640.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -960,6 +960,12 @@ static int ov5640_load_regs(struct ov564
+ return ov5640_set_timings(sensor, mode);
+ }
+
++static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on)
++{
++ return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
++ BIT(0), on ? 0 : BIT(0));
++}
++
+ /* read exposure, in number of line periods */
+ static int ov5640_get_exposure(struct ov5640_dev *sensor)
+ {
+@@ -1604,7 +1610,7 @@ static int ov5640_set_mode_exposure_calc
+ */
+ static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
+ const struct ov5640_mode_info *mode,
+- s32 exposure)
++ bool auto_exp)
+ {
+ int ret;
+
+@@ -1621,7 +1627,8 @@ static int ov5640_set_mode_direct(struct
+ if (ret)
+ return ret;
+
+- return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure);
++ return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, auto_exp ?
++ V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL);
+ }
+
+ static int ov5640_set_mode(struct ov5640_dev *sensor)
+@@ -1629,7 +1636,7 @@ static int ov5640_set_mode(struct ov5640
+ const struct ov5640_mode_info *mode = sensor->current_mode;
+ const struct ov5640_mode_info *orig_mode = sensor->last_mode;
+ enum ov5640_downsize_mode dn_mode, orig_dn_mode;
+- s32 exposure;
++ bool auto_exp = sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
+ int ret;
+
+ dn_mode = mode->dn_mode;
+@@ -1640,8 +1647,7 @@ static int ov5640_set_mode(struct ov5640
+ if (ret)
+ return ret;
+
+- exposure = sensor->ctrls.auto_exp->val;
+- ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL);
++ ret = ov5640_set_autoexposure(sensor, false);
+ if (ret)
+ return ret;
+
+@@ -1657,7 +1663,7 @@ static int ov5640_set_mode(struct ov5640
+ * change inside subsampling or scaling
+ * download firmware directly
+ */
+- ret = ov5640_set_mode_direct(sensor, mode, exposure);
++ ret = ov5640_set_mode_direct(sensor, mode, auto_exp);
+ }
+
+ if (ret < 0)
--- /dev/null
+From bad1774ed41e98a43074e50e7d5ac9e1e848d99a Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Wed, 18 Jul 2018 06:06:23 -0400
+Subject: media: ov5640: Fix timings setup code
+
+From: Jacopo Mondi <jacopo@jmondi.org>
+
+commit bad1774ed41e98a43074e50e7d5ac9e1e848d99a upstream.
+
+As of: commit 476dec012f4c ("media: ov5640: Add horizontal and vertical
+totals") the timings parameters gets programmed separately from the
+static register values array.
+
+When changing capture mode, the vertical and horizontal totals gets
+inspected by the set_mode_exposure_calc() functions, and only later
+programmed with the new values. This means exposure, light banding
+filter and shutter gain are calculated using the previous timings, and
+are thus not correct.
+
+Fix this by programming timings right after the static register value
+table has been sent to the sensor in the ov5640_load_regs() function.
+
+Fixes: 476dec012f4c ("media: ov5640: Add horizontal and vertical totals")
+
+Tested-by: Steve Longerbeam <slongerbeam@gmail.com> # i.MX6q SabreSD, CSI-2
+Tested-by: Loic Poulain <loic.poulain@linaro.org> # Dragonboard-410c, CSI-2
+Signed-off-by: Samuel Bobrowicz <sam@elite-embedded.com>
+Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/i2c/ov5640.c | 50 ++++++++++++++++++---------------------------
+ 1 file changed, 21 insertions(+), 29 deletions(-)
+
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -910,6 +910,26 @@ static int ov5640_mod_reg(struct ov5640_
+ }
+
+ /* download ov5640 settings to sensor through i2c */
++static int ov5640_set_timings(struct ov5640_dev *sensor,
++ const struct ov5640_mode_info *mode)
++{
++ int ret;
++
++ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
++ if (ret < 0)
++ return ret;
++
++ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
++ if (ret < 0)
++ return ret;
++
++ ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
++ if (ret < 0)
++ return ret;
++
++ return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
++}
++
+ static int ov5640_load_regs(struct ov5640_dev *sensor,
+ const struct ov5640_mode_info *mode)
+ {
+@@ -937,7 +957,7 @@ static int ov5640_load_regs(struct ov564
+ usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
+ }
+
+- return ret;
++ return ov5640_set_timings(sensor, mode);
+ }
+
+ /* read exposure, in number of line periods */
+@@ -1400,30 +1420,6 @@ static int ov5640_set_virtual_channel(st
+ return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp);
+ }
+
+-static int ov5640_set_timings(struct ov5640_dev *sensor,
+- const struct ov5640_mode_info *mode)
+-{
+- int ret;
+-
+- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
+- if (ret < 0)
+- return ret;
+-
+- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
+- if (ret < 0)
+- return ret;
+-
+- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
+- if (ret < 0)
+- return ret;
+-
+- ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
+- if (ret < 0)
+- return ret;
+-
+- return 0;
+-}
+-
+ static const struct ov5640_mode_info *
+ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
+ int width, int height, bool nearest)
+@@ -1667,10 +1663,6 @@ static int ov5640_set_mode(struct ov5640
+ if (ret < 0)
+ return ret;
+
+- ret = ov5640_set_timings(sensor, mode);
+- if (ret < 0)
+- return ret;
+-
+ ret = ov5640_set_binning(sensor, dn_mode != SCALING);
+ if (ret < 0)
+ return ret;
--- /dev/null
+From c2c3f42df4dd9bb231d756bacb0c897f662c6d3c Mon Sep 17 00:00:00 2001
+From: Hugues Fruchet <hugues.fruchet@st.com>
+Date: Tue, 11 Sep 2018 09:48:19 -0400
+Subject: media: ov5640: fix wrong binning value in exposure calculation
+
+From: Hugues Fruchet <hugues.fruchet@st.com>
+
+commit c2c3f42df4dd9bb231d756bacb0c897f662c6d3c upstream.
+
+ov5640_set_mode_exposure_calc() is checking binning value but
+binning value read is buggy, fix this.
+Rename ov5640_binning_on() to ov5640_get_binning() as per other
+similar functions.
+
+Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/i2c/ov5640.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -1384,7 +1384,7 @@ static int ov5640_set_ae_target(struct o
+ return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1F, fast_low);
+ }
+
+-static int ov5640_binning_on(struct ov5640_dev *sensor)
++static int ov5640_get_binning(struct ov5640_dev *sensor)
+ {
+ u8 temp;
+ int ret;
+@@ -1392,8 +1392,8 @@ static int ov5640_binning_on(struct ov56
+ ret = ov5640_read_reg(sensor, OV5640_REG_TIMING_TC_REG21, &temp);
+ if (ret)
+ return ret;
+- temp &= 0xfe;
+- return temp ? 1 : 0;
++
++ return temp & BIT(0);
+ }
+
+ static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable)
+@@ -1479,7 +1479,7 @@ static int ov5640_set_mode_exposure_calc
+ if (ret < 0)
+ return ret;
+ prev_shutter = ret;
+- ret = ov5640_binning_on(sensor);
++ ret = ov5640_get_binning(sensor);
+ if (ret < 0)
+ return ret;
+ if (ret && mode->id != OV5640_MODE_720P_1280_720 &&
--- /dev/null
+From aa4bb8b8838ffcc776a79f49a4d7476b82405349 Mon Sep 17 00:00:00 2001
+From: Jacopo Mondi <jacopo@jmondi.org>
+Date: Fri, 6 Jul 2018 05:51:52 -0400
+Subject: media: ov5640: Re-work MIPI startup sequence
+
+From: Jacopo Mondi <jacopo@jmondi.org>
+
+commit aa4bb8b8838ffcc776a79f49a4d7476b82405349 upstream.
+
+Rework the MIPI interface startup sequence with the following changes:
+
+- Remove MIPI bus initialization from the initial settings blob
+- At set_power(1) time power up MIPI Tx/Rx and set data and clock lanes in
+ LP11 during 'sleep' and 'idle' with MIPI clock in non-continuous mode.
+- At s_stream time enable/disable the MIPI interface output.
+- Restore default settings at set_power(0) time.
+
+Before this commit the sensor MIPI interface was initialized with settings
+that require a start/stop sequence at power-up time in order to force lanes
+into LP11 state, as they were initialized in LP00 when in 'sleep mode',
+which is assumed to be the sensor manual definition for the D-PHY defined
+stop mode.
+
+The stream start/stop was performed by enabling disabling clock gating,
+and had the side effect to change the lanes sleep mode configuration when
+stream was stopped.
+
+Clock gating/ungating:
+- ret = ov5640_mod_reg(sensor, OV5640_REG_MIPI_CTRL00, BIT(5),
+- on ? 0 : BIT(5));
+- if (ret)
+
+Set lanes in LP11 when in 'sleep mode':
+- ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00,
+- on ? 0x00 : 0x70);
+
+This commit fixes an issue reported by Jagan Teki on i.MX6 platforms that
+prevents the host interface from powering up correctly:
+https://lkml.org/lkml/2018/6/1/38
+
+It also improves MIPI capture operations stability on my testing platform
+where MIPI capture often failed and returned all-purple frames.
+
+Fixes: f22996db44e2 ("media: ov5640: add support of DVP parallel interface")
+
+Tested-by: Steve Longerbeam <slongerbeam@gmail.com> (i.MX6q SabreSD, CSI-2)
+Tested-by: Loic Poulain <loic.poulain@linaro.org> (Dragonboard-410c, CSI-2)
+Reported-by: Jagan Teki <jagan@amarulasolutions.com>
+Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/i2c/ov5640.c | 99 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 79 insertions(+), 20 deletions(-)
+
+--- a/drivers/media/i2c/ov5640.c
++++ b/drivers/media/i2c/ov5640.c
+@@ -288,10 +288,10 @@ static const struct reg_value ov5640_ini
+ {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
+ {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
+ {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
+- {0x300e, 0x45, 0, 0}, {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
++ {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
+ {0x501f, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0},
+ {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
+- {0x4837, 0x0a, 0, 0}, {0x4800, 0x04, 0, 0}, {0x3824, 0x02, 0, 0},
++ {0x4837, 0x0a, 0, 0}, {0x3824, 0x02, 0, 0},
+ {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
+ {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
+ {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
+@@ -1104,12 +1104,25 @@ static int ov5640_set_stream_mipi(struct
+ {
+ int ret;
+
+- ret = ov5640_mod_reg(sensor, OV5640_REG_MIPI_CTRL00, BIT(5),
+- on ? 0 : BIT(5));
+- if (ret)
+- return ret;
+- ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00,
+- on ? 0x00 : 0x70);
++ /*
++ * Enable/disable the MIPI interface
++ *
++ * 0x300e = on ? 0x45 : 0x40
++ *
++ * FIXME: the sensor manual (version 2.03) reports
++ * [7:5] = 000 : 1 data lane mode
++ * [7:5] = 001 : 2 data lanes mode
++ * But this settings do not work, while the following ones
++ * have been validated for 2 data lanes mode.
++ *
++ * [7:5] = 010 : 2 data lanes mode
++ * [4] = 0 : Power up MIPI HS Tx
++ * [3] = 0 : Power up MIPI LS Rx
++ * [2] = 1/0 : MIPI interface enable/disable
++ * [1:0] = 01/00: FIXME: 'debug'
++ */
++ ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00,
++ on ? 0x45 : 0x40);
+ if (ret)
+ return ret;
+
+@@ -1790,23 +1803,69 @@ static int ov5640_set_power(struct ov564
+ if (ret)
+ goto power_off;
+
++ /* We're done here for DVP bus, while CSI-2 needs setup. */
++ if (sensor->ep.bus_type != V4L2_MBUS_CSI2)
++ return 0;
++
++ /*
++ * Power up MIPI HS Tx and LS Rx; 2 data lanes mode
++ *
++ * 0x300e = 0x40
++ * [7:5] = 010 : 2 data lanes mode (see FIXME note in
++ * "ov5640_set_stream_mipi()")
++ * [4] = 0 : Power up MIPI HS Tx
++ * [3] = 0 : Power up MIPI LS Rx
++ * [2] = 0 : MIPI interface disabled
++ */
++ ret = ov5640_write_reg(sensor,
++ OV5640_REG_IO_MIPI_CTRL00, 0x40);
++ if (ret)
++ goto power_off;
++
++ /*
++ * Gate clock and set LP11 in 'no packets mode' (idle)
++ *
++ * 0x4800 = 0x24
++ * [5] = 1 : Gate clock when 'no packets'
++ * [2] = 1 : MIPI bus in LP11 when 'no packets'
++ */
++ ret = ov5640_write_reg(sensor,
++ OV5640_REG_MIPI_CTRL00, 0x24);
++ if (ret)
++ goto power_off;
++
++ /*
++ * Set data lanes and clock in LP11 when 'sleeping'
++ *
++ * 0x3019 = 0x70
++ * [6] = 1 : MIPI data lane 2 in LP11 when 'sleeping'
++ * [5] = 1 : MIPI data lane 1 in LP11 when 'sleeping'
++ * [4] = 1 : MIPI clock lane in LP11 when 'sleeping'
++ */
++ ret = ov5640_write_reg(sensor,
++ OV5640_REG_PAD_OUTPUT00, 0x70);
++ if (ret)
++ goto power_off;
++
++ /* Give lanes some time to coax into LP11 state. */
++ usleep_range(500, 1000);
++
++ } else {
+ if (sensor->ep.bus_type == V4L2_MBUS_CSI2) {
+- /*
+- * start streaming briefly followed by stream off in
+- * order to coax the clock lane into LP-11 state.
+- */
+- ret = ov5640_set_stream_mipi(sensor, true);
+- if (ret)
+- goto power_off;
+- usleep_range(1000, 2000);
+- ret = ov5640_set_stream_mipi(sensor, false);
+- if (ret)
+- goto power_off;
++ /* Reset MIPI bus settings to their default values. */
++ ov5640_write_reg(sensor,
++ OV5640_REG_IO_MIPI_CTRL00, 0x58);
++ ov5640_write_reg(sensor,
++ OV5640_REG_MIPI_CTRL00, 0x04);
++ ov5640_write_reg(sensor,
++ OV5640_REG_PAD_OUTPUT00, 0x00);
+ }
+
+- return 0;
++ ov5640_set_power_off(sensor);
+ }
+
++ return 0;
++
+ power_off:
+ ov5640_set_power_off(sensor);
+ return ret;
--- /dev/null
+From 92aa39e9dc77481b90cbef25e547d66cab901496 Mon Sep 17 00:00:00 2001
+From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Date: Mon, 9 Jul 2018 13:47:30 -0700
+Subject: rcu: Make need_resched() respond to urgent RCU-QS needs
+
+From: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+
+commit 92aa39e9dc77481b90cbef25e547d66cab901496 upstream.
+
+The per-CPU rcu_dynticks.rcu_urgent_qs variable communicates an urgent
+need for an RCU quiescent state from the force-quiescent-state processing
+within the grace-period kthread to context switches and to cond_resched().
+Unfortunately, such urgent needs are not communicated to need_resched(),
+which is sometimes used to decide when to invoke cond_resched(), for
+but one example, within the KVM vcpu_run() function. As of v4.15, this
+can result in synchronize_sched() being delayed by up to ten seconds,
+which can be problematic, to say nothing of annoying.
+
+This commit therefore checks rcu_dynticks.rcu_urgent_qs from within
+rcu_check_callbacks(), which is invoked from the scheduling-clock
+interrupt handler. If the current task is not an idle task and is
+not executing in usermode, a context switch is forced, and either way,
+the rcu_dynticks.rcu_urgent_qs variable is set to false. If the current
+task is an idle task, then RCU's dyntick-idle code will detect the
+quiescent state, so no further action is required. Similarly, if the
+task is executing in usermode, other code in rcu_check_callbacks() and
+its called functions will report the corresponding quiescent state.
+
+Reported-by: Marius Hillenbrand <mhillenb@amazon.de>
+Reported-by: David Woodhouse <dwmw2@infradead.org>
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+[ paulmck: Backported to make patch apply cleanly on older versions. ]
+Tested-by: Marius Hillenbrand <mhillenb@amazon.de>
+Cc: <stable@vger.kernel.org> # 4.12.x - 4.19.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/rcu/tree.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -2662,6 +2662,15 @@ void rcu_check_callbacks(int user)
+ rcu_bh_qs();
+ }
+ rcu_preempt_check_callbacks();
++ /* The load-acquire pairs with the store-release setting to true. */
++ if (smp_load_acquire(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs))) {
++ /* Idle and userspace execution already are quiescent states. */
++ if (!rcu_is_cpu_rrupt_from_idle() && !user) {
++ set_tsk_need_resched(current);
++ set_preempt_need_resched();
++ }
++ __this_cpu_write(rcu_dynticks.rcu_urgent_qs, false);
++ }
+ if (rcu_pending())
+ invoke_rcu_core();
+
include-linux-pfn_t.h-force-to-be-parsed-as-an-unary-operator.patch
tty-wipe-buffer.patch
tty-wipe-buffer-if-not-echoing-data.patch
+gfs2-fix-iomap-buffer-head-reference-counting-bug.patch
+rcu-make-need_resched-respond-to-urgent-rcu-qs-needs.patch
+media-ov5640-re-work-mipi-startup-sequence.patch
+media-ov5640-fix-timings-setup-code.patch
+media-ov5640-fix-exposure-regression.patch
+media-ov5640-fix-auto-gain-exposure-when-changing-mode.patch
+media-ov5640-fix-wrong-binning-value-in-exposure-calculation.patch
+media-ov5640-fix-auto-controls-values-when-switching-to-manual-mode.patch