Browse Source

Update v5.10 patches

Changes:
 - cameras
   - Add VBLANK control support
   - Clean up OV5693 driver

Links:
 - kernel: https://github.com/linux-surface/kernel/commit/59c2df3ee0f48b02ddeba525563c3d7d440c2306
 - cameras: https://github.com/linux-surface/kernel/commit/74f01bb065f6221309954a6299990f4e887d4c3a
Maximilian Luz 4 years ago
parent
commit
f8fab978a4

+ 1 - 1
patches/5.10/0001-surface3-oemb.patch

@@ -1,4 +1,4 @@
-From f696bf9c577af759678b5296ac4b944dbb188c9e Mon Sep 17 00:00:00 2001
+From 22340c14d342f06a997d3b5a89af9346de0a7435 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Sun, 18 Oct 2020 16:42:44 +0900
 Subject: [PATCH] (surface3-oemb) add DMI matches for Surface 3 with broken DMI

+ 11 - 11
patches/5.10/0002-wifi.patch

@@ -1,4 +1,4 @@
-From 7142aae4519bf0728c574940e21cc7ab2c4a9e0f Mon Sep 17 00:00:00 2001
+From 7b93499e4902acda6934cfb5f959f5e94e7f8044 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Thu, 24 Sep 2020 18:02:06 +0900
 Subject: [PATCH] mwifiex: pcie: skip cancel_work_sync() on reset failure path
@@ -156,7 +156,7 @@ index 843d57eda820..5ed613d65709 100644
 -- 
 2.30.1
 
-From 8ee97a2be558e3ee3fbdcee4c3934ffc46df6a66 Mon Sep 17 00:00:00 2001
+From f5aa70330a4efb8cf636143ef9aa7e4904ad5127 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Mon, 28 Sep 2020 17:46:49 +0900
 Subject: [PATCH] mwifiex: pcie: add DMI-based quirk impl for Surface devices
@@ -364,7 +364,7 @@ index 000000000000..5326ae7e5671
 -- 
 2.30.1
 
-From 012378c78ce0aa9f54e6233fb03f15ab662b4bff Mon Sep 17 00:00:00 2001
+From 24b69b7365838ea8b0d5f82ad3f180fa090012ed Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Tue, 29 Sep 2020 17:25:22 +0900
 Subject: [PATCH] mwifiex: pcie: add reset_d3cold quirk for Surface gen4+
@@ -565,7 +565,7 @@ index 5326ae7e5671..8b9dcb5070d8 100644
 -- 
 2.30.1
 
-From e0e72a8bd4641edbd1f4f3c386f8573b3359a713 Mon Sep 17 00:00:00 2001
+From 874ad16a7ebce9ad8c0e35108b9f2b2f0acb6356 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Tue, 29 Sep 2020 17:32:22 +0900
 Subject: [PATCH] mwifiex: pcie: add reset_wsid quirk for Surface 3
@@ -744,7 +744,7 @@ index 8b9dcb5070d8..3ef7440418e3 100644
 -- 
 2.30.1
 
-From 7690864649999f7373e5800a04b4b053efb9232a Mon Sep 17 00:00:00 2001
+From fa1e5b2ce0632c6b9d95c7f6cd0b24791b5c9365 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Wed, 30 Sep 2020 18:08:24 +0900
 Subject: [PATCH] mwifiex: pcie: (OEMB) add quirk for Surface 3 with broken DMI
@@ -806,7 +806,7 @@ index f0a6fa0a7ae5..34dcd84f02a6 100644
 -- 
 2.30.1
 
-From 9db151b0136ea9d7d9170020e0c74d45fa17a824 Mon Sep 17 00:00:00 2001
+From 919301a63938bca88969a454f0abdc3db27f1ad3 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Thu, 24 Sep 2020 01:56:34 +0900
 Subject: [PATCH] mwifiex: pcie: use shutdown_sw()/reinit_sw() on
@@ -948,7 +948,7 @@ index 94561ddaf126..7b25335f1df3 100644
 -- 
 2.30.1
 
-From 3b864ce43d794995d3f3ea182ad5bff74be4a573 Mon Sep 17 00:00:00 2001
+From ebac0bf11dff3fa948916a759bae904fd960d05b Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Mon, 24 Aug 2020 17:11:35 +0900
 Subject: [PATCH] mwifiex: pcie: add enable_device_dump module parameter
@@ -997,7 +997,7 @@ index 7b25335f1df3..f7e0b86eb553 100644
 -- 
 2.30.1
 
-From 31ab9786797227365c34354d842efe0aaf6e62dd Mon Sep 17 00:00:00 2001
+From 142fdbb7737b947c70e064ba916d24e895d8cb2a Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Sun, 4 Oct 2020 00:11:49 +0900
 Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+
@@ -1152,7 +1152,7 @@ index 3ef7440418e3..a95ebac06e13 100644
 -- 
 2.30.1
 
-From 9c5b054473350dae8139e9b5c1ceea86b0560264 Mon Sep 17 00:00:00 2001
+From c0e83e93479fc6f348e1ec300412cc0971cc0427 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Sun, 4 Oct 2020 00:25:48 +0900
 Subject: [PATCH] mwifiex: add allow_ps_mode module parameter
@@ -1214,7 +1214,7 @@ index a6b9dc6700b1..943bc1e8ceae 100644
 -- 
 2.30.1
 
-From 635922ff9b7d620d892a0bf5757dbc852d432a2e Mon Sep 17 00:00:00 2001
+From 189cb0a5ea576d49e36b52ecf8316a2ceb5361c8 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Sun, 4 Oct 2020 00:38:48 +0900
 Subject: [PATCH] mwifiex: print message when changing ps_mode
@@ -1249,7 +1249,7 @@ index 943bc1e8ceae..a2eb8df8d385 100644
 -- 
 2.30.1
 
-From c53651a257e2f7af1daa566df43e7724ac75e04f Mon Sep 17 00:00:00 2001
+From d56d58a5b0ee3636946447789c88ce474b7b1006 Mon Sep 17 00:00:00 2001
 From: Tsuchiya Yuto <kitakar@gmail.com>
 Date: Sun, 4 Oct 2020 00:59:37 +0900
 Subject: [PATCH] mwifiex: disable ps_mode explicitly by default instead

+ 2 - 2
patches/5.10/0003-ipts.patch

@@ -1,4 +1,4 @@
-From b0ddc5d69f3ed78e7689a7d1e143567fbc16e55e Mon Sep 17 00:00:00 2001
+From da1f68432e7f4aaf42d07ac2a84d379cd1de4f4c Mon Sep 17 00:00:00 2001
 From: Dorian Stoll <dorian.stoll@tmsp.io>
 Date: Thu, 30 Jul 2020 13:21:53 +0200
 Subject: [PATCH] misc: mei: Add missing IPTS device IDs
@@ -36,7 +36,7 @@ index 1de9ef7a272b..e12484840f88 100644
 -- 
 2.30.1
 
-From 23313b15879627928315f6d97d1002264dc511f7 Mon Sep 17 00:00:00 2001
+From 8dacfcecc5c09994fbc750d50e063a5e2db72c65 Mon Sep 17 00:00:00 2001
 From: Dorian Stoll <dorian.stoll@tmsp.io>
 Date: Thu, 6 Aug 2020 11:20:41 +0200
 Subject: [PATCH] misc: Add support for Intel Precise Touch & Stylus

+ 1 - 1
patches/5.10/0004-surface-gpe.patch

@@ -1,4 +1,4 @@
-From ae725f58a769c0b98d72e612af0657fd21801ef4 Mon Sep 17 00:00:00 2001
+From e8a3fc1564b60e6a55a0ee1616731d584feeabaf Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sun, 16 Aug 2020 23:39:56 +0200
 Subject: [PATCH] platform/x86: Add Driver to set up lid GPEs on MS Surface

+ 2 - 2
patches/5.10/0005-surface-sam-over-hid.patch

@@ -1,4 +1,4 @@
-From 7fcb1bb56b0aeef64bb650f5cd7e40d56c1b8a06 Mon Sep 17 00:00:00 2001
+From b5f61c00e82a5552d5c48a538442c103d730b1fe Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sat, 25 Jul 2020 17:19:53 +0200
 Subject: [PATCH] i2c: acpi: Implement RawBytes read access
@@ -110,7 +110,7 @@ index 37c510d9347a..aed579942436 100644
 -- 
 2.30.1
 
-From 636027109cba56a411620d37a35fb9b56d6ec302 Mon Sep 17 00:00:00 2001
+From 3e4f517c369e8356fea37f130ff284343ca5cd15 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sun, 6 Sep 2020 04:01:19 +0200
 Subject: [PATCH] platform/x86: Add driver for Surface Book 1 dGPU switch

+ 2 - 2
patches/5.10/0006-surface-sam.patch

@@ -1,4 +1,4 @@
-From ba3917a0ce79087cc77219c47d2aa9fb9b7f0b9b Mon Sep 17 00:00:00 2001
+From 96a6523e58defc8462ccb29cff2b9d07b21c8ed5 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Mon, 17 Aug 2020 01:23:20 +0200
 Subject: [PATCH] Add file2alias support for Surface Aggregator Module devices
@@ -99,7 +99,7 @@ index 2417dd1dee33..a6c583362b92 100644
 -- 
 2.30.1
 
-From 18dfadbd32eae7eb88d5062564daf977c62d9c67 Mon Sep 17 00:00:00 2001
+From 23b5e1e8212af0785a88344444b01d0040d6ab7f Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Mon, 17 Aug 2020 01:44:30 +0200
 Subject: [PATCH] platform/x86: Add support for Surface System Aggregator

+ 3 - 3
patches/5.10/0007-surface-hotplug.patch

@@ -1,4 +1,4 @@
-From 97b4cb5fe354ae2aa11a51bf0add7434f65da636 Mon Sep 17 00:00:00 2001
+From c210052439b7cbd1ddc4d25703087ad25cc240c7 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Mon, 9 Nov 2020 14:23:00 +0100
 Subject: [PATCH] PCI: Run platform power transition on initial D0 entry
@@ -58,7 +58,7 @@ index 6427cbd0a5be..3200afed2604 100644
 -- 
 2.30.1
 
-From e99a49e3321f5f210825bd1cd35b04f9aff73a92 Mon Sep 17 00:00:00 2001
+From 924f1ae4e5c625f6fddb4bbed1b915d9ef6dd12a Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sat, 31 Oct 2020 20:46:33 +0100
 Subject: [PATCH] PCI: Add sysfs attribute for PCI device power state
@@ -131,7 +131,7 @@ index d15c881e2e7e..b15f754e6346 100644
 -- 
 2.30.1
 
-From 0702027c25539792b81325e843377c54010d8d56 Mon Sep 17 00:00:00 2001
+From 6e3cc9d0f7e5541b219240ba4344444e25a0a99d Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Mon, 14 Dec 2020 20:50:59 +0100
 Subject: [PATCH] platform/x86: Add Surface Hotplug driver

+ 1 - 1
patches/5.10/0008-surface-typecover.patch

@@ -1,4 +1,4 @@
-From e1b4a113984cf38f01c2a0e2bbf4e8192664ce0d Mon Sep 17 00:00:00 2001
+From 9929845c4ef162a6bc28f16e211a8b5781a39a59 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
 Date: Thu, 5 Nov 2020 13:09:45 +0100
 Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when

+ 1 - 1
patches/5.10/0009-surface-sensors.patch

@@ -1,4 +1,4 @@
-From 46132805b14e21b99d61fb2f35b459c638c87dca Mon Sep 17 00:00:00 2001
+From 1f0b9f668442306f8624e69a4066c81918e87ad1 Mon Sep 17 00:00:00 2001
 From: Max Leiter <maxwell.leiter@gmail.com>
 Date: Sat, 19 Dec 2020 17:50:55 -0800
 Subject: [PATCH] iio:light:apds9960 add detection for MSHW0184 ACPI device in

+ 4757 - 32
patches/5.10/0010-cameras.patch

@@ -1,4 +1,4 @@
-From 3b09d327318b99c630c758d32d28aff5ca65c072 Mon Sep 17 00:00:00 2001
+From 32471cc9c5d98f0d10dbea253304e0f96abb2916 Mon Sep 17 00:00:00 2001
 From: Sakari Ailus <sakari.ailus@linux.intel.com>
 Date: Mon, 12 Oct 2020 21:04:11 +0300
 Subject: [PATCH] ipu3-cio2: Use unsigned values where appropriate
@@ -316,7 +316,7 @@ index 146492383aa5..7650d7998a3f 100644
 -- 
 2.30.1
 
-From c6fc4d5d0b225173cfbe1df908c8950c3f40f0bc Mon Sep 17 00:00:00 2001
+From 34c2da7111d19237998a6420189f5896d0b7e037 Mon Sep 17 00:00:00 2001
 From: Sakari Ailus <sakari.ailus@linux.intel.com>
 Date: Mon, 12 Oct 2020 21:04:12 +0300
 Subject: [PATCH] ipu3-cio2: Remove explicit type from frame size checks
@@ -350,7 +350,7 @@ index 1fcd131482e0..b2679ff185fc 100644
 -- 
 2.30.1
 
-From 74f14515d35868f08cb32111ae06c33d0a7eda81 Mon Sep 17 00:00:00 2001
+From c0d5f91f3262dfcad057817b7cc92e27f4bc82b5 Mon Sep 17 00:00:00 2001
 From: Sakari Ailus <sakari.ailus@linux.intel.com>
 Date: Mon, 12 Oct 2020 21:04:13 +0300
 Subject: [PATCH] ipu3-cio2: Rename CIO2_IMAGE_MAX_LENGTH as
@@ -409,7 +409,7 @@ index 7650d7998a3f..ccf0b85ae36f 100644
 -- 
 2.30.1
 
-From 656111f0523d4ab97cac8437c1617a241bece72e Mon Sep 17 00:00:00 2001
+From dc6a77ee8a8ad188cc3bd63231b7759ce6e95503 Mon Sep 17 00:00:00 2001
 From: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx>
 Date: Tue, 13 Oct 2020 17:25:35 +0300
 Subject: [PATCH] ipu3-cio2: Check receved the size against payload size, not
@@ -463,7 +463,7 @@ index 51c4dd6a8f9a..c557d189200b 100644
 -- 
 2.30.1
 
-From 02ff48a15f0e0da02d088fc4c7ec959b97d6016d Mon Sep 17 00:00:00 2001
+From fbffeecd2e7454f14fae4c13b486dc136b49a750 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 10 Oct 2020 23:42:09 +0100
 Subject: [PATCH] software_node: Fix refcounts in
@@ -511,7 +511,7 @@ index 010828fc785b..615a0c93e116 100644
 -- 
 2.30.1
 
-From 012323f01e585cb17073d859cba7392a9119c613 Mon Sep 17 00:00:00 2001
+From 025f45ed28564cdef6c7fe699432e1ae1f20a487 Mon Sep 17 00:00:00 2001
 From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 Date: Wed, 30 Dec 2020 22:44:05 +0200
 Subject: [PATCH] media: ipu3-cio2: Add headers that ipu3-cio2.h is direct user
@@ -563,7 +563,7 @@ index ccf0b85ae36f..62187ab5ae43 100644
 -- 
 2.30.1
 
-From 02efb9f2e40c323cf51d9b3807e2dbea40f08d26 Mon Sep 17 00:00:00 2001
+From 17f9b714c6c43dd36f96013e97ed6d47230df117 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 24 Oct 2020 22:42:28 +0100
 Subject: [PATCH] device property: Return true in fwnode_device_is_available
@@ -608,7 +608,7 @@ index 4c43d30145c6..bc9c634df6df 100644
 -- 
 2.30.1
 
-From 41d95371ec70fb792fdf404e09c7bc422116741d Mon Sep 17 00:00:00 2001
+From 7e8095e7a5754ab247ef6d7e3d459fd7b0de7b7a Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 21 Nov 2020 22:06:38 +0000
 Subject: [PATCH] device property: Call fwnode_graph_get_endpoint_by_id() for
@@ -652,7 +652,7 @@ index bc9c634df6df..ddba75d90af2 100644
 -- 
 2.30.1
 
-From 077ca29de10ed13810d77e4b5283b2b71141b685 Mon Sep 17 00:00:00 2001
+From b80bff10119170d8dab3cda43a71624a18ec5ae8 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sun, 25 Oct 2020 22:49:08 +0000
 Subject: [PATCH] software_node: Enforce parent before child ordering of nodes
@@ -755,7 +755,7 @@ index 615a0c93e116..ade49173ff8d 100644
 -- 
 2.30.1
 
-From 9cfcb92a9d56040c58453f7ff517112103f96a96 Mon Sep 17 00:00:00 2001
+From 7670dadea357641b8b9e5ed804e18b412fe334fc Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Wed, 21 Oct 2020 22:25:03 +0100
 Subject: [PATCH] software_node: unregister software_nodes in reverse order
@@ -810,7 +810,7 @@ index ade49173ff8d..1f43c51b431e 100644
 -- 
 2.30.1
 
-From b07d850a68e50eaa31b6d51d3a235c6a3d027f7c Mon Sep 17 00:00:00 2001
+From c6b79e9a2a765592e11723d61a12e3c30f8c4650 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Tue, 22 Dec 2020 13:09:05 +0000
 Subject: [PATCH] device property: Define format macros for ports and endpoints
@@ -851,7 +851,7 @@ index 9506f8ec0974..72d36d46287d 100644
 -- 
 2.30.1
 
-From 048747fc7cf291e76bc88d36ce7e174dbe67c86d Mon Sep 17 00:00:00 2001
+From 56e57aa31cd20535fc3e3f685848da6b8ba7a469 Mon Sep 17 00:00:00 2001
 From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
 Date: Tue, 15 Sep 2020 15:47:46 +0100
 Subject: [PATCH] software_node: Add support for fwnode_graph*() family of
@@ -1019,7 +1019,7 @@ index 1f43c51b431e..2ff504aca0be 100644
 -- 
 2.30.1
 
-From e5a525987762827d42408d301651ddd7dee58a13 Mon Sep 17 00:00:00 2001
+From f70bc3eb837b1ad8c95150b96a9768d28d4848cd Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 10 Oct 2020 23:07:22 +0100
 Subject: [PATCH] lib/test_printf.c: Use helper function to unwind array of
@@ -1057,7 +1057,7 @@ index 7ac87f18a10f..7d60f24240a4 100644
 -- 
 2.30.1
 
-From 7db14aecb682f2821c02420dc3356f311591ff12 Mon Sep 17 00:00:00 2001
+From ecbb6f67417898624be3b3aded3aceb893025bfd Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 10 Oct 2020 23:11:36 +0100
 Subject: [PATCH] ipu3-cio2: Add T: entry to MAINTAINERS
@@ -1088,7 +1088,7 @@ index 281de213ef47..5a1c6e959aa8 100644
 -- 
 2.30.1
 
-From 5cd26f650205295b0162859db1855119daa50b30 Mon Sep 17 00:00:00 2001
+From 231bcccd03410528c1c5971204f344ff289f9c29 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 10 Oct 2020 22:47:21 +0100
 Subject: [PATCH] ipu3-cio2: Rename ipu3-cio2.c
@@ -1123,7 +1123,7 @@ rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
 -- 
 2.30.1
 
-From 173774fc8274db26b11e9518948d7dc2fbd2a286 Mon Sep 17 00:00:00 2001
+From c2a6d9ea77c97c0810deca4efa0e20632a0d1580 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Wed, 21 Oct 2020 21:53:05 +0100
 Subject: [PATCH] media: v4l2-core: v4l2-async: Check sd->fwnode->secondary in
@@ -1164,7 +1164,7 @@ index e3ab003a6c85..9dd896d085ec 100644
 -- 
 2.30.1
 
-From 54866c066f7eb157f72611427af44096d6ed388e Mon Sep 17 00:00:00 2001
+From e2a35c5d387c7e8341afd52bf41a42c3cc9a8615 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sun, 15 Nov 2020 08:15:34 +0000
 Subject: [PATCH] ACPI / bus: Add acpi_dev_get_next_match_dev() and helper
@@ -1273,7 +1273,7 @@ index 6d1879bf9440..02a716a0af5d 100644
 -- 
 2.30.1
 
-From 3a8c20986a3b297f30269464f628439b23b0ed7e Mon Sep 17 00:00:00 2001
+From 356810b8ffa42d22eeaf19b694e6d225b74580f1 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 19 Dec 2020 23:55:04 +0000
 Subject: [PATCH] media: v4l2-fwnode: Include v4l2_fwnode_bus_type
@@ -1350,7 +1350,7 @@ index ed0840f3d5df..6ca337c28b3c 100644
 -- 
 2.30.1
 
-From d3d67a61296add16ecd644971ec0ac25a6ba1022 Mon Sep 17 00:00:00 2001
+From f9f3ecfc891d1671fd45426e3194d774887da80b Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Wed, 21 Oct 2020 21:53:44 +0100
 Subject: [PATCH] ipu3-cio2: Add cio2-bridge to ipu3-cio2 driver
@@ -1948,7 +1948,7 @@ index 62187ab5ae43..dc3e343a37fb 100644
 -- 
 2.30.1
 
-From 66c0bc2e1a548ce3d1f6e7b3356c29c702c137ac Mon Sep 17 00:00:00 2001
+From b138b0799d6b023a33cdd69b2ff6ddcf2b7f189c Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Wed, 2 Dec 2020 12:38:10 +0000
 Subject: [PATCH] acpi: utils: move acpi_lpss_dep() to utils
@@ -2050,7 +2050,7 @@ index ddca1550cce6..78b38775f18b 100644
 -- 
 2.30.1
 
-From 19bdf96ef080ad643ced9c7810156857d30d21ee Mon Sep 17 00:00:00 2001
+From 84b2fdfd7ba36a7525ff97cd4d4080471cdcba06 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Thu, 26 Nov 2020 21:12:41 +0000
 Subject: [PATCH] acpi: utils: Add function to fetch dependent acpi_devices
@@ -2136,7 +2136,7 @@ index 02a716a0af5d..33deb22294f2 100644
 -- 
 2.30.1
 
-From ec31436438fd065f39e144fbd8652d292bf07f05 Mon Sep 17 00:00:00 2001
+From cad6e20a6ceacb6f120f20fddd9cadc0355802d7 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Mon, 16 Nov 2020 21:38:49 +0000
 Subject: [PATCH] i2c: i2c-core-base: Use format macro in i2c_dev_set_name()
@@ -2204,7 +2204,7 @@ index 56622658b215..65acae61dc5c 100644
 -- 
 2.30.1
 
-From 8b7807ff6bca711e87af1b6e5b11f0495f36c6ef Mon Sep 17 00:00:00 2001
+From f2760c77484f8bfd90fbae8a1dc6ae2107cb2c6e Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Wed, 2 Dec 2020 16:41:42 +0000
 Subject: [PATCH] i2c: i2c-core-acpi: Add i2c_acpi_dev_name()
@@ -2262,7 +2262,7 @@ index 65acae61dc5c..b82aac05b17f 100644
 -- 
 2.30.1
 
-From df44db561d8855d0255503e20268c08c01c3c5ee Mon Sep 17 00:00:00 2001
+From 869d5dd9d5828a4728ea0204e09f7ff80d56c82e Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Mon, 16 Nov 2020 00:16:56 +0000
 Subject: [PATCH] gpio: gpiolib-acpi: Export acpi_get_gpiod()
@@ -2326,7 +2326,7 @@ index 5b1dc1ad4fb3..47ae139e8781 100644
 -- 
 2.30.1
 
-From 89313343dd227867456401fe62cf944058e47534 Mon Sep 17 00:00:00 2001
+From 8780e6b11b5d4b1a493e89cf9d4ecb4334845227 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sat, 12 Dec 2020 23:56:59 +0000
 Subject: [PATCH] mfd: Remove tps68470 MFD driver
@@ -2359,10 +2359,10 @@ index 56bbcb2ce61b..e27d8ef3a32c 100644
  	  This config adds ACPI operation region support for TI TPS68470 PMIC.
  	  TPS68470 device is an advanced power management unit that powers
 diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
-index f20ac3d69424..751b7a733bff 100644
+index 14751c7ccd1f..442b2cc5e2f0 100644
 --- a/drivers/gpio/Kconfig
 +++ b/drivers/gpio/Kconfig
-@@ -1320,7 +1320,6 @@ config GPIO_TPS65912
+@@ -1321,7 +1321,6 @@ config GPIO_TPS65912
  
  config GPIO_TPS68470
  	bool "TPS68470 GPIO"
@@ -2517,7 +2517,7 @@ index 4a4df4ffd18c..000000000000
 -- 
 2.30.1
 
-From c8f82a485887fff61743f6612812d7b66e9ebe6d Mon Sep 17 00:00:00 2001
+From 75ad8c2f266e8802fa95c3d59bf702af6019b41f Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Fri, 15 Jan 2021 12:37:31 +0000
 Subject: [PATCH] platform: x86: Add intel_skl_int3472 driver
@@ -3486,7 +3486,7 @@ index 000000000000..3fe27ec0caff
 -- 
 2.30.1
 
-From 0564d5c307f712e18fffa6816cb0853c1e6a1224 Mon Sep 17 00:00:00 2001
+From 12d4fe655786e70db9868cd005c28e6d5361d6b1 Mon Sep 17 00:00:00 2001
 From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
 Date: Fri, 11 Dec 2020 21:17:35 +0100
 Subject: [PATCH] PCI: ACPI: Fix up ACPI companion lookup for device 0 on the
@@ -3556,7 +3556,7 @@ index 745a4e0c4994..87e45a800919 100644
 -- 
 2.30.1
 
-From 8fea36502f89e914226e1159c094b83d9ec3d226 Mon Sep 17 00:00:00 2001
+From bd5f7d894a6956b9f9abf41ee22d1fcb485d5f5d Mon Sep 17 00:00:00 2001
 From: Jake Day <jake@ninebysix.com>
 Date: Fri, 25 Sep 2020 10:24:53 -0400
 Subject: [PATCH] media: i2c: Add support for the OV5693 image sensor
@@ -6913,7 +6913,7 @@ index 000000000000..9a508e1f3624
 -- 
 2.30.1
 
-From 73624b0f335955c8cc097bdbdffe954bc5466c75 Mon Sep 17 00:00:00 2001
+From d830bae59cb11cbc0f97dde540b14b931ed1c0b3 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sun, 17 Jan 2021 19:08:18 +0000
 Subject: [PATCH] media: i2c: Add reset pin toggling to ov5693
@@ -6954,7 +6954,7 @@ index 32485e4ed42b..f9ced52ad37a 100644
 -- 
 2.30.1
 
-From f3982cd7cf3ec7bca291cfc821c4d5dedd94d7ac Mon Sep 17 00:00:00 2001
+From 7fb8c70cd22feb2ba77480f58d09ea44aff1c767 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sun, 17 Jan 2021 21:39:15 +0000
 Subject: [PATCH] media: i2c: Fix misnamed variable in power_down() for ov5693
@@ -6983,3 +6983,4728 @@ index f9ced52ad37a..9fd44a3d1d85 100644
 -- 
 2.30.1
 
+From 2e833ff778b536f2f6a401c979662122bf9e1277 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabian=20W=C3=BCthrich?= <me@fabwu.ch>
+Date: Fri, 22 Jan 2021 20:58:13 +0100
+Subject: [PATCH] cio2-bridge: Parse sensor orientation and rotation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The sensor orientation is read from the _PLC ACPI buffer and converted
+to a v4l2 format.
+
+See https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
+page 351 for a definition of the Panel property.
+
+The sensor rotation is read from the SSDB ACPI buffer and converted into
+degrees.
+
+Signed-off-by: Fabian Wüthrich <me@fabwu.ch>
+Patchset: cameras
+---
+ drivers/media/pci/intel/ipu3/cio2-bridge.c | 45 ++++++++++++++++++++--
+ drivers/media/pci/intel/ipu3/cio2-bridge.h |  3 ++
+ 2 files changed, 44 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
+index 143f3c0f445e..806d4e5fc177 100644
+--- a/drivers/media/pci/intel/ipu3/cio2-bridge.c
++++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
+@@ -29,6 +29,7 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = {
+ static const struct cio2_property_names prop_names = {
+ 	.clock_frequency = "clock-frequency",
+ 	.rotation = "rotation",
++	.orientation = "orientation",
+ 	.bus_type = "bus-type",
+ 	.data_lanes = "data-lanes",
+ 	.remote_endpoint = "remote-endpoint",
+@@ -72,11 +73,36 @@ static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
+ 	return ret;
+ }
+ 
++static u32 cio2_bridge_parse_rotation(u8 rotation)
++{
++	if (rotation == 1)
++		return 180;
++	return 0;
++}
++
++static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(u8 panel)
++{
++	switch (panel) {
++	case 4:
++		return V4L2_FWNODE_ORIENTATION_FRONT;
++	case 5:
++		return V4L2_FWNODE_ORIENTATION_BACK;
++	default:
++		return V4L2_FWNODE_ORIENTATION_EXTERNAL;
++	}
++}
++
+ static void cio2_bridge_create_fwnode_properties(
+ 	struct cio2_sensor *sensor,
+ 	struct cio2_bridge *bridge,
+ 	const struct cio2_sensor_config *cfg)
+ {
++	u32 rotation;
++	enum v4l2_fwnode_orientation orientation;
++
++	rotation = cio2_bridge_parse_rotation(sensor->ssdb.degree);
++	orientation = cio2_bridge_parse_orientation(sensor->pld->panel);
++
+ 	sensor->prop_names = prop_names;
+ 
+ 	sensor->local_ref[0].node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT];
+@@ -85,9 +111,12 @@ static void cio2_bridge_create_fwnode_properties(
+ 	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(
+ 					sensor->prop_names.clock_frequency,
+ 					sensor->ssdb.mclkspeed);
+-	sensor->dev_properties[1] = PROPERTY_ENTRY_U8(
++	sensor->dev_properties[1] = PROPERTY_ENTRY_U32(
+ 					sensor->prop_names.rotation,
+-					sensor->ssdb.degree);
++					rotation);
++	sensor->dev_properties[2] = PROPERTY_ENTRY_U32(
++					sensor->prop_names.orientation,
++					orientation);
+ 
+ 	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
+ 					sensor->prop_names.bus_type,
+@@ -159,6 +188,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
+ 	for (i = 0; i < bridge->n_sensors; i++) {
+ 		sensor = &bridge->sensors[i];
+ 		software_node_unregister_nodes(sensor->swnodes);
++		ACPI_FREE(sensor->pld);
+ 		acpi_dev_put(sensor->adev);
+ 	}
+ }
+@@ -170,6 +200,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
+ 	struct fwnode_handle *fwnode;
+ 	struct cio2_sensor *sensor;
+ 	struct acpi_device *adev;
++	acpi_status status;
+ 	int ret;
+ 
+ 	for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
+@@ -193,11 +224,15 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
+ 		if (ret)
+ 			goto err_put_adev;
+ 
++		status = acpi_get_physical_device_location(adev->handle, &sensor->pld);
++		if (ACPI_FAILURE(status))
++			goto err_put_adev;
++
+ 		if (sensor->ssdb.lanes > CIO2_MAX_LANES) {
+ 			dev_err(&adev->dev,
+ 				"Number of lanes in SSDB is invalid\n");
+ 			ret = -EINVAL;
+-			goto err_put_adev;
++			goto err_free_pld;
+ 		}
+ 
+ 		cio2_bridge_create_fwnode_properties(sensor, bridge, cfg);
+@@ -205,7 +240,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
+ 
+ 		ret = software_node_register_nodes(sensor->swnodes);
+ 		if (ret)
+-			goto err_put_adev;
++			goto err_free_pld;
+ 
+ 		fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
+ 		if (!fwnode) {
+@@ -225,6 +260,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
+ 
+ err_free_swnodes:
+ 	software_node_unregister_nodes(sensor->swnodes);
++err_free_pld:
++	ACPI_FREE(sensor->pld);
+ err_put_adev:
+ 	acpi_dev_put(sensor->adev);
+ err_out:
+diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
+index dd0ffcafa489..924d99d20328 100644
+--- a/drivers/media/pci/intel/ipu3/cio2-bridge.h
++++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
+@@ -80,6 +80,7 @@ struct cio2_sensor_ssdb {
+ struct cio2_property_names {
+ 	char clock_frequency[16];
+ 	char rotation[9];
++	char orientation[12];
+ 	char bus_type[9];
+ 	char data_lanes[11];
+ 	char remote_endpoint[16];
+@@ -106,6 +107,8 @@ struct cio2_sensor {
+ 	struct cio2_node_names node_names;
+ 
+ 	struct cio2_sensor_ssdb ssdb;
++	struct acpi_pld_info *pld;
++
+ 	struct cio2_property_names prop_names;
+ 	struct property_entry ep_properties[5];
+ 	struct property_entry dev_properties[3];
+-- 
+2.30.1
+
+From e767277317119f90d0841ac9c3bdce118a461e6a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabian=20W=C3=BCthrich?= <me@fabwu.ch>
+Date: Fri, 22 Jan 2021 21:23:47 +0100
+Subject: [PATCH] ov5693: Add orientation and rotation controls
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+    Parse orientation and rotation from fwnodes and initialize the
+    respective controls.
+
+Signed-off-by: Fabian Wüthrich <me@fabwu.ch>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 9fd44a3d1d85..1a85800df7ed 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -31,6 +31,7 @@
+ #include <linux/i2c.h>
+ #include <linux/moduleparam.h>
+ #include <media/v4l2-device.h>
++#include <media/v4l2-fwnode.h>
+ #include <linux/io.h>
+ #include <linux/acpi.h>
+ #include <linux/regulator/consumer.h>
+@@ -1608,6 +1609,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	const struct v4l2_ctrl_ops *ops = &ov5693_ctrl_ops;
++	struct v4l2_fwnode_device_properties props;
+ 	struct v4l2_ctrl *ctrl;
+ 	unsigned int i;
+ 	int ret;
+@@ -1663,6 +1665,15 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	if (ov5693->hblank)
+ 		ov5693->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
++	/* set properties from fwnode (e.g. rotation, orientation) */
++	ret = v4l2_fwnode_device_parse(&client->dev, &props);
++	if (ret)
++		return ret;
++
++	ret = v4l2_ctrl_new_fwnode_properties(&ov5693->ctrl_handler, ops, &props);
++	if (ret)
++		return ret;
++
+ 	/* Use same lock for controls as for everything else. */
+ 	ov5693->ctrl_handler.lock = &ov5693->input_lock;
+ 	ov5693->sd.ctrl_handler = &ov5693->ctrl_handler;
+-- 
+2.30.1
+
+From 0823b3b1fd4f8ce2897681f9e9493a8e3c3ae952 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 23 Jan 2021 00:28:32 +0000
+Subject: [PATCH] platform: x86: Stylistic updates for intel-skl-int3472
+
+This commit makes a bunch of stylistic updates, minor changes and other
+stuff that's part of the improvements pass I'm doing to the code after
+taking into account feedback from the list.
+
+It also alters the ACPI buffer fetching code to be more generalisable so
+I can re-use it to fetch the clock frequency.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ .../platform/x86/intel_skl_int3472_common.c   |  37 ++++---
+ .../platform/x86/intel_skl_int3472_common.h   |   7 +-
+ .../platform/x86/intel_skl_int3472_discrete.c | 101 +++++++++---------
+ .../platform/x86/intel_skl_int3472_tps68470.c |  16 +--
+ 4 files changed, 89 insertions(+), 72 deletions(-)
+
+diff --git a/drivers/platform/x86/intel_skl_int3472_common.c b/drivers/platform/x86/intel_skl_int3472_common.c
+index 08cb9d3c06aa..549d211979e1 100644
+--- a/drivers/platform/x86/intel_skl_int3472_common.c
++++ b/drivers/platform/x86/intel_skl_int3472_common.c
+@@ -7,41 +7,52 @@
+ 
+ #include "intel_skl_int3472_common.h"
+ 
+-int skl_int3472_get_cldb_buffer(struct acpi_device *adev,
+-				struct int3472_cldb *cldb)
++union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
++					       char *id)
+ {
+ 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ 	acpi_handle handle = adev->handle;
+ 	union acpi_object *obj;
+ 	acpi_status status;
+-	int ret = 0;
+ 
+-	status = acpi_evaluate_object(handle, "CLDB", NULL, &buffer);
++	status = acpi_evaluate_object(handle, id, NULL, &buffer);
+ 	if (ACPI_FAILURE(status))
+-		return -ENODEV;
++		return ERR_PTR(-ENODEV);
+ 
+ 	obj = buffer.pointer;
+ 	if (!obj) {
+-		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
+-		return -ENODEV;
++		dev_err(&adev->dev, "ACPI device has no %s object\n", id);
++		return ERR_PTR(-ENODEV);
+ 	}
+ 
+ 	if (obj->type != ACPI_TYPE_BUFFER) {
+-		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
+-		ret = -EINVAL;
+-		goto out_free_buff;
++		dev_err(&adev->dev, "%s object is not an ACPI buffer\n", id);
++		kfree(obj);
++		return ERR_PTR(-EINVAL);
+ 	}
+ 
++	return obj;
++}
++
++int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb)
++{
++	union acpi_object *obj;
++	int ret = 0;
++
++	obj = skl_int3472_get_acpi_buffer(adev, "CLDB");
++	if (IS_ERR(obj))
++		return PTR_ERR(obj);
++
+ 	if (obj->buffer.length > sizeof(*cldb)) {
+ 		dev_err(&adev->dev, "The CLDB buffer is too large\n");
+ 		ret = -EINVAL;
+-		goto out_free_buff;
++		goto out_free_obj;
+ 	}
+ 
+ 	memcpy(cldb, obj->buffer.pointer, obj->buffer.length);
+ 
+-out_free_buff:
+-	kfree(buffer.pointer);
++out_free_obj:
++	kfree(obj);
+ 	return ret;
+ }
+ 
+diff --git a/drivers/platform/x86/intel_skl_int3472_common.h b/drivers/platform/x86/intel_skl_int3472_common.h
+index 4ac6bb2b223f..e1083bb67dc6 100644
+--- a/drivers/platform/x86/intel_skl_int3472_common.h
++++ b/drivers/platform/x86/intel_skl_int3472_common.h
+@@ -29,7 +29,7 @@
+ 
+ #define INT3472_GPIO_FUNCTION_REMAP(_PIN, _FUNCTION)		\
+ 	(const struct int3472_gpio_function_remap) {		\
+-		.documented = _PIN,					\
++		.documented = _PIN,				\
+ 		.actual = _FUNCTION				\
+ 	}
+ 
+@@ -95,5 +95,6 @@ struct int3472_sensor_config {
+ int skl_int3472_discrete_probe(struct platform_device *pdev);
+ int skl_int3472_discrete_remove(struct platform_device *pdev);
+ int skl_int3472_tps68470_probe(struct i2c_client *client);
+-int skl_int3472_get_cldb_buffer(struct acpi_device *adev,
+-				struct int3472_cldb *cldb);
++union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
++					       char *id);
++int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb);
+diff --git a/drivers/platform/x86/intel_skl_int3472_discrete.c b/drivers/platform/x86/intel_skl_int3472_discrete.c
+index ea7e57f3e3f0..42ae8396eb64 100644
+--- a/drivers/platform/x86/intel_skl_int3472_discrete.c
++++ b/drivers/platform/x86/intel_skl_int3472_discrete.c
+@@ -12,12 +12,12 @@
+ 
+ #include "intel_skl_int3472_common.h"
+ 
+-/* 79234640-9e10-4fea-a5c1b5aa8b19756f */
++/* 79234640-9e10-4fea-a5c1-b5aa8b19756f */
+ static const guid_t int3472_gpio_guid =
+ 	GUID_INIT(0x79234640, 0x9e10, 0x4fea,
+ 		  0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
+ 
+-/* 822ace8f-2814-4174-a56b5f029fe079ee */
++/* 822ace8f-2814-4174-a56b-5f029fe079ee */
+ static const guid_t cio2_sensor_module_guid =
+ 	GUID_INIT(0x822ace8f, 0x2814, 0x4174,
+ 		  0xa5, 0x6b, 0x5f, 0x02, 0x9f, 0xe0, 0x79, 0xee);
+@@ -94,7 +94,7 @@ static const struct clk_ops skl_int3472_clock_ops = {
+ };
+ 
+ static struct int3472_sensor_config *
+-int3472_get_sensor_module_config(struct int3472_device *int3472)
++skl_int3472_get_sensor_module_config(struct int3472_device *int3472)
+ {
+ 	unsigned int i = ARRAY_SIZE(int3472_sensor_configs);
+ 	struct int3472_sensor_config *ret;
+@@ -131,9 +131,9 @@ int3472_get_sensor_module_config(struct int3472_device *int3472)
+ 	return ret;
+ }
+ 
+-static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
+-				      struct acpi_resource *ares,
+-				      char *func, u32 polarity)
++static int skl_int3472_map_gpio_to_sensor(struct int3472_device *int3472,
++					  struct acpi_resource *ares,
++					  char *func, u32 polarity)
+ {
+ 	char *path = ares->data.gpio.resource_source.string_ptr;
+ 	struct int3472_sensor_config *sensor_config;
+@@ -143,7 +143,7 @@ static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
+ 	acpi_status status;
+ 	int ret;
+ 
+-	sensor_config = int3472_get_sensor_module_config(int3472);
++	sensor_config = skl_int3472_get_sensor_module_config(int3472);
+ 	if (!IS_ERR(sensor_config) && sensor_config->function_maps) {
+ 		unsigned int i = 0;
+ 
+@@ -186,17 +186,19 @@ static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
+ 	return 0;
+ }
+ 
+-static int int3472_register_clock(struct int3472_device *int3472,
+-				  struct acpi_resource *ares)
++static int skl_int3472_register_clock(struct int3472_device *int3472,
++				      struct acpi_resource *ares)
+ {
+ 	char *path = ares->data.gpio.resource_source.string_ptr;
+-	struct clk_init_data init = { };
++	struct clk_init_data init = { 0 };
+ 	int ret = 0;
+ 
+-	init.name = kasprintf(GFP_KERNEL, "%s-clk", acpi_dev_name(int3472->adev));
++	init.name = kasprintf(GFP_KERNEL, "%s-clk",
++			      acpi_dev_name(int3472->adev));
+ 	init.ops = &skl_int3472_clock_ops;
+ 
+-	int3472->clock.gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
++	int3472->clock.gpio = acpi_get_gpiod(path,
++					     ares->data.gpio.pin_table[0]);
+ 	if (IS_ERR(int3472->clock.gpio)) {
+ 		ret = PTR_ERR(int3472->clock.gpio);
+ 		goto out_free_init_name;
+@@ -226,17 +228,16 @@ static int int3472_register_clock(struct int3472_device *int3472,
+ 	return ret;
+ }
+ 
+-static int int3472_register_regulator(struct int3472_device *int3472,
+-				      struct acpi_resource *ares)
++static int skl_int3472_register_regulator(struct int3472_device *int3472,
++					  struct acpi_resource *ares)
+ {
+ 	char *path = ares->data.gpio.resource_source.string_ptr;
+ 	struct int3472_sensor_config *sensor_config;
+ 	struct regulator_init_data init_data = { };
+-	struct int3472_gpio_regulator *regulator;
+ 	struct regulator_config cfg = { };
+ 	int ret;
+ 
+-	sensor_config = int3472_get_sensor_module_config(int3472);
++	sensor_config = skl_int3472_get_sensor_module_config(int3472);
+ 	if (IS_ERR_OR_NULL(sensor_config)) {
+ 		dev_err(&int3472->pdev->dev, "No sensor module config\n");
+ 		return PTR_ERR(sensor_config);
+@@ -252,26 +253,29 @@ static int int3472_register_regulator(struct int3472_device *int3472,
+ 	init_data.num_consumer_supplies = 1;
+ 	init_data.consumer_supplies = &sensor_config->supply_map;
+ 
+-	snprintf(int3472->regulator.regulator_name, GPIO_REGULATOR_NAME_LENGTH,
+-		 "int3472-discrete-regulator");
+-	snprintf(int3472->regulator.supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
+-		 "supply-0");
++	snprintf(int3472->regulator.regulator_name,
++		 GPIO_REGULATOR_NAME_LENGTH, "int3472-discrete-regulator");
++	snprintf(int3472->regulator.supply_name,
++		 GPIO_REGULATOR_SUPPLY_NAME_LENGTH, "supply-0");
+ 
+-	int3472->regulator.rdesc = INT3472_REGULATOR(int3472->regulator.regulator_name,
+-						     int3472->regulator.supply_name,
+-						     &int3472_gpio_regulator_ops);
++	int3472->regulator.rdesc = INT3472_REGULATOR(
++						int3472->regulator.regulator_name,
++						int3472->regulator.supply_name,
++						&int3472_gpio_regulator_ops);
+ 
+-	int3472->regulator.gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
++	int3472->regulator.gpio = acpi_get_gpiod(path,
++						 ares->data.gpio.pin_table[0]);
+ 	if (IS_ERR(int3472->regulator.gpio)) {
+-		ret = PTR_ERR(int3472->regulator.gpio);
+-		goto err_free_regulator;
++		dev_err(&int3472->pdev->dev, "Failed to get GPIO line\n");
++		return PTR_ERR(int3472->regulator.gpio);
+ 	}
+ 
+ 	cfg.dev = &int3472->adev->dev;
+ 	cfg.init_data = &init_data;
+ 	cfg.ena_gpiod = int3472->regulator.gpio;
+ 
+-	int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc, &cfg);
++	int3472->regulator.rdev = regulator_register(&int3472->regulator.rdesc,
++						     &cfg);
+ 	if (IS_ERR(int3472->regulator.rdev)) {
+ 		ret = PTR_ERR(int3472->regulator.rdev);
+ 		goto err_free_gpio;
+@@ -280,15 +284,13 @@ static int int3472_register_regulator(struct int3472_device *int3472,
+ 	return 0;
+ 
+ err_free_gpio:
+-	gpiod_put(regulator->gpio);
+-err_free_regulator:
+-	kfree(regulator);
++	gpiod_put(int3472->regulator.gpio);
+ 
+ 	return ret;
+ }
+ 
+ /**
+- * int3472_handle_gpio_resources: maps PMIC resources to consuming sensor
++ * skl_int3472_handle_gpio_resources: maps PMIC resources to consuming sensor
+  * @ares: A pointer to a &struct acpi_resource
+  * @data: A pointer to a &struct int3472_device
+  *
+@@ -305,8 +307,9 @@ static int int3472_register_regulator(struct int3472_device *int3472,
+  *
+  * There are some known platform specific quirks where that does not quite
+  * hold up; for example where a pin with type 0x01 (Power down) is mapped to
+- * a sensor pin that performs a reset function. These will be handled by the
+- * mapping sub-functions.
++ * a sensor pin that performs a reset function or entries in _CRS and _DSM that
++ * do not actually correspond to a physical connection. These will be handled by
++ * the mapping sub-functions.
+  *
+  * GPIOs will either be mapped directly to the sensor device or else used
+  * to create clocks and regulators via the usual frameworks.
+@@ -317,8 +320,8 @@ static int int3472_register_regulator(struct int3472_device *int3472,
+  * * -ENODEV	- If the resource has no corresponding _DSM entry
+  * * -Other	- Errors propagated from one of the sub-functions.
+  */
+-static int int3472_handle_gpio_resources(struct acpi_resource *ares,
+-					 void *data)
++static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
++					     void *data)
+ {
+ 	struct int3472_device *int3472 = data;
+ 	union acpi_object *obj;
+@@ -345,30 +348,30 @@ static int int3472_handle_gpio_resources(struct acpi_resource *ares,
+ 
+ 	switch (obj->integer.value & 0xff) {
+ 	case INT3472_GPIO_TYPE_RESET:
+-		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset",
+-						 GPIO_ACTIVE_LOW);
++		ret = skl_int3472_map_gpio_to_sensor(int3472, ares, "reset",
++						     GPIO_ACTIVE_LOW);
+ 		if (ret)
+ 			dev_err(&int3472->pdev->dev,
+ 				"Failed to map reset pin to sensor\n");
+ 
+ 		break;
+ 	case INT3472_GPIO_TYPE_POWERDOWN:
+-		ret = int3472_map_gpio_to_sensor(int3472, ares, "powerdown",
+-						 GPIO_ACTIVE_LOW);
++		ret = skl_int3472_map_gpio_to_sensor(int3472, ares, "powerdown",
++						     GPIO_ACTIVE_LOW);
+ 		if (ret)
+ 			dev_err(&int3472->pdev->dev,
+ 				"Failed to map powerdown pin to sensor\n");
+ 
+ 		break;
+ 	case INT3472_GPIO_TYPE_CLK_ENABLE:
+-		ret = int3472_register_clock(int3472, ares);
++		ret = skl_int3472_register_clock(int3472, ares);
+ 		if (ret)
+ 			dev_err(&int3472->pdev->dev,
+ 				"Failed to map clock to sensor\n");
+ 
+ 		break;
+ 	case INT3472_GPIO_TYPE_POWER_ENABLE:
+-		ret = int3472_register_regulator(int3472, ares);
++		ret = skl_int3472_register_regulator(int3472, ares);
+ 		if (ret) {
+ 			dev_err(&int3472->pdev->dev,
+ 				"Failed to map regulator to sensor\n");
+@@ -376,8 +379,9 @@ static int int3472_handle_gpio_resources(struct acpi_resource *ares,
+ 
+ 		break;
+ 	case INT3472_GPIO_TYPE_PRIVACY_LED:
+-		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led",
+-						 GPIO_ACTIVE_HIGH);
++		ret = skl_int3472_map_gpio_to_sensor(int3472, ares,
++						     "indicator-led",
++						     GPIO_ACTIVE_HIGH);
+ 		if (ret)
+ 			dev_err(&int3472->pdev->dev,
+ 				"Failed to map indicator led to sensor\n");
+@@ -396,7 +400,7 @@ static int int3472_handle_gpio_resources(struct acpi_resource *ares,
+ 	return ret;
+ }
+ 
+-static int int3472_parse_crs(struct int3472_device *int3472)
++static int skl_int3472_parse_crs(struct int3472_device *int3472)
+ {
+ 	struct list_head resource_list;
+ 	int ret = 0;
+@@ -404,7 +408,8 @@ static int int3472_parse_crs(struct int3472_device *int3472)
+ 	INIT_LIST_HEAD(&resource_list);
+ 
+ 	ret = acpi_dev_get_resources(int3472->adev, &resource_list,
+-				     int3472_handle_gpio_resources, int3472);
++				     skl_int3472_handle_gpio_resources,
++				     int3472);
+ 
+ 	if (!ret) {
+ 		gpiod_add_lookup_table(&int3472->gpios);
+@@ -423,7 +428,7 @@ int skl_int3472_discrete_probe(struct platform_device *pdev)
+ 	struct int3472_cldb cldb;
+ 	int ret = 0;
+ 
+-	ret = skl_int3472_get_cldb_buffer(adev, &cldb);
++	ret = skl_int3472_fill_cldb(adev, &cldb);
+ 	if (ret || cldb.control_logic_type != 1)
+ 		return -EINVAL;
+ 
+@@ -444,10 +449,10 @@ int skl_int3472_discrete_probe(struct platform_device *pdev)
+ 		ret = -ENODEV;
+ 		goto err_free_int3472;
+ 	}
+-	int3472->sensor_name = i2c_acpi_dev_name(int3472->sensor);
++	int3472->sensor_name = kasprintf(GFP_KERNEL, I2C_DEV_NAME_FORMAT, acpi_dev_name(int3472->sensor));
+ 	int3472->gpios.dev_id = int3472->sensor_name;
+ 
+-	ret = int3472_parse_crs(int3472);
++	ret = skl_int3472_parse_crs(int3472);
+ 	if (ret) {
+ 		skl_int3472_discrete_remove(pdev);
+ 		goto err_return_ret;
+diff --git a/drivers/platform/x86/intel_skl_int3472_tps68470.c b/drivers/platform/x86/intel_skl_int3472_tps68470.c
+index 3fe27ec0caff..40629291b339 100644
+--- a/drivers/platform/x86/intel_skl_int3472_tps68470.c
++++ b/drivers/platform/x86/intel_skl_int3472_tps68470.c
+@@ -87,20 +87,20 @@ int skl_int3472_tps68470_probe(struct i2c_client *client)
+ 
+ 	/*
+ 	 * Check CLDB buffer against the PMIC's adev. If present, then we check
+-	 * the value of control_logic_type field and follow one of the following
+-	 * scenarios:
++	 * the value of control_logic_type field and follow one of the
++	 * following scenarios:
+ 	 *
+-	 *	1. No CLDB - likely ACPI tables designed for ChromeOS. We create
+-	 *	platform devices for the GPIOs and OpRegion drivers.
++	 *	1. No CLDB - likely ACPI tables designed for ChromeOS. We
++	 *	create platform devices for the GPIOs and OpRegion drivers.
+ 	 *
+-	 *	2. CLDB, with control_logic_type = 2 - probably ACPI tables made
+-	 *	for Windows 2-in-1 platforms. Register pdevs for GPIO, Clock and
+-	 *	Regulator drivers to bind to.
++	 *	2. CLDB, with control_logic_type = 2 - probably ACPI tables
++	 *	made for Windows 2-in-1 platforms. Register pdevs for GPIO,
++	 *	Clock and Regulator drivers to bind to.
+ 	 *
+ 	 *	3. Any other value in control_logic_type, we should never have
+ 	 *	gotten to this point; crash and burn.
+ 	 */
+-	ret = skl_int3472_get_cldb_buffer(adev, &cldb);
++	ret = skl_int3472_fill_cldb(adev, &cldb);
+ 	if (!ret && cldb.control_logic_type != 2)
+ 		return -EINVAL;
+ 
+-- 
+2.30.1
+
+From e3cde392d3facfbf24232e866f644db25c012f5b Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 23 Jan 2021 00:30:15 +0000
+Subject: [PATCH] platform: x86: Add recalc_rate opp to int3472-discrete clock
+
+This commit adds the recalc_rate opp to the clock registered by
+int3472-discrete so that sensor drivers calling clk_get_rate() will get a
+valid value returned.
+
+The value is simply read from the sensor's SSDB buffer, and so we pass
+CLK_GET_RATE_NOCACHE
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ .../platform/x86/intel_skl_int3472_common.h   |  6 +++
+ .../platform/x86/intel_skl_int3472_discrete.c | 37 ++++++++++++++++++-
+ 2 files changed, 41 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/platform/x86/intel_skl_int3472_common.h b/drivers/platform/x86/intel_skl_int3472_common.h
+index e1083bb67dc6..860c849b7769 100644
+--- a/drivers/platform/x86/intel_skl_int3472_common.h
++++ b/drivers/platform/x86/intel_skl_int3472_common.h
+@@ -17,6 +17,8 @@
+ #define GPIO_REGULATOR_NAME_LENGTH				27
+ #define GPIO_REGULATOR_SUPPLY_NAME_LENGTH			9
+ 
++#define CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET			86
++
+ #define INT3472_REGULATOR(_NAME, _SUPPLY, _OPS)			\
+ 	(const struct regulator_desc) {				\
+ 		.name = _NAME,					\
+@@ -36,6 +38,9 @@
+ #define to_int3472_clk(hw)					\
+ 	container_of(hw, struct int3472_gpio_clock, clk_hw)
+ 
++#define to_int3472_device(clk)					\
++	container_of(clk, struct int3472_device, clock)
++
+ struct int3472_cldb {
+ 	u8 version;
+ 	/*
+@@ -62,6 +67,7 @@ struct int3472_gpio_regulator {
+ struct int3472_gpio_clock {
+ 	struct clk *clk;
+ 	struct clk_hw clk_hw;
++	struct clk_lookup *cl;
+ 	struct gpio_desc *gpio;
+ };
+ 
+diff --git a/drivers/platform/x86/intel_skl_int3472_discrete.c b/drivers/platform/x86/intel_skl_int3472_discrete.c
+index 42ae8396eb64..98eb1ec3399e 100644
+--- a/drivers/platform/x86/intel_skl_int3472_discrete.c
++++ b/drivers/platform/x86/intel_skl_int3472_discrete.c
+@@ -86,11 +86,41 @@ static void skl_int3472_clk_unprepare(struct clk_hw *hw)
+ 	/* Likewise, nothing to do here... */
+ }
+ 
++static unsigned int skl_int3472_get_clk_frequency(struct int3472_device *int3472)
++{
++	union acpi_object *obj;
++	unsigned int ret = 0;
++
++	obj = skl_int3472_get_acpi_buffer(int3472->sensor, "SSDB");
++	if (IS_ERR(obj))
++		goto out_free_buff; /* report rate as 0 on error */
++
++	if (obj->buffer.length < CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET + sizeof(u32)) {
++		dev_err(&int3472->pdev->dev, "The buffer is too small\n");
++		goto out_free_buff;
++	}
++
++	ret = *(u32*)(obj->buffer.pointer + CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET);
++
++out_free_buff:
++	kfree(obj);
++	return ret;
++}
++
++static unsigned long skl_int3472_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
++{
++	struct int3472_gpio_clock *clk = to_int3472_clk(hw);
++	struct int3472_device *int3472 = to_int3472_device(clk);
++
++	return skl_int3472_get_clk_frequency(int3472);
++}
++
+ static const struct clk_ops skl_int3472_clock_ops = {
+ 	.prepare = skl_int3472_clk_prepare,
+ 	.unprepare = skl_int3472_clk_unprepare,
+ 	.enable = skl_int3472_clk_enable,
+ 	.disable = skl_int3472_clk_disable,
++	.recalc_rate = skl_int3472_clk_recalc_rate,
+ };
+ 
+ static struct int3472_sensor_config *
+@@ -196,6 +226,7 @@ static int skl_int3472_register_clock(struct int3472_device *int3472,
+ 	init.name = kasprintf(GFP_KERNEL, "%s-clk",
+ 			      acpi_dev_name(int3472->adev));
+ 	init.ops = &skl_int3472_clock_ops;
++	init.flags |= CLK_GET_RATE_NOCACHE;
+ 
+ 	int3472->clock.gpio = acpi_get_gpiod(path,
+ 					     ares->data.gpio.pin_table[0]);
+@@ -212,8 +243,9 @@ static int skl_int3472_register_clock(struct int3472_device *int3472,
+ 		goto err_put_gpio;
+ 	}
+ 
+-	ret = clk_register_clkdev(int3472->clock.clk, "xvclk", int3472->sensor_name);
+-	if (ret)
++	int3472->clock.cl = clkdev_create(int3472->clock.clk, "xvclk",
++					  int3472->sensor_name);
++	if (IS_ERR_OR_NULL(int3472->clock.cl))
+ 		goto err_unregister_clk;
+ 
+ 	goto out_free_init_name;
+@@ -483,6 +515,7 @@ int skl_int3472_discrete_remove(struct platform_device *pdev)
+ 	if (!IS_ERR_OR_NULL(int3472->clock.clk)) {
+ 		gpiod_put(int3472->clock.gpio);
+ 		clk_unregister(int3472->clock.clk);
++		clkdev_drop(int3472->clock.cl);
+ 	}
+ 
+ 	acpi_dev_put(int3472->sensor);
+-- 
+2.30.1
+
+From 1d1a0b5731f637597568a2e8cce2758e14b3c2ca Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabian=20W=C3=BCthrich?= <me@fabwu.ch>
+Date: Sun, 24 Jan 2021 11:07:42 +0100
+Subject: [PATCH] cio2-bridge: Use macros and add warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use macros for the _PLD panel as defined in the ACPI spec 6.3 and emit
+a warning if we see an unknown value.
+
+Signed-off-by: Fabian Wüthrich <me@fabwu.ch>
+Patchset: cameras
+---
+ drivers/media/pci/intel/ipu3/cio2-bridge.c | 33 ++++++++++++++++------
+ drivers/media/pci/intel/ipu3/cio2-bridge.h | 13 +++++++++
+ 2 files changed, 37 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
+index 806d4e5fc177..3c373ad1c0b0 100644
+--- a/drivers/media/pci/intel/ipu3/cio2-bridge.c
++++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
+@@ -73,21 +73,36 @@ static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
+ 	return ret;
+ }
+ 
+-static u32 cio2_bridge_parse_rotation(u8 rotation)
++static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor)
+ {
+-	if (rotation == 1)
++	switch (sensor->ssdb.degree) {
++	case CIO2_SENSOR_ROTATION_NORMAL:
++		return 0;
++	case CIO2_SENSOR_ROTATION_INVERTED:
+ 		return 180;
+-	return 0;
++	default:
++		dev_warn(&sensor->adev->dev,
++			 "Unknown rotation %d. Assume 0 degree rotation\n",
++			 sensor->ssdb.degree);
++		return 0;
++	}
+ }
+ 
+-static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(u8 panel)
++static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(struct cio2_sensor *sensor)
+ {
+-	switch (panel) {
+-	case 4:
++	switch (sensor->pld->panel) {
++	case CIO2_PLD_PANEL_FRONT:
+ 		return V4L2_FWNODE_ORIENTATION_FRONT;
+-	case 5:
++	case CIO2_PLD_PANEL_BACK:
+ 		return V4L2_FWNODE_ORIENTATION_BACK;
++	case CIO2_PLD_PANEL_TOP:
++	case CIO2_PLD_PANEL_LEFT:
++	case CIO2_PLD_PANEL_RIGHT:
++	case CIO2_PLD_PANEL_UNKNOWN:
++		return V4L2_FWNODE_ORIENTATION_EXTERNAL;
+ 	default:
++		dev_warn(&sensor->adev->dev, "Unknown _PLD panel value %d\n",
++			 sensor->pld->panel);
+ 		return V4L2_FWNODE_ORIENTATION_EXTERNAL;
+ 	}
+ }
+@@ -100,8 +115,8 @@ static void cio2_bridge_create_fwnode_properties(
+ 	u32 rotation;
+ 	enum v4l2_fwnode_orientation orientation;
+ 
+-	rotation = cio2_bridge_parse_rotation(sensor->ssdb.degree);
+-	orientation = cio2_bridge_parse_orientation(sensor->pld->panel);
++	rotation = cio2_bridge_parse_rotation(sensor);
++	orientation = cio2_bridge_parse_orientation(sensor);
+ 
+ 	sensor->prop_names = prop_names;
+ 
+diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
+index 924d99d20328..e1e388cc9f45 100644
+--- a/drivers/media/pci/intel/ipu3/cio2-bridge.h
++++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
+@@ -12,6 +12,19 @@
+ #define CIO2_MAX_LANES				4
+ #define MAX_NUM_LINK_FREQS			3
+ 
++/* Values are estimated guesses as we don't have a spec */
++#define CIO2_SENSOR_ROTATION_NORMAL		0
++#define CIO2_SENSOR_ROTATION_INVERTED		1
++
++/* Panel position defined in _PLD section of ACPI Specification 6.3 */
++#define CIO2_PLD_PANEL_TOP			0
++#define CIO2_PLD_PANEL_BOTTOM			1
++#define CIO2_PLD_PANEL_LEFT			2
++#define CIO2_PLD_PANEL_RIGHT			3
++#define CIO2_PLD_PANEL_FRONT			4
++#define CIO2_PLD_PANEL_BACK			5
++#define CIO2_PLD_PANEL_UNKNOWN			6
++
+ #define CIO2_SENSOR_CONFIG(_HID, _NR, ...)	\
+ 	(const struct cio2_sensor_config) {	\
+ 		.hid = _HID,			\
+-- 
+2.30.1
+
+From b070306c3889044cba1bd72c52cc818b642003a5 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 8 Feb 2021 21:44:38 +0000
+Subject: [PATCH] media: i2c: Tidy up ov5693_init_controls()
+
+The ov5693 driver initialises a bunch of v4l2 controls and throws away
+the pointers. This seems weird, let's not do that.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 46 ++++++++++++++++++++++----------------
+ drivers/media/i2c/ov5693.h | 12 +++++++++-
+ 2 files changed, 38 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 1a85800df7ed..a9747ab783d7 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1610,7 +1610,6 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	const struct v4l2_ctrl_ops *ops = &ov5693_ctrl_ops;
+ 	struct v4l2_fwnode_device_properties props;
+-	struct v4l2_ctrl *ctrl;
+ 	unsigned int i;
+ 	int ret;
+ 	int hblank;
+@@ -1628,15 +1627,17 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 				     NULL);
+ 
+ 	/* link freq */
+-	ctrl = v4l2_ctrl_new_int_menu(&ov5693->ctrl_handler, NULL,
+-				      V4L2_CID_LINK_FREQ,
+-				      0, 0, link_freq_menu_items);
+-	if (ctrl)
+-		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++	ov5693->ctrls.link_freq = v4l2_ctrl_new_int_menu(&ov5693->ctrl_handler,
++							 NULL, V4L2_CID_LINK_FREQ,
++							 0, 0, link_freq_menu_items);
++	if (ov5693->ctrls.link_freq)
++		ov5693->ctrls.link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
+ 	/* pixel rate */
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE,
+-			  0, OV5693_PIXEL_RATE, 1, OV5693_PIXEL_RATE);
++	ov5693->ctrls.pixel_rate = v4l2_ctrl_new_std(&ov5693->ctrl_handler, NULL,
++						     V4L2_CID_PIXEL_RATE, 0,
++						     OV5693_PIXEL_RATE, 1,
++						     OV5693_PIXEL_RATE);
+ 
+ 	if (ov5693->ctrl_handler.error) {
+ 		ov5693_remove(client);
+@@ -1645,25 +1646,32 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ 	/* Exposure */
+ 
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_EXPOSURE, 16, 1048575, 16,
+-			  512);
++	ov5693->ctrls.exposure = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						   V4L2_CID_EXPOSURE, 16,
++						   1048575, 16, 512);
+ 
+ 	/* Gain */
+ 
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_ANALOGUE_GAIN, 1, 1023, 1, 128);
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_DIGITAL_GAIN, 1, 3999, 1, 1000);
++	ov5693->ctrls.analogue_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler,
++							ops, V4L2_CID_ANALOGUE_GAIN,
++							1, 1023, 1, 128);
++	ov5693->ctrls.digital_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						       V4L2_CID_DIGITAL_GAIN, 1,
++						       3999, 1, 1000);
+ 
+ 	/* Flip */
+ 
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+-	v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
++	ov5693->ctrls.hflip = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						V4L2_CID_HFLIP, 0, 1, 1, 0);
++	ov5693->ctrls.vflip = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						V4L2_CID_VFLIP, 0, 1, 1, 0);
+ 
+ 	hblank = OV5693_PPL_DEFAULT - ov5693->mode->width;
+-	ov5693->hblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+-					   V4L2_CID_HBLANK, hblank, hblank,
+-					   1, hblank);
+-	if (ov5693->hblank)
+-		ov5693->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
++	ov5693->ctrls.hblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						 V4L2_CID_HBLANK, hblank, hblank,
++						 1, hblank);
++	if (ov5693->ctrls.hblank)
++		ov5693->ctrls.hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
+ 	/* set properties from fwnode (e.g. rotation, orientation) */
+ 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 9a508e1f3624..26819cf3f4d2 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -270,7 +270,17 @@ struct ov5693_device {
+ 
+ 	bool has_vcm;
+ 
+-	struct v4l2_ctrl *hblank;
++	struct ov5693_v4l2_ctrls {
++		struct v4l2_ctrl *link_freq;
++		struct v4l2_ctrl *pixel_rate;
++		struct v4l2_ctrl *exposure;
++		struct v4l2_ctrl *analogue_gain;
++		struct v4l2_ctrl *digital_gain;
++		struct v4l2_ctrl *hflip;
++		struct v4l2_ctrl *vflip;
++		struct v4l2_ctrl *hblank;
++	} ctrls;
++
+ };
+ 
+ enum ov5693_tok_type {
+-- 
+2.30.1
+
+From 77dd02990795cbc0eeb69d29a234ecef694612b9 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 8 Feb 2021 21:46:49 +0000
+Subject: [PATCH] media: i2c: Remove OV5693_PPL_DEFAULT
+
+No need for this macro, the PPL setting is against the mode structs.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index a9747ab783d7..7fb368eec327 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -105,8 +105,6 @@ MODULE_PARM_DESC(up_delay,
+ #define OV5693_PIXEL_ARRAY_WIDTH	2592U
+ #define OV5693_PIXEL_ARRAY_HEIGHT	1944U
+ 
+-#define	OV5693_PPL_DEFAULT		2800
+-
+ static int vcm_ad_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
+ {
+ 	int err;
+@@ -1666,7 +1664,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	ov5693->ctrls.vflip = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+ 						V4L2_CID_VFLIP, 0, 1, 1, 0);
+ 
+-	hblank = OV5693_PPL_DEFAULT - ov5693->mode->width;
++	hblank = ov5693->mode->pixels_per_line - ov5693->mode->width;
+ 	ov5693->ctrls.hblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+ 						 V4L2_CID_HBLANK, hblank, hblank,
+ 						 1, hblank);
+-- 
+2.30.1
+
+From 9c063797defadfe3580002f79d5503c4a697d1a4 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 8 Feb 2021 22:53:02 +0000
+Subject: [PATCH] media: i2c: Add vblank control to ov5693 driver
+
+The latest libcamera requires a V4L2_CID_VBLANK control in each sensor
+driver; add a skeleton one to the ov5693 to fulfill the requirement.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 12 ++++++++++++
+ drivers/media/i2c/ov5693.h |  3 +++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 7fb368eec327..1950d7ac2d54 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -946,6 +946,10 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 		return ov5693_flip_horz_configure(dev, !!ctrl->val);
+ 	case V4L2_CID_VFLIP:
+ 		return ov5693_flip_vert_configure(dev, !!ctrl->val);
++	case V4L2_CID_VBLANK:
++		ret = ov5693_write_reg(client, OV5693_16BIT, OV5693_TIMING_VTS_H,
++				       dev->mode->height + ctrl->val);
++		break;
+ 	default:
+ 		ret = -EINVAL;
+ 	}
+@@ -1611,6 +1615,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	unsigned int i;
+ 	int ret;
+ 	int hblank;
++	int vblank_max, vblank_min, vblank_def;
+ 
+ 	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler,
+ 				     ARRAY_SIZE(ov5693_controls));
+@@ -1671,6 +1676,13 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	if (ov5693->ctrls.hblank)
+ 		ov5693->ctrls.hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ 
++	vblank_max = OV5693_TIMING_MAX_VTS - ov5693->mode->height;
++	vblank_def = ov5693->mode->lines_per_frame - ov5693->mode->height;
++	vblank_min = ov5693->mode->lines_per_frame - ov5693->mode->height;
++	ov5693->ctrls.vblank = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
++						 V4L2_CID_VBLANK, vblank_min,
++						 vblank_max, 1, vblank_def);
++
+ 	/* set properties from fwnode (e.g. rotation, orientation) */
+ 	ret = v4l2_fwnode_device_parse(&client->dev, &props);
+ 	if (ret)
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 26819cf3f4d2..9d7eed97963b 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -131,6 +131,8 @@
+ /*High 8-bit, and low 8-bit HTS address is 0x380f*/
+ #define OV5693_TIMING_VTS_L			0x380f
+ 
++#define OV5693_TIMING_MAX_VTS			0xffff
++
+ #define OV5693_MWB_RED_GAIN_H			0x3400
+ #define OV5693_MWB_GREEN_GAIN_H			0x3402
+ #define OV5693_MWB_BLUE_GAIN_H			0x3404
+@@ -279,6 +281,7 @@ struct ov5693_device {
+ 		struct v4l2_ctrl *hflip;
+ 		struct v4l2_ctrl *vflip;
+ 		struct v4l2_ctrl *hblank;
++		struct v4l2_ctrl *vblank;
+ 	} ctrls;
+ 
+ };
+-- 
+2.30.1
+
+From b32056993cea983468fc25d3e64e06e37f4c40a6 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 00:36:32 +0000
+Subject: [PATCH] media: i2c: update exposure control for ov5693
+
+The exposure control for ov5693 currently is in units of 1/16th of a line,
+but I think the framework expects it in units of lines. Set the control to
+work in lines and simply apply the multiplication when configuring the chip
+registers instead.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 1950d7ac2d54..cea767230aa9 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -801,6 +801,12 @@ static int ov5693_exposure_configure(struct ov5693_device *sensor, u32 exposure)
+ {
+ 	int ret;
+ 
++	/*
++	 * The control for exposure seems to be in units of lines, but the chip
++	 * datasheet specifies exposure is in units of 1/16th of a line.
++	 */
++	exposure = exposure * 16;
++
+ 	ov5693_get_exposure(sensor);
+ 	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_HH_REG, OV5693_EXPOSURE_CTRL_HH(exposure));
+@@ -910,6 +916,16 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 	struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
+ 	int ret = 0;
+ 
++	/* If VBLANK is altered we need to update exposure to compensate */
++	if (ctrl->id == V4L2_CID_VBLANK) {
++		int exposure_max;
++		exposure_max = dev->mode->lines_per_frame - 8;
++		__v4l2_ctrl_modify_range(dev->ctrls.exposure, dev->ctrls.exposure->minimum,
++					 exposure_max, dev->ctrls.exposure->step,
++					 dev->ctrls.exposure->val < exposure_max ?
++					 dev->ctrls.exposure->val : exposure_max);
++	}
++
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+@@ -1616,6 +1632,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	int ret;
+ 	int hblank;
+ 	int vblank_max, vblank_min, vblank_def;
++	int exposure_max;
+ 
+ 	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler,
+ 				     ARRAY_SIZE(ov5693_controls));
+@@ -1648,10 +1665,10 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	}
+ 
+ 	/* Exposure */
+-
++	exposure_max = ov5693->mode->lines_per_frame - 8;
+ 	ov5693->ctrls.exposure = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+-						   V4L2_CID_EXPOSURE, 16,
+-						   1048575, 16, 512);
++						   V4L2_CID_EXPOSURE, 1,
++						   exposure_max, 1, 123);
+ 
+ 	/* Gain */
+ 
+-- 
+2.30.1
+
+From 6233e6bbe8f499ba8b4c31f9df53daa1d221d303 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 00:39:42 +0000
+Subject: [PATCH] media: i2c: Fix incorrect bit-setting
+
+The bitmask macros to set the exposure for the ov5693 are not quite right.
+Update them so that they're setting the correct bits in the registers.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index cea767230aa9..f681dbfcec56 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -63,11 +63,11 @@ MODULE_PARM_DESC(up_delay,
+ /* Exposure/gain */
+ 
+ #define OV5693_EXPOSURE_CTRL_HH_REG		0x3500
+-#define OV5693_EXPOSURE_CTRL_HH(v)		(((v) & GENMASK(18, 16)) >> 16)
++#define OV5693_EXPOSURE_CTRL_HH(v)		(((v) & GENMASK(14, 12)) >> 12)
+ #define OV5693_EXPOSURE_CTRL_H_REG		0x3501
+-#define OV5693_EXPOSURE_CTRL_H(v)		(((v) & GENMASK(15, 8)) >> 8)
++#define OV5693_EXPOSURE_CTRL_H(v)		(((v) & GENMASK(11, 4)) >> 4)
+ #define OV5693_EXPOSURE_CTRL_L_REG		0x3502
+-#define OV5693_EXPOSURE_CTRL_L(v)		((v) & GENMASK(7, 0))
++#define OV5693_EXPOSURE_CTRL_L(v)		(((v) & GENMASK(3, 0)) << 4)
+ #define OV5693_EXPOSURE_GAIN_MANUAL_REG		0x3509
+ 
+ #define OV5693_GAIN_CTRL_H_REG			0x3504
+-- 
+2.30.1
+
+From c8f37984c1cddea585f2acf6c71b878a92d451d4 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 16:25:48 +0000
+Subject: [PATCH] media: i2c: Don't set stream on during mode config
+
+Currently the register lists for the ov5693 include setting stream on.
+That register shouldn't be set until the control is called, so remove
+this setting from all of the modes.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 16 ----------------
+ 1 file changed, 16 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 9d7eed97963b..965208078c2b 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -581,7 +581,6 @@ static struct ov5693_reg const ov5693_654x496[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -626,7 +625,6 @@ static struct ov5693_reg const ov5693_1296x976[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ 
+ };
+@@ -656,7 +654,6 @@ static struct ov5693_reg const ov5693_336x256[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -683,7 +680,6 @@ static struct ov5693_reg const ov5693_368x304[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -715,7 +711,6 @@ static struct ov5693_reg const ov5693_192x160[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -742,7 +737,6 @@ static struct ov5693_reg const ov5693_736x496[] = {
+ 	{OV5693_8BIT, 0x3820, 0x04},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -771,7 +765,6 @@ static struct ov5693_reg const ov5693_736x496[] = {
+ 	{OV5693_8BIT, 0x3820, 0x01},
+ 	{OV5693_8BIT, 0x3821, 0x1f},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ */
+@@ -802,7 +795,6 @@ static struct ov5693_reg const ov5693_976x556[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -841,7 +833,6 @@ static struct ov5693_reg const ov5693_1296x736[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -868,7 +859,6 @@ static struct ov5693_reg const ov5693_1636p_30fps[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -904,7 +894,6 @@ static struct ov5693_reg const ov5693_1616x1216_30fps[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},	/*MIRROR control*/
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -935,7 +924,6 @@ static struct ov5693_reg const ov5693_1940x1096[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -1029,7 +1017,6 @@ static struct ov5693_reg const ov5693_2592x1944_30fps[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -1073,7 +1060,6 @@ static struct ov5693_reg const ov5693_1424x1168_30fps[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ #endif
+@@ -1114,7 +1100,6 @@ static struct ov5693_reg const ov5693_736x496_30fps[] = {
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+ 	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+@@ -1141,7 +1126,6 @@ static struct ov5693_reg const ov5693_2576x1936_30fps[] = {
+ 	{OV5693_8BIT, 0x3820, 0x00},
+ 	{OV5693_8BIT, 0x3821, 0x1e},
+ 	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x0100, 0x01},
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+-- 
+2.30.1
+
+From 0249d4e96dc77cedc82269d535ccb68a0ce3fc40 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 16:35:24 +0000
+Subject: [PATCH] media: i2c: Update gain control for ov5693
+
+The gain control of the ov5693 driver is setting the wrong bits and
+defining an invalid maximum value; change (and use) the bitshifting
+macros and update the control's ranges.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index f681dbfcec56..51eb3b05d121 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -71,9 +71,9 @@ MODULE_PARM_DESC(up_delay,
+ #define OV5693_EXPOSURE_GAIN_MANUAL_REG		0x3509
+ 
+ #define OV5693_GAIN_CTRL_H_REG			0x3504
+-#define OV5693_GAIN_CTRL_H(v)			(((v) & GENMASK(9, 8)) >> 8)
++#define OV5693_GAIN_CTRL_H(v)			((v >> 4) & GENMASK(2, 0))
+ #define OV5693_GAIN_CTRL_L_REG			0x3505
+-#define OV5693_GAIN_CTRL_L(v)			((v) & GENMASK(7, 0))
++#define OV5693_GAIN_CTRL_L(v)			((v << 4) & GENMASK(7, 4))
+ 
+ #define OV5693_FORMAT1_REG			0x3820
+ #define OV5693_FORMAT1_FLIP_VERT_ISP_EN		BIT(2)
+@@ -889,9 +889,13 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ {
+ 	int ret;
+ 
+-	/* Analog gain */
++	/*
++	 * As with exposure, the lowest 4 bits are fractional bits. Setting
++	 * those is not supported, so we have a tiny bit of bit shifting to
++	 * do.
++	 */
+ 	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
+-				OV5693_AGC_L, gain & 0xff);
++				OV5693_AGC_L, OV5693_GAIN_CTRL_L(gain));
+ 	if (ret) {
+ 		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_L);
+@@ -899,7 +903,7 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 	}
+ 
+ 	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
+-				OV5693_AGC_H, (gain >> 8) & 0xff);
++				OV5693_AGC_H, OV5693_GAIN_CTRL_H(gain));
+ 	if (ret) {
+ 		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_H);
+@@ -1674,10 +1678,10 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ 	ov5693->ctrls.analogue_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler,
+ 							ops, V4L2_CID_ANALOGUE_GAIN,
+-							1, 1023, 1, 128);
++							1, 127, 1, 8);
+ 	ov5693->ctrls.digital_gain = v4l2_ctrl_new_std(&ov5693->ctrl_handler, ops,
+ 						       V4L2_CID_DIGITAL_GAIN, 1,
+-						       3999, 1, 1000);
++						       4095, 1, 1024);
+ 
+ 	/* Flip */
+ 
+-- 
+2.30.1
+
+From 4655f5f33e843e03296049fc6efa10f4310eceb3 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 10 Feb 2021 23:44:39 +0000
+Subject: [PATCH] media: i2c: Fixup gain read
+
+This function reads the bits from the gain registers poorly. Update
+it to do that properly (although, it probably just needs to be deleted)
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 51eb3b05d121..952558c4f33b 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -770,30 +770,35 @@ static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+ 
+ static int ov5693_get_exposure(struct ov5693_device *sensor)
+ {
+-	u16 reg_v, reg_v2;
++	u32 exposure = 0;
++	u16 tmp;
+ 	int ret = 0;
+ 
+ 	/* get exposure */
+ 	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_L,
+-			      &reg_v);
++			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
++	exposure |= ((tmp >> 4) & 0b1111);
++
+ 	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_M,
+-			      &reg_v2);
++			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
+-	reg_v += reg_v2 << 8;
++	exposure |= (tmp << 4);
+ 	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_H,
+-			      &reg_v2);
++			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
+-	printk("exposure set to: %u\n", reg_v + (((u32)reg_v2 << 16)));
++	exposure |= (tmp << 12);
++
++	printk("exposure set to: %u\n", exposure);
+ 	return ret;
+ }
+ 
+-- 
+2.30.1
+
+From 8ac23f62d38472adff45eae9c562023b5289cb53 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 11 Feb 2021 00:40:10 +0000
+Subject: [PATCH] media: i2c: Update controls on stream
+
+Currently the ov5693 driver throws away control setting by simply loading
+each mode's default registers. Instead, re-set the user defined controls
+during stream with __v4l2_ctrl_handler_setup()
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 952558c4f33b..dd31083eeb7b 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1492,6 +1492,12 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ 		}
+ 	}
+ 
++	ret = __v4l2_ctrl_handler_setup(&dev->ctrl_handler);
++	if (ret) {
++		power_down(sd);
++		return ret;
++	}
++
+ 	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
+ 			       enable ? OV5693_START_STREAMING :
+ 			       OV5693_STOP_STREAMING);
+-- 
+2.30.1
+
+From 7e8aa95e23d65abe33ca4d80f50fcf47a96ee313 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 11 Feb 2021 23:29:15 +0000
+Subject: [PATCH] media: i2c: Correct link frequency value
+
+The link frequency is given by vts * hts * fps * bits / lanes / 2. In the
+case of the ov5693 driver that works out to 400MHz, not 640Mhz. Correct
+the macro.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 965208078c2b..7f1d31a82d3d 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -186,13 +186,13 @@
+ #define OV5693_OTP_MODE_READ		1
+ 
+ /* link freq and pixel rate required for IPU3 */
+-#define OV5693_LINK_FREQ_640MHZ		640000000
++#define OV5693_LINK_FREQ_400MHZ		400000000
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
+  * To avoid integer overflow, dividing by bits_per_sample first.
+  */
+-#define OV5693_PIXEL_RATE		(OV5693_LINK_FREQ_640MHZ / 10) * 2 * 2
++#define OV5693_PIXEL_RATE		(OV5693_LINK_FREQ_400MHZ / 10) * 2 * 2
+ static const s64 link_freq_menu_items[] = {
+-	OV5693_LINK_FREQ_640MHZ
++	OV5693_LINK_FREQ_400MHZ
+ };
+ 
+ #define OV5693_NUM_SUPPLIES             2
+-- 
+2.30.1
+
+From 061cbcd2070ab1907d0702ff358255514a1efc47 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 25 Jan 2021 23:12:09 +0000
+Subject: [PATCH] media: i2c: Cleanup ov5693 driver
+
+This commit performs some cleanup to the ov5693 driver:
+
+1. Superfluous words in variable names dropped; "i2c_client" becomes
+   "client", "input_lock" becomes "lock"
+2. ov5693_configure_gpios() is does error handling properly, and uses
+   gpiod_get_optional()
+3. The name of the struct ov5693_device variable in each functions, which
+   previously was a mix of dev, sensor or ov5693, is standardised to the
+   latter.
+4. The list of headers is alphabetised (and probably also needs trimming)
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 309 +++++++++++++++++++------------------
+ drivers/media/i2c/ov5693.h |   5 +-
+ 2 files changed, 165 insertions(+), 149 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index dd31083eeb7b..0643390c872a 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -16,25 +16,25 @@
+  *
+  */
+ 
++#include <linux/acpi.h>
+ #include <linux/clk.h>
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/device.h>
+ #include <linux/errno.h>
++#include <linux/i2c.h>
+ #include <linux/init.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
+ #include <linux/kmod.h>
+-#include <linux/device.h>
+-#include <linux/delay.h>
+-#include <linux/slab.h>
+-#include <linux/i2c.h>
++#include <linux/module.h>
+ #include <linux/moduleparam.h>
++#include <linux/mm.h>
++#include <linux/regulator/consumer.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/types.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-fwnode.h>
+-#include <linux/io.h>
+-#include <linux/acpi.h>
+-#include <linux/regulator/consumer.h>
+ 
+ #include "ov5693.h"
+ #include "ad5823.h"
+@@ -485,12 +485,12 @@ static int ov5693_read_otp_reg_array(struct i2c_client *client, u16 size,
+ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	int ret;
+ 	int i;
+ 	u8 *b = buf;
+ 
+-	dev->otp_size = 0;
++	ov5693->otp_size = 0;
+ 	for (i = 1; i < OV5693_OTP_BANK_MAX; i++) {
+ 		/*set bank NO and OTP read mode. */
+ 		ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_OTP_BANK_REG,
+@@ -529,7 +529,7 @@ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ 		//Intel OTP map, try to read 320byts first.
+ 		if (i == 21) {
+ 			if ((*b) == 0) {
+-				dev->otp_size = 320;
++				ov5693->otp_size = 320;
+ 				break;
+ 			}
+ 			/* (*b) != 0 */
+@@ -538,7 +538,7 @@ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ 		} else if (i ==
+ 			   24) {		//if the first 320bytes data doesn't not exist, try to read the next 32bytes data.
+ 			if ((*b) == 0) {
+-				dev->otp_size = 32;
++				ov5693->otp_size = 32;
+ 				break;
+ 			}
+ 			/* (*b) != 0 */
+@@ -547,11 +547,11 @@ static int __ov5693_otp_read(struct v4l2_subdev *sd, u8 *buf)
+ 		} else if (i ==
+ 			   27) {		//if the prvious 32bytes data doesn't exist, try to read the next 32bytes data again.
+ 			if ((*b) == 0) {
+-				dev->otp_size = 32;
++				ov5693->otp_size = 32;
+ 				break;
+ 			}
+ 			/* (*b) != 0 */
+-			dev->otp_size = 0;	// no OTP data.
++			ov5693->otp_size = 0;	// no OTP data.
+ 			break;
+ 		}
+ 
+@@ -598,20 +598,20 @@ static void *ov5693_otp_read(struct v4l2_subdev *sd)
+ 	return buf;
+ }
+ 
+-static int ov5693_update_bits(struct ov5693_device *sensor, u16 address,
++static int ov5693_update_bits(struct ov5693_device *ov5693, u16 address,
+ 			      u16 mask, u16 bits)
+ {
+ 	u16 value = 0;
+ 	int ret;
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT, address, &value);
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT, address, &value);
+ 	if (ret)
+ 		return ret;
+ 
+ 	value &= ~mask;
+ 	value |= bits;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT, address, value);
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT, address, value);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -620,13 +620,13 @@ static int ov5693_update_bits(struct ov5693_device *sensor, u16 address,
+ 
+ /* Flip */
+ 
+-static int ov5693_flip_vert_configure(struct ov5693_device *sensor, bool enable)
++static int ov5693_flip_vert_configure(struct ov5693_device *ov5693, bool enable)
+ {
+ 	u8 bits = OV5693_FORMAT1_FLIP_VERT_ISP_EN |
+ 		  OV5693_FORMAT1_FLIP_VERT_SENSOR_EN;
+ 	int ret;
+ 
+-	ret = ov5693_update_bits(sensor, OV5693_FORMAT1_REG, bits,
++	ret = ov5693_update_bits(ov5693, OV5693_FORMAT1_REG, bits,
+ 				 enable ? bits : 0);
+ 	if (ret)
+ 		return ret;
+@@ -634,13 +634,13 @@ static int ov5693_flip_vert_configure(struct ov5693_device *sensor, bool enable)
+ 	return 0;
+ }
+ 
+-static int ov5693_flip_horz_configure(struct ov5693_device *sensor, bool enable)
++static int ov5693_flip_horz_configure(struct ov5693_device *ov5693, bool enable)
+ {
+ 	u8 bits = OV5693_FORMAT2_FLIP_HORZ_ISP_EN |
+ 		  OV5693_FORMAT2_FLIP_HORZ_SENSOR_EN;
+ 	int ret;
+ 
+-	ret = ov5693_update_bits(sensor, OV5693_FORMAT2_REG, bits,
++	ret = ov5693_update_bits(ov5693, OV5693_FORMAT2_REG, bits,
+ 				 enable ? bits : 0);
+ 	if (ret)
+ 		return ret;
+@@ -721,14 +721,14 @@ static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ 
+ static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 
+ 	dev_dbg(&client->dev, "%s: FOCUS_POS: 0x%x\n", __func__, value);
+ 	value = clamp(value, 0, OV5693_VCM_MAX_FOCUS_POS);
+-	if (dev->vcm == VCM_DW9714) {
+-		if (dev->vcm_update) {
++	if (ov5693->vcm == VCM_DW9714) {
++		if (ov5693->vcm_update) {
+ 			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_OFF);
+ 			if (ret)
+ 				return ret;
+@@ -738,17 +738,17 @@ static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ 			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_ON);
+ 			if (ret)
+ 				return ret;
+-			dev->vcm_update = false;
++			ov5693->vcm_update = false;
+ 		}
+ 		ret = vcm_dw_i2c_write(client,
+ 				       vcm_val(value, VCM_DEFAULT_S));
+-	} else if (dev->vcm == VCM_AD5823) {
++	} else if (ov5693->vcm == VCM_AD5823) {
+ 		ad5823_t_focus_abs(sd, value);
+ 	}
+ 	if (ret == 0) {
+-		dev->number_of_steps = value - dev->focus;
+-		dev->focus = value;
+-		dev->timestamp_t_focus_abs = ktime_get();
++		ov5693->number_of_steps = value - ov5693->focus;
++		ov5693->focus = value;
++		ov5693->timestamp_t_focus_abs = ktime_get();
+ 	} else
+ 		dev_err(&client->dev,
+ 			"%s: i2c failed. ret %d\n", __func__, ret);
+@@ -758,9 +758,9 @@ static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+ 
+ static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+-	return ov5693_t_focus_abs(sd, dev->focus + value);
++	return ov5693_t_focus_abs(sd, ov5693->focus + value);
+ }
+ 
+ #define DELAY_PER_STEP_NS	1000000
+@@ -768,14 +768,14 @@ static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+ 
+ /* Exposure */
+ 
+-static int ov5693_get_exposure(struct ov5693_device *sensor)
++static int ov5693_get_exposure(struct ov5693_device *ov5693)
+ {
+ 	u32 exposure = 0;
+ 	u16 tmp;
+ 	int ret = 0;
+ 
+ 	/* get exposure */
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_L,
+ 			      &tmp);
+ 	if (ret)
+@@ -783,14 +783,14 @@ static int ov5693_get_exposure(struct ov5693_device *sensor)
+ 
+ 	exposure |= ((tmp >> 4) & 0b1111);
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_M,
+ 			      &tmp);
+ 	if (ret)
+ 		return ret;
+ 
+ 	exposure |= (tmp << 4);
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_EXPOSURE_H,
+ 			      &tmp);
+ 	if (ret)
+@@ -802,7 +802,7 @@ static int ov5693_get_exposure(struct ov5693_device *sensor)
+ 	return ret;
+ }
+ 
+-static int ov5693_exposure_configure(struct ov5693_device *sensor, u32 exposure)
++static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ {
+ 	int ret;
+ 
+@@ -812,40 +812,40 @@ static int ov5693_exposure_configure(struct ov5693_device *sensor, u32 exposure)
+ 	 */
+ 	exposure = exposure * 16;
+ 
+-	ov5693_get_exposure(sensor);
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ov5693_get_exposure(ov5693);
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_HH_REG, OV5693_EXPOSURE_CTRL_HH(exposure));
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_H_REG, OV5693_EXPOSURE_CTRL_H(exposure));
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_L_REG, OV5693_EXPOSURE_CTRL_L(exposure));
+ 	if (ret)
+ 		return ret;
+-	ov5693_get_exposure(sensor);
++	ov5693_get_exposure(ov5693);
+ 
+ 	return 0;
+ }
+ 
+ /* Gain */
+ 
+-static int ov5693_get_gain(struct ov5693_device *sensor, u32 *gain)
++static int ov5693_get_gain(struct ov5693_device *ov5693, u32 *gain)
+ {
+ 	u16 gain_l, gain_h;
+ 	int ret = 0;
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_GAIN_CTRL_L_REG,
+ 			      &gain_l);
+ 	if (ret)
+ 		return ret;
+ 
+-	ret = ov5693_read_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+ 			      OV5693_GAIN_CTRL_H_REG,
+ 			      &gain_h);
+ 	if (ret)
+@@ -856,33 +856,33 @@ static int ov5693_get_gain(struct ov5693_device *sensor, u32 *gain)
+ 
+ 	return ret;
+ }
+-static int ov5693_gain_configure(struct ov5693_device *sensor, u32 gain)
++static int ov5693_gain_configure(struct ov5693_device *ov5693, u32 gain)
+ {
+ 	int ret;
+ 
+ 	/* A 1.0 gain is 0x400 */
+ 	gain = (gain * 1024)/1000;
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_16BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_16BIT,
+ 			OV5693_MWB_RED_GAIN_H, gain);
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_MWB_RED_GAIN_H);
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_16BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_16BIT,
+ 			OV5693_MWB_GREEN_GAIN_H, gain);
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_MWB_RED_GAIN_H);
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_16BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_16BIT,
+ 			OV5693_MWB_BLUE_GAIN_H, gain);
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_MWB_RED_GAIN_H);
+ 		return ret;
+ 	}
+@@ -890,7 +890,7 @@ static int ov5693_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 	return 0;
+ }
+ 
+-static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
++static int ov5693_analog_gain_configure(struct ov5693_device *ov5693, u32 gain)
+ {
+ 	int ret;
+ 
+@@ -899,18 +899,18 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 	 * those is not supported, so we have a tiny bit of bit shifting to
+ 	 * do.
+ 	 */
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 				OV5693_AGC_L, OV5693_GAIN_CTRL_L(gain));
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_L);
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 				OV5693_AGC_H, OV5693_GAIN_CTRL_H(gain));
+ 	if (ret) {
+-		dev_err(&sensor->i2c_client->dev, "%s: write %x error, aborted\n",
++		dev_err(&ov5693->client->dev, "%s: write %x error, aborted\n",
+ 			__func__, OV5693_AGC_H);
+ 		return ret;
+ 	}
+@@ -920,60 +920,60 @@ static int ov5693_analog_gain_configure(struct ov5693_device *sensor, u32 gain)
+ 
+ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ {
+-	struct ov5693_device *dev =
++	struct ov5693_device *ov5693 =
+ 	    container_of(ctrl->handler, struct ov5693_device, ctrl_handler);
+-	struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
++	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	int ret = 0;
+ 
+ 	/* If VBLANK is altered we need to update exposure to compensate */
+ 	if (ctrl->id == V4L2_CID_VBLANK) {
+ 		int exposure_max;
+-		exposure_max = dev->mode->lines_per_frame - 8;
+-		__v4l2_ctrl_modify_range(dev->ctrls.exposure, dev->ctrls.exposure->minimum,
+-					 exposure_max, dev->ctrls.exposure->step,
+-					 dev->ctrls.exposure->val < exposure_max ?
+-					 dev->ctrls.exposure->val : exposure_max);
++		exposure_max = ov5693->mode->lines_per_frame - 8;
++		__v4l2_ctrl_modify_range(ov5693->ctrls.exposure, ov5693->ctrls.exposure->minimum,
++					 exposure_max, ov5693->ctrls.exposure->step,
++					 ov5693->ctrls.exposure->val < exposure_max ?
++					 ov5693->ctrls.exposure->val : exposure_max);
+ 	}
+ 
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_t_focus_abs(&dev->sd, ctrl->val);
++		ret = ov5693_t_focus_abs(&ov5693->sd, ctrl->val);
+ 		break;
+ 	case V4L2_CID_FOCUS_RELATIVE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_RELATIVE:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_t_focus_rel(&dev->sd, ctrl->val);
++		ret = ov5693_t_focus_rel(&ov5693->sd, ctrl->val);
+ 		break;
+ 	case V4L2_CID_EXPOSURE:
+ 		dev_dbg(&client->dev, "%s: CID_EXPOSURE:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_exposure_configure(dev, ctrl->val);
++		ret = ov5693_exposure_configure(ov5693, ctrl->val);
+ 		if (ret)
+ 			return ret;
+ 		break;
+ 	case V4L2_CID_ANALOGUE_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_ANALOGUE_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_analog_gain_configure(dev, ctrl->val);
++		ret = ov5693_analog_gain_configure(ov5693, ctrl->val);
+ 		if (ret)
+ 			return ret;
+ 		break;
+ 	case V4L2_CID_DIGITAL_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_DIGITAL_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+-		ret = ov5693_gain_configure(dev, ctrl->val);
++		ret = ov5693_gain_configure(ov5693, ctrl->val);
+ 		if (ret)
+ 			return ret;
+ 		break;
+ 	case V4L2_CID_HFLIP:
+-		return ov5693_flip_horz_configure(dev, !!ctrl->val);
++		return ov5693_flip_horz_configure(ov5693, !!ctrl->val);
+ 	case V4L2_CID_VFLIP:
+-		return ov5693_flip_vert_configure(dev, !!ctrl->val);
++		return ov5693_flip_vert_configure(ov5693, !!ctrl->val);
+ 	case V4L2_CID_VBLANK:
+ 		ret = ov5693_write_reg(client, OV5693_16BIT, OV5693_TIMING_VTS_H,
+-				       dev->mode->height + ctrl->val);
++				       ov5693->mode->height + ctrl->val);
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+@@ -983,16 +983,16 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 
+ static int ov5693_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+ {
+-	struct ov5693_device *dev =
++	struct ov5693_device *ov5693 =
+ 	    container_of(ctrl->handler, struct ov5693_device, ctrl_handler);
+ 	int ret = 0;
+ 
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_EXPOSURE_ABSOLUTE:
+-		ret = ov5693_q_exposure(&dev->sd, &ctrl->val);
++		ret = ov5693_q_exposure(&ov5693->sd, &ctrl->val);
+ 		break;
+ 	case V4L2_CID_AUTOGAIN:
+-		ret = ov5693_get_gain(dev, &ctrl->val);
++		ret = ov5693_get_gain(ov5693, &ctrl->val);
+ 		break;
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		/* NOTE: there was atomisp-specific function ov5693_q_focus_abs() */
+@@ -1034,12 +1034,12 @@ static const struct v4l2_ctrl_config ov5693_controls[] = {
+ 	},
+ };
+ 
+-static int ov5693_isp_configure(struct ov5693_device *sensor)
++static int ov5693_isp_configure(struct ov5693_device *ov5693)
+ {
+ 	int ret;
+ 
+ 	/* Enable lens correction. */
+-	ret = ov5693_write_reg(sensor->i2c_client, OV5693_8BIT,
++	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			   OV5693_ISP_CTRL0_REG, 0x86);
+ 	if (ret)
+ 		return ret;
+@@ -1049,18 +1049,18 @@ static int ov5693_isp_configure(struct ov5693_device *sensor)
+ 
+ static int ov5693_init(struct v4l2_subdev *sd)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret;
+ 
+-	if (!dev->has_vcm)
++	if (!ov5693->has_vcm)
+ 		return 0;
+ 
+ 	dev_info(&client->dev, "%s\n", __func__);
+-	mutex_lock(&dev->input_lock);
+-	dev->vcm_update = false;
++	mutex_lock(&ov5693->lock);
++	ov5693->vcm_update = false;
+ 
+-	if (dev->vcm == VCM_AD5823) {
++	if (ov5693->vcm == VCM_AD5823) {
+ 		ret = vcm_ad_i2c_wr8(client, 0x01, 0x01); /* vcm init test */
+ 		if (ret)
+ 			dev_err(&client->dev,
+@@ -1079,16 +1079,16 @@ static int ov5693_init(struct v4l2_subdev *sd)
+ 	}
+ 
+ 	/*change initial focus value for ad5823*/
+-	if (dev->vcm == VCM_AD5823) {
+-		dev->focus = AD5823_INIT_FOCUS_POS;
++	if (ov5693->vcm == VCM_AD5823) {
++		ov5693->focus = AD5823_INIT_FOCUS_POS;
+ 		ov5693_t_focus_abs(sd, AD5823_INIT_FOCUS_POS);
+ 	} else {
+-		dev->focus = 0;
++		ov5693->focus = 0;
+ 		ov5693_t_focus_abs(sd, 0);
+ 	}
+ 
+-	ov5693_isp_configure(dev);
+-	mutex_unlock(&dev->input_lock);
++	ov5693_isp_configure(ov5693);
++	mutex_unlock(&ov5693->lock);
+ 
+ 	return 0;
+ }
+@@ -1096,32 +1096,32 @@ static int ov5693_init(struct v4l2_subdev *sd)
+ static int __power_up(struct v4l2_subdev *sd)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	struct ov5693_device *sensor = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	int ret;
+ 
+-	ret = clk_prepare_enable(sensor->clk);
++	ret = clk_prepare_enable(ov5693->clk);
+ 	if (ret) {
+ 		dev_err(&client->dev, "Error enabling clock\n");
+ 		return -EINVAL;
+ 	}
+ 
+-	if (sensor->indicator_led)
+-		gpiod_set_value_cansleep(sensor->indicator_led, 1);
++	if (ov5693->indicator_led)
++		gpiod_set_value_cansleep(ov5693->indicator_led, 1);
+ 
+ 	ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES,
+-			sensor->supplies);
++			ov5693->supplies);
+ 	if (ret)
+ 		goto fail_power;
+ 
+-	gpiod_set_value_cansleep(sensor->reset, 0);
++	gpiod_set_value_cansleep(ov5693->reset, 0);
+ 
+ 	__cci_delay(up_delay);
+ 
+ 	return 0;
+ 
+ fail_power:
+-	if (sensor->indicator_led)
+-		gpiod_set_value_cansleep(sensor->indicator_led, 0);
++	if (ov5693->indicator_led)
++		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
+ 	dev_err(&client->dev, "sensor power-up failed\n");
+ 
+ 	return ret;
+@@ -1129,17 +1129,17 @@ static int __power_up(struct v4l2_subdev *sd)
+ 
+ static int power_down(struct v4l2_subdev *sd)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+-	dev->focus = OV5693_INVALID_CONFIG;
++	ov5693->focus = OV5693_INVALID_CONFIG;
+ 
+-	gpiod_set_value_cansleep(dev->reset, 1);
++	gpiod_set_value_cansleep(ov5693->reset, 1);
+ 
+-	clk_disable_unprepare(dev->clk);
++	clk_disable_unprepare(ov5693->clk);
+ 
+-	if (dev->indicator_led)
+-		gpiod_set_value_cansleep(dev->indicator_led, 0);
+-	return regulator_bulk_disable(OV5693_NUM_SUPPLIES, dev->supplies);
++	if (ov5693->indicator_led)
++		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
++	return regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies);
+ }
+ 
+ static int power_up(struct v4l2_subdev *sd)
+@@ -1265,7 +1265,7 @@ static int get_resolution_index(int w, int h)
+ /* TODO: remove it. */
+ static int startup(struct v4l2_subdev *sd)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 
+@@ -1282,7 +1282,7 @@ static int startup(struct v4l2_subdev *sd)
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg_array(client, ov5693_res[dev->fmt_idx].regs);
++	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 write register err.\n");
+ 		return ret;
+@@ -1296,7 +1296,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_format *format)
+ {
+ 	struct v4l2_mbus_framefmt *fmt = &format->format;
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 	int idx;
+@@ -1307,7 +1307,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 	if (!fmt)
+ 		return -EINVAL;
+ 
+-	mutex_lock(&dev->input_lock);
++	mutex_lock(&ov5693->lock);
+ 	idx = nearest_resolution_index(fmt->width, fmt->height);
+ 	if (idx == -1) {
+ 		/* return the largest resolution */
+@@ -1325,8 +1325,8 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		goto mutex_unlock;
+ 	}
+ 
+-	dev->fmt_idx = get_resolution_index(fmt->width, fmt->height);
+-	if (dev->fmt_idx == -1) {
++	ov5693->fmt_idx = get_resolution_index(fmt->width, fmt->height);
++	if (ov5693->fmt_idx == -1) {
+ 		dev_err(&client->dev, "get resolution fail\n");
+ 		ret = -EINVAL;
+ 		goto mutex_unlock;
+@@ -1339,9 +1339,9 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			continue;
+ 		}
+ 
+-		mutex_unlock(&dev->input_lock);
++		mutex_unlock(&ov5693->lock);
+ 		ov5693_init(sd);
+-		mutex_lock(&dev->input_lock);
++		mutex_lock(&ov5693->lock);
+ 		ret = startup(sd);
+ 		if (ret)
+ 			dev_err(&client->dev, " startup() FAILED!\n");
+@@ -1353,8 +1353,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		goto mutex_unlock;
+ 	}
+ 
+-
+-
+ 	/*
+ 	 * After sensor settings are set to HW, sometimes stream is started.
+ 	 * This would cause ISP timeout because ISP is not ready to receive
+@@ -1366,19 +1364,19 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		dev_warn(&client->dev, "ov5693 stream off err\n");
+ 
+ mutex_unlock:
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&ov5693->lock);
+ 	return ret;
+ }
+ 
+ static const struct v4l2_rect *
+-__ov5693_get_pad_crop(struct ov5693_device *dev, struct v4l2_subdev_pad_config *cfg,
++__ov5693_get_pad_crop(struct ov5693_device *ov5693, struct v4l2_subdev_pad_config *cfg,
+ 		      unsigned int pad, enum v4l2_subdev_format_whence which)
+ {
+ 	switch (which) {
+ 	case V4L2_SUBDEV_FORMAT_TRY:
+-		return v4l2_subdev_get_try_crop(&dev->sd, cfg, pad);
++		return v4l2_subdev_get_try_crop(&ov5693->sd, cfg, pad);
+ 	case V4L2_SUBDEV_FORMAT_ACTIVE:
+-		return &dev->mode->crop;
++		return &ov5693->mode->crop;
+ 	}
+ 
+ 	return NULL;
+@@ -1389,12 +1387,12 @@ static int ov5693_get_selection(struct v4l2_subdev *sd,
+ {
+ 	switch (sel->target) {
+ 	case V4L2_SEL_TGT_CROP: {
+-		struct ov5693_device *dev = to_ov5693_sensor(sd);
++		struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+-		mutex_lock(&dev->input_lock);
+-		sel->r = *__ov5693_get_pad_crop(dev, cfg, sel->pad,
++		mutex_lock(&ov5693->lock);
++		sel->r = *__ov5693_get_pad_crop(ov5693, cfg, sel->pad,
+ 						sel->which);
+-		mutex_unlock(&dev->input_lock);
++		mutex_unlock(&ov5693->lock);
+ 
+ 		return 0;
+ 	}
+@@ -1424,7 +1422,7 @@ static int ov5693_get_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_format *format)
+ {
+ 	struct v4l2_mbus_framefmt *fmt = &format->format;
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+ 	if (format->pad)
+ 		return -EINVAL;
+@@ -1432,8 +1430,8 @@ static int ov5693_get_fmt(struct v4l2_subdev *sd,
+ 	if (!fmt)
+ 		return -EINVAL;
+ 
+-	fmt->width = ov5693_res[dev->fmt_idx].width;
+-	fmt->height = ov5693_res[dev->fmt_idx].height;
++	fmt->width = ov5693_res[ov5693->fmt_idx].width;
++	fmt->height = ov5693_res[ov5693->fmt_idx].height;
+ 	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ 
+ 	return 0;
+@@ -1481,7 +1479,7 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret;
+ 
+-	mutex_lock(&dev->input_lock);
++	mutex_lock(&dev->lock);
+ 
+ 	/* power_on() here before streaming for regular PCs. */
+ 	if (enable) {
+@@ -1507,26 +1505,26 @@ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ 		power_down(sd);
+ 
+ out:
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&dev->lock);
+ 
+ 	return ret;
+ }
+ 
+ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 
+-	mutex_lock(&dev->input_lock);
++	mutex_lock(&ov5693->lock);
+ 	ret = power_up(sd);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 power-up err.\n");
+ 		goto fail_power_on;
+ 	}
+ 
+-	if (!dev->vcm)
+-		dev->vcm = vcm_detect(client);
++	if (!ov5693->vcm)
++		ov5693->vcm = vcm_detect(client);
+ 
+ 	/* config & detect sensor */
+ 	ret = ov5693_detect(client);
+@@ -1535,7 +1533,7 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 		goto fail_power_on;
+ 	}
+ 
+-	dev->otp_data = ov5693_otp_read(sd);
++	ov5693->otp_data = ov5693_otp_read(sd);
+ 
+ 	/* turn off sensor, after probed */
+ 	ret = power_down(sd);
+@@ -1543,24 +1541,24 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 		dev_err(&client->dev, "ov5693 power-off err.\n");
+ 		goto fail_power_on;
+ 	}
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&ov5693->lock);
+ 
+ 	return ret;
+ 
+ fail_power_on:
+ 	power_down(sd);
+ 	dev_err(&client->dev, "sensor power-gating failed\n");
+-	mutex_unlock(&dev->input_lock);
++	mutex_unlock(&ov5693->lock);
+ 	return ret;
+ }
+ 
+ static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
+ 				   struct v4l2_subdev_frame_interval *interval)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+ 	interval->interval.numerator = 1;
+-	interval->interval.denominator = ov5693_res[dev->fmt_idx].fps;
++	interval->interval.denominator = ov5693_res[ov5693->fmt_idx].fps;
+ 
+ 	return 0;
+ }
+@@ -1725,7 +1723,7 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 		return ret;
+ 
+ 	/* Use same lock for controls as for everything else. */
+-	ov5693->ctrl_handler.lock = &ov5693->input_lock;
++	ov5693->ctrl_handler.lock = &ov5693->lock;
+ 	ov5693->sd.ctrl_handler = &ov5693->ctrl_handler;
+ 
+ 	return 0;
+@@ -1733,21 +1731,38 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ static int ov5693_configure_gpios(struct ov5693_device *ov5693)
+ {
+-	ov5693->reset = gpiod_get_index(&ov5693->i2c_client->dev, "reset", 0,
++	int ret;
++
++	ov5693->reset = gpiod_get_optional(&ov5693->client->dev, "reset",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->reset)) {
+-                dev_err(&ov5693->i2c_client->dev, "Couldn't find reset GPIO\n");
+-                return -EINVAL;
++                dev_err(&ov5693->client->dev, "Couldn't find reset GPIO\n");
++                return PTR_ERR(ov5693->reset);
++        }
++
++	ov5693->powerdown = gpiod_get_optional(&ov5693->client->dev, "powerdown",
++                                        GPIOD_OUT_HIGH);
++        if (IS_ERR(ov5693->powerdown)) {
++                dev_err(&ov5693->client->dev, "Couldn't find powerdown GPIO\n");
++                ret = PTR_ERR(ov5693->powerdown);
++		goto err_put_reset;
+         }
+ 
+-        ov5693->indicator_led = gpiod_get_index_optional(&ov5693->i2c_client->dev, "indicator-led", 0,
++        ov5693->indicator_led = gpiod_get_optional(&ov5693->client->dev, "indicator-led",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->indicator_led)) {
+-                dev_err(&ov5693->i2c_client->dev, "Couldn't find indicator-led GPIO\n");
+-                return -EINVAL;
++                dev_err(&ov5693->client->dev, "Couldn't find indicator-led GPIO\n");
++                ret = PTR_ERR(ov5693->indicator_led);
++		goto err_put_powerdown;
+         }
+ 
+         return 0;
++err_put_reset:
++	gpiod_put(ov5693->reset);
++err_put_powerdown:
++	gpiod_put(ov5693->powerdown);
++
++	return ret;
+ }
+ 
+ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+@@ -1757,7 +1772,7 @@ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+ 	for (i = 0; i < OV5693_NUM_SUPPLIES; i++)
+ 		ov5693->supplies[i].supply = ov5693_supply_names[i];
+ 
+-	return regulator_bulk_get(&ov5693->i2c_client->dev,
++	return regulator_bulk_get(&ov5693->client->dev,
+ 				       OV5693_NUM_SUPPLIES,
+ 				       ov5693->supplies);
+ }
+@@ -1773,13 +1788,13 @@ static int ov5693_probe(struct i2c_client *client)
+ 	if (!ov5693)
+ 		return -ENOMEM;
+ 
+-	ov5693->i2c_client = client;
++	ov5693->client = client;
+ 
+ 	/* check if VCM device exists */
+ 	/* TODO: read from SSDB */
+ 	ov5693->has_vcm = false;
+ 
+-	mutex_init(&ov5693->input_lock);
++	mutex_init(&ov5693->lock);
+ 
+ 	v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops);
+ 
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 7f1d31a82d3d..70ccb3aae4c7 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -241,14 +241,15 @@ enum vcm_type {
+  * ov5693 device structure.
+  */
+ struct ov5693_device {
+-	struct i2c_client *i2c_client;
++	struct i2c_client *client;
+ 	struct v4l2_subdev sd;
+ 	struct media_pad pad;
+ 	struct v4l2_mbus_framefmt format;
+-	struct mutex input_lock;
++	struct mutex lock;
+ 	struct v4l2_ctrl_handler ctrl_handler;
+ 
+         struct gpio_desc *reset;
++	struct gpio_desc *powerdown;
+         struct gpio_desc *indicator_led;
+         struct regulator_bulk_data supplies[OV5693_NUM_SUPPLIES];
+ 	struct clk *clk;
+-- 
+2.30.1
+
+From 1bb274c64997c78a292658d4b62e4b025271737d Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Jan 2021 12:04:38 +0000
+Subject: [PATCH] media: i2c: Add pm_runtime support to ov5693 driver
+
+The ov5693 driver currently uses hacky and horrible power up/down methods
+called directly in s_stream. Add pm_runtime support and use that in
+s_stream instead. Replace all other uses of the power+up/down() calls with
+the single ov5693_sensor_stream() for now.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 183 +++++++++++++++++++++++++++++--------
+ drivers/media/i2c/ov5693.h |   1 +
+ 2 files changed, 146 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 0643390c872a..f2eaa5f71a31 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -29,6 +29,7 @@
+ #include <linux/module.h>
+ #include <linux/moduleparam.h>
+ #include <linux/mm.h>
++#include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
+@@ -935,6 +936,10 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 					 ov5693->ctrls.exposure->val : exposure_max);
+ 	}
+ 
++	/* Only apply changes to the controls if the device is powered up */
++	if (!pm_runtime_get_if_in_use(&ov5693->client->dev))
++		return 0;
++
+ 	switch (ctrl->id) {
+ 	case V4L2_CID_FOCUS_ABSOLUTE:
+ 		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+@@ -950,27 +955,23 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 		dev_dbg(&client->dev, "%s: CID_EXPOSURE:%d.\n",
+ 			__func__, ctrl->val);
+ 		ret = ov5693_exposure_configure(ov5693, ctrl->val);
+-		if (ret)
+-			return ret;
+ 		break;
+ 	case V4L2_CID_ANALOGUE_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_ANALOGUE_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+ 		ret = ov5693_analog_gain_configure(ov5693, ctrl->val);
+-		if (ret)
+-			return ret;
+ 		break;
+ 	case V4L2_CID_DIGITAL_GAIN:
+ 		dev_dbg(&client->dev, "%s: CID_DIGITAL_GAIN:%d.\n",
+ 			__func__, ctrl->val);
+ 		ret = ov5693_gain_configure(ov5693, ctrl->val);
+-		if (ret)
+-			return ret;
+ 		break;
+ 	case V4L2_CID_HFLIP:
+-		return ov5693_flip_horz_configure(ov5693, !!ctrl->val);
++		ret = ov5693_flip_horz_configure(ov5693, !!ctrl->val);
++		break;
+ 	case V4L2_CID_VFLIP:
+-		return ov5693_flip_vert_configure(ov5693, !!ctrl->val);
++		ret = ov5693_flip_vert_configure(ov5693, !!ctrl->val);
++		break;
+ 	case V4L2_CID_VBLANK:
+ 		ret = ov5693_write_reg(client, OV5693_16BIT, OV5693_TIMING_VTS_H,
+ 				       ov5693->mode->height + ctrl->val);
+@@ -978,6 +979,9 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 	default:
+ 		ret = -EINVAL;
+ 	}
++
++	pm_runtime_put(&ov5693->client->dev);
++
+ 	return ret;
+ }
+ 
+@@ -1093,6 +1097,106 @@ static int ov5693_init(struct v4l2_subdev *sd)
+ 	return 0;
+ }
+ 
++static int ov5693_sw_standby(struct ov5693_device *ov5693, bool standby)
++{
++	return ov5693_write_reg(ov5693->client, OV5693_8BIT, OV5693_SW_STREAM,
++			       standby ? OV5693_STOP_STREAMING : OV5693_START_STREAMING);
++}
++
++static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
++{
++	gpiod_set_value_cansleep(ov5693->reset, 1);
++	gpiod_set_value_cansleep(ov5693->powerdown, 1);
++
++	regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies);
++
++	clk_disable_unprepare(ov5693->clk);
++	gpiod_set_value_cansleep(ov5693->indicator_led, 0);
++}
++
++
++static int ov5693_sensor_powerup(struct ov5693_device *ov5693)
++{
++	int ret = 0;
++
++	gpiod_set_value_cansleep(ov5693->reset, 1);
++	gpiod_set_value_cansleep(ov5693->powerdown, 1);
++
++	ret = clk_prepare_enable(ov5693->clk);
++	if (ret) {
++		dev_err(&ov5693->client->dev, "Failed to enable clk\n");
++		goto fail_power;
++	}
++
++	ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES, ov5693->supplies);
++	if (ret) {
++		dev_err(&ov5693->client->dev, "Failed to enable regulators\n");
++		goto fail_power;
++	}
++
++	gpiod_set_value_cansleep(ov5693->reset, 0);
++	gpiod_set_value_cansleep(ov5693->powerdown, 0);
++	gpiod_set_value_cansleep(ov5693->indicator_led, 1);
++
++	usleep_range(20000, 25000);
++
++	return 0;
++
++fail_power:
++	ov5693_sensor_powerdown(ov5693);
++	return ret;
++}
++
++static int __maybe_unused ov5693_sensor_suspend(struct device *dev)
++{
++	struct i2c_client *client = i2c_verify_client(dev);
++	struct v4l2_subdev *sd = i2c_get_clientdata(client);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
++	int ret;
++
++	mutex_lock(&ov5693->lock);
++
++	if (ov5693->streaming) {
++		ret = ov5693_sw_standby(ov5693, true);
++		if (ret)
++			goto out_unlock;
++	}
++
++	ov5693_sensor_powerdown(ov5693);
++
++out_unlock:
++	mutex_unlock(&ov5693->lock);
++	return ret;
++}
++
++static int __maybe_unused ov5693_sensor_resume(struct device *dev)
++{
++	struct i2c_client *client = i2c_verify_client(dev);
++	struct v4l2_subdev *sd = i2c_get_clientdata(client);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
++	int ret;
++
++	mutex_lock(&ov5693->lock);
++
++	ret = ov5693_sensor_powerup(ov5693);
++	if (ret)
++		goto out_unlock;
++
++	if (ov5693->streaming) {
++		ret = ov5693_sw_standby(ov5693, false);
++		if (ret)
++			goto err_power;
++	}
++
++	goto out_unlock;
++
++err_power:
++	ov5693_sensor_powerdown(ov5693);
++out_unlock:
++	mutex_unlock(&ov5693->lock);
++	return ret;
++}
++
+ static int __power_up(struct v4l2_subdev *sd)
+ {
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+@@ -1134,6 +1238,7 @@ static int power_down(struct v4l2_subdev *sd)
+ 	ov5693->focus = OV5693_INVALID_CONFIG;
+ 
+ 	gpiod_set_value_cansleep(ov5693->reset, 1);
++	gpiod_set_value_cansleep(ov5693->powerdown, 1);
+ 
+ 	clk_disable_unprepare(ov5693->clk);
+ 
+@@ -1333,7 +1438,7 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 	}
+ 
+ 	for (cnt = 0; cnt < OV5693_POWER_UP_RETRY_NUM; cnt++) {
+-		ret = power_up(sd);
++		ret = ov5693_sensor_powerup(ov5693);
+ 		if (ret) {
+ 			dev_err(&client->dev, "power up failed\n");
+ 			continue;
+@@ -1475,38 +1580,34 @@ static int ov5693_detect(struct i2c_client *client)
+ 
+ static int ov5693_s_stream(struct v4l2_subdev *sd, int enable)
+ {
+-	struct ov5693_device *dev = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
++	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 	int ret;
+ 
+-	mutex_lock(&dev->lock);
+-
+-	/* power_on() here before streaming for regular PCs. */
+ 	if (enable) {
+-		ret = power_up(sd);
+-		if (ret) {
+-			dev_err(&client->dev, "sensor power-up error\n");
+-			goto out;
+-		}
++		ret = pm_runtime_get_sync(&ov5693->client->dev);
++		if (ret < 0)
++			goto err_power_down;
+ 	}
+ 
+-	ret = __v4l2_ctrl_handler_setup(&dev->ctrl_handler);
+-	if (ret) {
+-		power_down(sd);
+-		return ret;
+-	}
++	ret = __v4l2_ctrl_handler_setup(&ov5693->ctrl_handler);
++	if (ret)
++		goto err_power_down;
+ 
+-	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
+-			       enable ? OV5693_START_STREAMING :
+-			       OV5693_STOP_STREAMING);
++	mutex_lock(&ov5693->lock);
++	ret = ov5693_sw_standby(ov5693, !enable);
++	mutex_unlock(&ov5693->lock);
++
++	if (ret)
++		goto err_power_down;
++	ov5693->streaming = !!enable;
+ 
+ 	/* power_off() here after streaming for regular PCs. */
+ 	if (!enable)
+-		power_down(sd);
+-
+-out:
+-	mutex_unlock(&dev->lock);
++		pm_runtime_put(&ov5693->client->dev);
+ 
++	return 0;
++err_power_down:
++	pm_runtime_put_noidle(&ov5693->client->dev);
+ 	return ret;
+ }
+ 
+@@ -1517,7 +1618,7 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 	int ret = 0;
+ 
+ 	mutex_lock(&ov5693->lock);
+-	ret = power_up(sd);
++	ret = ov5693_sensor_powerup(ov5693);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 power-up err.\n");
+ 		goto fail_power_on;
+@@ -1536,17 +1637,14 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 	ov5693->otp_data = ov5693_otp_read(sd);
+ 
+ 	/* turn off sensor, after probed */
+-	ret = power_down(sd);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 power-off err.\n");
+-		goto fail_power_on;
+-	}
++	ov5693_sensor_powerdown(ov5693);
++
+ 	mutex_unlock(&ov5693->lock);
+ 
+ 	return ret;
+ 
+ fail_power_on:
+-	power_down(sd);
++	ov5693_sensor_powerdown(ov5693);
+ 	dev_err(&client->dev, "sensor power-gating failed\n");
+ 	mutex_unlock(&ov5693->lock);
+ 	return ret;
+@@ -1830,6 +1928,9 @@ static int ov5693_probe(struct i2c_client *client)
+ 	if (ret)
+ 		ov5693_remove(client);
+ 
++	pm_runtime_enable(&client->dev);
++	pm_runtime_set_suspended(&client->dev);
++
+ 	ret = v4l2_async_register_subdev_sensor_common(&ov5693->sd);
+ 	if (ret) {
+ 		dev_err(&client->dev, "failed to register V4L2 subdev: %d", ret);
+@@ -1839,6 +1940,7 @@ static int ov5693_probe(struct i2c_client *client)
+ 	return ret;
+ 
+ media_entity_cleanup:
++	pm_runtime_disable(&client->dev);
+ 	media_entity_cleanup(&ov5693->sd.entity);
+ out_put_reset:
+         gpiod_put(ov5693->reset);
+@@ -1848,6 +1950,10 @@ static int ov5693_probe(struct i2c_client *client)
+ 	return ret;
+ }
+ 
++static const struct dev_pm_ops ov5693_pm_ops = {
++	SET_RUNTIME_PM_OPS(ov5693_sensor_suspend, ov5693_sensor_resume, NULL)
++};
++
+ static const struct acpi_device_id ov5693_acpi_match[] = {
+ 	{"INT33BE"},
+ 	{},
+@@ -1858,6 +1964,7 @@ static struct i2c_driver ov5693_driver = {
+ 	.driver = {
+ 		.name = "ov5693",
+ 		.acpi_match_table = ov5693_acpi_match,
++		.pm = &ov5693_pm_ops,
+ 	},
+ 	.probe_new = ov5693_probe,
+ 	.remove = ov5693_remove,
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 70ccb3aae4c7..b78d3b474a43 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -256,6 +256,7 @@ struct ov5693_device {
+ 
+ 	/* Current mode */
+ 	const struct ov5693_resolution *mode;
++	bool streaming;
+ 
+ 	struct camera_sensor_platform_data *platform_data;
+ 	ktime_t timestamp_t_focus_abs;
+-- 
+2.30.1
+
+From 14139a66573795862858f43042067bab217e3a8d Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Jan 2021 12:07:36 +0000
+Subject: [PATCH] media: i2c: Remove old power methods from ov5693
+
+Now that we have replaced the power_up/down() methods with a unified
+function and pm_runtime support, we can remove these old methods from the
+driver entirely along with some macros and a header.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 114 -------------------------------------
+ 1 file changed, 114 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index f2eaa5f71a31..ce26ce86fbd5 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -27,7 +27,6 @@
+ #include <linux/kernel.h>
+ #include <linux/kmod.h>
+ #include <linux/module.h>
+-#include <linux/moduleparam.h>
+ #include <linux/mm.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+@@ -40,27 +39,6 @@
+ #include "ov5693.h"
+ #include "ad5823.h"
+ 
+-#define __cci_delay(t) \
+-	do { \
+-		if ((t) < 10) { \
+-			usleep_range((t) * 1000, ((t) + 1) * 1000); \
+-		} else { \
+-			msleep((t)); \
+-		} \
+-	} while (0)
+-
+-/* Value 30ms reached through experimentation on byt ecs.
+- * The DS specifies a much lower value but when using a smaller value
+- * the I2C bus sometimes locks up permanently when starting the camera.
+- * This issue could not be reproduced on cht, so we can reduce the
+- * delay value to a lower value when insmod.
+- */
+-static uint up_delay = 30;
+-module_param(up_delay, uint, 0644);
+-MODULE_PARM_DESC(up_delay,
+-		 "Delay prior to the first CCI transaction for ov5693");
+-
+-
+ /* Exposure/gain */
+ 
+ #define OV5693_EXPOSURE_CTRL_HH_REG		0x3500
+@@ -1197,93 +1175,6 @@ static int __maybe_unused ov5693_sensor_resume(struct device *dev)
+ 	return ret;
+ }
+ 
+-static int __power_up(struct v4l2_subdev *sd)
+-{
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	int ret;
+-
+-	ret = clk_prepare_enable(ov5693->clk);
+-	if (ret) {
+-		dev_err(&client->dev, "Error enabling clock\n");
+-		return -EINVAL;
+-	}
+-
+-	if (ov5693->indicator_led)
+-		gpiod_set_value_cansleep(ov5693->indicator_led, 1);
+-
+-	ret = regulator_bulk_enable(OV5693_NUM_SUPPLIES,
+-			ov5693->supplies);
+-	if (ret)
+-		goto fail_power;
+-
+-	gpiod_set_value_cansleep(ov5693->reset, 0);
+-
+-	__cci_delay(up_delay);
+-
+-	return 0;
+-
+-fail_power:
+-	if (ov5693->indicator_led)
+-		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
+-	dev_err(&client->dev, "sensor power-up failed\n");
+-
+-	return ret;
+-}
+-
+-static int power_down(struct v4l2_subdev *sd)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-
+-	ov5693->focus = OV5693_INVALID_CONFIG;
+-
+-	gpiod_set_value_cansleep(ov5693->reset, 1);
+-	gpiod_set_value_cansleep(ov5693->powerdown, 1);
+-
+-	clk_disable_unprepare(ov5693->clk);
+-
+-	if (ov5693->indicator_led)
+-		gpiod_set_value_cansleep(ov5693->indicator_led, 0);
+-	return regulator_bulk_disable(OV5693_NUM_SUPPLIES, ov5693->supplies);
+-}
+-
+-static int power_up(struct v4l2_subdev *sd)
+-{
+-	static const int retry_count = 4;
+-	int i, ret;
+-
+-	for (i = 0; i < retry_count; i++) {
+-		ret = __power_up(sd);
+-		if (!ret)
+-			return 0;
+-
+-		power_down(sd);
+-	}
+-	return ret;
+-}
+-
+-static int ov5693_s_power(struct v4l2_subdev *sd, int on)
+-{
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret;
+-
+-	dev_info(&client->dev, "%s: on %d\n", __func__, on);
+-
+-	if (on == 0)
+-		return power_down(sd);
+-
+-	/* on == 1 */
+-	ret = power_up(sd);
+-	if (!ret) {
+-		ret = ov5693_init(sd);
+-		/* restore settings */
+-		ov5693_res = ov5693_res_video;
+-		N_RES = N_RES_VIDEO;
+-	}
+-
+-	return ret;
+-}
+-
+ /*
+  * distance - calculate the distance
+  * @res: resolution
+@@ -1694,10 +1585,6 @@ static const struct v4l2_subdev_video_ops ov5693_video_ops = {
+ 	.g_frame_interval = ov5693_g_frame_interval,
+ };
+ 
+-static const struct v4l2_subdev_core_ops ov5693_core_ops = {
+-	.s_power = ov5693_s_power,
+-};
+-
+ static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
+ 	.enum_mbus_code = ov5693_enum_mbus_code,
+ 	.enum_frame_size = ov5693_enum_frame_size,
+@@ -1707,7 +1594,6 @@ static const struct v4l2_subdev_pad_ops ov5693_pad_ops = {
+ };
+ 
+ static const struct v4l2_subdev_ops ov5693_ops = {
+-	.core = &ov5693_core_ops,
+ 	.video = &ov5693_video_ops,
+ 	.pad = &ov5693_pad_ops,
+ };
+-- 
+2.30.1
+
+From 5011775be888a29eaaf4100b229a80271cfc78da Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Jan 2021 12:14:00 +0000
+Subject: [PATCH] media: i2c: Trim unused headers from ov5693
+
+The ov5693 driver includes a ton of unecessary headers,
+trim the list down.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index ce26ce86fbd5..b3b391a49fdb 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -20,19 +20,11 @@
+ #include <linux/clk.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
+-#include <linux/errno.h>
+ #include <linux/i2c.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/kernel.h>
+-#include <linux/kmod.h>
+ #include <linux/module.h>
+-#include <linux/mm.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+-#include <linux/string.h>
+-#include <linux/types.h>
+ #include <media/v4l2-device.h>
+ #include <media/v4l2-fwnode.h>
+ 
+-- 
+2.30.1
+
+From d9137b83092e75131784f32b2f43be8c2be1a13f Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 21:39:35 +0000
+Subject: [PATCH] media: i2c: Remove VCM stuff
+
+This all needs binning, since we have no idea if it's right. It needs to
+be moved to a driver for the VCM device I guess.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 325 +------------------------------------
+ 1 file changed, 1 insertion(+), 324 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index b3b391a49fdb..2c82b6578de9 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -76,72 +76,6 @@
+ #define OV5693_PIXEL_ARRAY_WIDTH	2592U
+ #define OV5693_PIXEL_ARRAY_HEIGHT	1944U
+ 
+-static int vcm_ad_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
+-{
+-	int err;
+-	struct i2c_msg msg;
+-	u8 buf[2];
+-
+-	buf[0] = reg;
+-	buf[1] = val;
+-
+-	msg.addr = VCM_ADDR;
+-	msg.flags = 0;
+-	msg.len = 2;
+-	msg.buf = &buf[0];
+-
+-	err = i2c_transfer(client->adapter, &msg, 1);
+-	if (err != 1) {
+-		dev_err(&client->dev, "%s: vcm i2c fail, err code = %d\n",
+-			__func__, err);
+-		return -EIO;
+-	}
+-	return 0;
+-}
+-
+-static int ad5823_i2c_write(struct i2c_client *client, u8 reg, u8 val)
+-{
+-	struct i2c_msg msg;
+-	u8 buf[2];
+-
+-	buf[0] = reg;
+-	buf[1] = val;
+-	msg.addr = AD5823_VCM_ADDR;
+-	msg.flags = 0;
+-	msg.len = 0x02;
+-	msg.buf = &buf[0];
+-
+-	if (i2c_transfer(client->adapter, &msg, 1) != 1)
+-		return -EIO;
+-	return 0;
+-}
+-
+-static int ad5823_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
+-{
+-	struct i2c_msg msg[2];
+-	u8 buf[2];
+-
+-	buf[0] = reg;
+-	buf[1] = 0;
+-
+-	msg[0].addr = AD5823_VCM_ADDR;
+-	msg[0].flags = 0;
+-	msg[0].len = 0x01;
+-	msg[0].buf = &buf[0];
+-
+-	msg[1].addr = 0x0c;
+-	msg[1].flags = I2C_M_RD;
+-	msg[1].len = 0x01;
+-	msg[1].buf = &buf[1];
+-	*val = 0;
+-	if (i2c_transfer(client->adapter, msg, 2) != 2)
+-		return -EIO;
+-	*val = buf[1];
+-	return 0;
+-}
+-
+-static const u32 ov5693_embedded_effective_size = 28;
+-
+ /* i2c read/write stuff */
+ static int ov5693_read_reg(struct i2c_client *client,
+ 			   u16 data_length, u16 reg, u16 *val)
+@@ -215,69 +149,6 @@ static int ov5693_i2c_write(struct i2c_client *client, u16 len, u8 *data)
+ 	return ret == num_msg ? 0 : -EIO;
+ }
+ 
+-static int vcm_dw_i2c_write(struct i2c_client *client, u16 data)
+-{
+-	struct i2c_msg msg;
+-	const int num_msg = 1;
+-	int ret;
+-	__be16 val;
+-
+-	val = cpu_to_be16(data);
+-	msg.addr = VCM_ADDR;
+-	msg.flags = 0;
+-	msg.len = OV5693_16BIT;
+-	msg.buf = (void *)&val;
+-
+-	ret = i2c_transfer(client->adapter, &msg, 1);
+-
+-	return ret == num_msg ? 0 : -EIO;
+-}
+-
+-/*
+- * Theory: per datasheet, the two VCMs both allow for a 2-byte read.
+- * The DW9714 doesn't actually specify what this does (it has a
+- * two-byte write-only protocol, but specifies the read sequence as
+- * legal), but it returns the same data (zeroes) always, after an
+- * undocumented initial NAK.  The AD5823 has a one-byte address
+- * register to which all writes go, and subsequent reads will cycle
+- * through the 8 bytes of registers.  Notably, the default values (the
+- * device is always power-cycled affirmatively, so we can rely on
+- * these) in AD5823 are not pairwise repetitions of the same 16 bit
+- * word.  So all we have to do is sequentially read two bytes at a
+- * time and see if we detect a difference in any of the first four
+- * pairs.
+- */
+-static int vcm_detect(struct i2c_client *client)
+-{
+-	int i, ret;
+-	struct i2c_msg msg;
+-	u16 data0 = 0, data;
+-
+-	for (i = 0; i < 4; i++) {
+-		msg.addr = VCM_ADDR;
+-		msg.flags = I2C_M_RD;
+-		msg.len = sizeof(data);
+-		msg.buf = (u8 *)&data;
+-		ret = i2c_transfer(client->adapter, &msg, 1);
+-
+-		/*
+-		 * DW9714 always fails the first read and returns
+-		 * zeroes for subsequent ones
+-		 */
+-		if (i == 0 && ret == -EREMOTEIO) {
+-			data0 = 0;
+-			continue;
+-		}
+-
+-		if (i == 0)
+-			data0 = data;
+-
+-		if (data != data0)
+-			return VCM_AD5823;
+-	}
+-	return ret == 1 ? VCM_DW9714 : ret;
+-}
+-
+ static int ov5693_write_reg(struct i2c_client *client, u16 data_length,
+ 			    u16 reg, u16 val)
+ {
+@@ -654,89 +525,6 @@ static int ov5693_q_exposure(struct v4l2_subdev *sd, s32 *value)
+ 	return ret;
+ }
+ 
+-static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val)
+-{
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret = -EINVAL;
+-	u8 vcm_code;
+-
+-	ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code);
+-	if (ret)
+-		return ret;
+-
+-	/* set reg VCM_CODE_MSB Bit[1:0] */
+-	vcm_code = (vcm_code & VCM_CODE_MSB_MASK) |
+-		   ((val >> 8) & ~VCM_CODE_MSB_MASK);
+-	ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB, vcm_code);
+-	if (ret)
+-		return ret;
+-
+-	/* set reg VCM_CODE_LSB Bit[7:0] */
+-	ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_LSB, (val & 0xff));
+-	if (ret)
+-		return ret;
+-
+-	/* set required vcm move time */
+-	vcm_code = AD5823_RESONANCE_PERIOD / AD5823_RESONANCE_COEF
+-		   - AD5823_HIGH_FREQ_RANGE;
+-	ret = ad5823_i2c_write(client, AD5823_REG_VCM_MOVE_TIME, vcm_code);
+-
+-	return ret;
+-}
+-
+-static int ad5823_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+-{
+-	value = min(value, AD5823_MAX_FOCUS_POS);
+-	return ad5823_t_focus_vcm(sd, value);
+-}
+-
+-static int ov5693_t_focus_abs(struct v4l2_subdev *sd, s32 value)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret = 0;
+-
+-	dev_dbg(&client->dev, "%s: FOCUS_POS: 0x%x\n", __func__, value);
+-	value = clamp(value, 0, OV5693_VCM_MAX_FOCUS_POS);
+-	if (ov5693->vcm == VCM_DW9714) {
+-		if (ov5693->vcm_update) {
+-			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_OFF);
+-			if (ret)
+-				return ret;
+-			ret = vcm_dw_i2c_write(client, DIRECT_VCM);
+-			if (ret)
+-				return ret;
+-			ret = vcm_dw_i2c_write(client, VCM_PROTECTION_ON);
+-			if (ret)
+-				return ret;
+-			ov5693->vcm_update = false;
+-		}
+-		ret = vcm_dw_i2c_write(client,
+-				       vcm_val(value, VCM_DEFAULT_S));
+-	} else if (ov5693->vcm == VCM_AD5823) {
+-		ad5823_t_focus_abs(sd, value);
+-	}
+-	if (ret == 0) {
+-		ov5693->number_of_steps = value - ov5693->focus;
+-		ov5693->focus = value;
+-		ov5693->timestamp_t_focus_abs = ktime_get();
+-	} else
+-		dev_err(&client->dev,
+-			"%s: i2c failed. ret %d\n", __func__, ret);
+-
+-	return ret;
+-}
+-
+-static int ov5693_t_focus_rel(struct v4l2_subdev *sd, s32 value)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-
+-	return ov5693_t_focus_abs(sd, ov5693->focus + value);
+-}
+-
+-#define DELAY_PER_STEP_NS	1000000
+-#define DELAY_MAX_PER_STEP_NS	(1000000 * 1023)
+-
+ /* Exposure */
+ 
+ static int ov5693_get_exposure(struct ov5693_device *ov5693)
+@@ -911,16 +699,6 @@ static int ov5693_s_ctrl(struct v4l2_ctrl *ctrl)
+ 		return 0;
+ 
+ 	switch (ctrl->id) {
+-	case V4L2_CID_FOCUS_ABSOLUTE:
+-		dev_dbg(&client->dev, "%s: CID_FOCUS_ABSOLUTE:%d.\n",
+-			__func__, ctrl->val);
+-		ret = ov5693_t_focus_abs(&ov5693->sd, ctrl->val);
+-		break;
+-	case V4L2_CID_FOCUS_RELATIVE:
+-		dev_dbg(&client->dev, "%s: CID_FOCUS_RELATIVE:%d.\n",
+-			__func__, ctrl->val);
+-		ret = ov5693_t_focus_rel(&ov5693->sd, ctrl->val);
+-		break;
+ 	case V4L2_CID_EXPOSURE:
+ 		dev_dbg(&client->dev, "%s: CID_EXPOSURE:%d.\n",
+ 			__func__, ctrl->val);
+@@ -983,90 +761,6 @@ static const struct v4l2_ctrl_ops ov5693_ctrl_ops = {
+ 	.g_volatile_ctrl = ov5693_g_volatile_ctrl
+ };
+ 
+-static const struct v4l2_ctrl_config ov5693_controls[] = {
+-	{
+-		.ops = &ov5693_ctrl_ops,
+-		.id = V4L2_CID_FOCUS_ABSOLUTE,
+-		.type = V4L2_CTRL_TYPE_INTEGER,
+-		.name = "focus move absolute",
+-		.min = 0,
+-		.max = OV5693_VCM_MAX_FOCUS_POS,
+-		.step = 1,
+-		.def = 0,
+-		.flags = 0,
+-	},
+-	{
+-		.ops = &ov5693_ctrl_ops,
+-		.id = V4L2_CID_FOCUS_RELATIVE,
+-		.type = V4L2_CTRL_TYPE_INTEGER,
+-		.name = "focus move relative",
+-		.min = OV5693_VCM_MAX_FOCUS_NEG,
+-		.max = OV5693_VCM_MAX_FOCUS_POS,
+-		.step = 1,
+-		.def = 0,
+-		.flags = 0,
+-	},
+-};
+-
+-static int ov5693_isp_configure(struct ov5693_device *ov5693)
+-{
+-	int ret;
+-
+-	/* Enable lens correction. */
+-	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+-			   OV5693_ISP_CTRL0_REG, 0x86);
+-	if (ret)
+-		return ret;
+-
+-	return 0;
+-}
+-
+-static int ov5693_init(struct v4l2_subdev *sd)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret;
+-
+-	if (!ov5693->has_vcm)
+-		return 0;
+-
+-	dev_info(&client->dev, "%s\n", __func__);
+-	mutex_lock(&ov5693->lock);
+-	ov5693->vcm_update = false;
+-
+-	if (ov5693->vcm == VCM_AD5823) {
+-		ret = vcm_ad_i2c_wr8(client, 0x01, 0x01); /* vcm init test */
+-		if (ret)
+-			dev_err(&client->dev,
+-				"vcm reset failed\n");
+-		/*change the mode*/
+-		ret = ad5823_i2c_write(client, AD5823_REG_VCM_CODE_MSB,
+-				       AD5823_RING_CTRL_ENABLE);
+-		if (ret)
+-			dev_err(&client->dev,
+-				"vcm enable ringing failed\n");
+-		ret = ad5823_i2c_write(client, AD5823_REG_MODE,
+-				       AD5823_ARC_RES1);
+-		if (ret)
+-			dev_err(&client->dev,
+-				"vcm change mode failed\n");
+-	}
+-
+-	/*change initial focus value for ad5823*/
+-	if (ov5693->vcm == VCM_AD5823) {
+-		ov5693->focus = AD5823_INIT_FOCUS_POS;
+-		ov5693_t_focus_abs(sd, AD5823_INIT_FOCUS_POS);
+-	} else {
+-		ov5693->focus = 0;
+-		ov5693_t_focus_abs(sd, 0);
+-	}
+-
+-	ov5693_isp_configure(ov5693);
+-	mutex_unlock(&ov5693->lock);
+-
+-	return 0;
+-}
+-
+ static int ov5693_sw_standby(struct ov5693_device *ov5693, bool standby)
+ {
+ 	return ov5693_write_reg(ov5693->client, OV5693_8BIT, OV5693_SW_STREAM,
+@@ -1327,9 +1021,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			continue;
+ 		}
+ 
+-		mutex_unlock(&ov5693->lock);
+-		ov5693_init(sd);
+-		mutex_lock(&ov5693->lock);
+ 		ret = startup(sd);
+ 		if (ret)
+ 			dev_err(&client->dev, " startup() FAILED!\n");
+@@ -1507,9 +1198,6 @@ static int ov5693_s_config(struct v4l2_subdev *sd, int irq)
+ 		goto fail_power_on;
+ 	}
+ 
+-	if (!ov5693->vcm)
+-		ov5693->vcm = vcm_detect(client);
+-
+ 	/* config & detect sensor */
+ 	ret = ov5693_detect(client);
+ 	if (ret) {
+@@ -1617,24 +1305,17 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 	struct i2c_client *client = v4l2_get_subdevdata(&ov5693->sd);
+ 	const struct v4l2_ctrl_ops *ops = &ov5693_ctrl_ops;
+ 	struct v4l2_fwnode_device_properties props;
+-	unsigned int i;
+ 	int ret;
+ 	int hblank;
+ 	int vblank_max, vblank_min, vblank_def;
+ 	int exposure_max;
+ 
+-	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler,
+-				     ARRAY_SIZE(ov5693_controls));
++	ret = v4l2_ctrl_handler_init(&ov5693->ctrl_handler, 8);
+ 	if (ret) {
+ 		ov5693_remove(client);
+ 		return ret;
+ 	}
+ 
+-	for (i = 0; i < ARRAY_SIZE(ov5693_controls); i++)
+-		v4l2_ctrl_new_custom(&ov5693->ctrl_handler,
+-				     &ov5693_controls[i],
+-				     NULL);
+-
+ 	/* link freq */
+ 	ov5693->ctrls.link_freq = v4l2_ctrl_new_int_menu(&ov5693->ctrl_handler,
+ 							 NULL, V4L2_CID_LINK_FREQ,
+@@ -1766,10 +1447,6 @@ static int ov5693_probe(struct i2c_client *client)
+ 
+ 	ov5693->client = client;
+ 
+-	/* check if VCM device exists */
+-	/* TODO: read from SSDB */
+-	ov5693->has_vcm = false;
+-
+ 	mutex_init(&ov5693->lock);
+ 
+ 	v4l2_i2c_subdev_init(&ov5693->sd, client, &ov5693_ops);
+-- 
+2.30.1
+
+From 260af2d112381bd949f9900f141a1e7ef78951d7 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 22:16:08 +0000
+Subject: [PATCH] media: i2c: Tidy up ov5693 sensor init
+
+The initialisation of a mode when the sensor is activated is a bit messy,
+so lets tidy that up a bit to bring it in line with other drivers.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 100 ++++++++++++++++---------------------
+ 1 file changed, 42 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 2c82b6578de9..313bc9177328 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -767,6 +767,42 @@ static int ov5693_sw_standby(struct ov5693_device *ov5693, bool standby)
+ 			       standby ? OV5693_STOP_STREAMING : OV5693_START_STREAMING);
+ }
+ 
++static int ov5693_sw_reset(struct ov5693_device *ov5693)
++{
++	return ov5693_write_reg(ov5693->client, OV5693_8BIT, OV5693_SW_RESET,
++				0x01);
++}
++
++static int ov5693_sensor_init(struct ov5693_device *ov5693)
++{
++	struct i2c_client *client = ov5693->client;
++	int ret = 0;
++
++	ret = ov5693_sw_reset(ov5693);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 reset err.\n");
++		return ret;
++	}
++
++	ret = ov5693_write_reg_array(client, ov5693_global_setting);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 write register err.\n");
++		return ret;
++	}
++
++	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 write register err.\n");
++		return ret;
++	}
++
++	ret = ov5693_sw_standby(ov5693, true);
++	if (ret)
++		dev_err(&client->dev, "ov5693 stream off error\n");
++
++	return ret;
++}
++
+ static void ov5693_sensor_powerdown(struct ov5693_device *ov5693)
+ {
+ 	gpiod_set_value_cansleep(ov5693->reset, 1);
+@@ -846,6 +882,12 @@ static int __maybe_unused ov5693_sensor_resume(struct device *dev)
+ 	if (ret)
+ 		goto out_unlock;
+ 
++	ret = ov5693_sensor_init(ov5693);
++	if (ret) {
++		dev_err(&client->dev, "ov5693 sensor init failure\n");
++		goto err_power;
++	}
++
+ 	if (ov5693->streaming) {
+ 		ret = ov5693_sw_standby(ov5693, false);
+ 		if (ret)
+@@ -944,35 +986,6 @@ static int get_resolution_index(int w, int h)
+ 	return -1;
+ }
+ 
+-/* TODO: remove it. */
+-static int startup(struct v4l2_subdev *sd)
+-{
+-	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
+-	int ret = 0;
+-
+-	ret = ov5693_write_reg(client, OV5693_8BIT,
+-			       OV5693_SW_RESET, 0x01);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 reset err.\n");
+-		return ret;
+-	}
+-
+-	ret = ov5693_write_reg_array(client, ov5693_global_setting);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 write register err.\n");
+-		return ret;
+-	}
+-
+-	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
+-	if (ret) {
+-		dev_err(&client->dev, "ov5693 write register err.\n");
+-		return ret;
+-	}
+-
+-	return ret;
+-}
+-
+ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_pad_config *cfg,
+ 			  struct v4l2_subdev_format *format)
+@@ -982,7 +995,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 	struct i2c_client *client = v4l2_get_subdevdata(sd);
+ 	int ret = 0;
+ 	int idx;
+-	int cnt;
+ 
+ 	if (format->pad)
+ 		return -EINVAL;
+@@ -1014,34 +1026,6 @@ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 		goto mutex_unlock;
+ 	}
+ 
+-	for (cnt = 0; cnt < OV5693_POWER_UP_RETRY_NUM; cnt++) {
+-		ret = ov5693_sensor_powerup(ov5693);
+-		if (ret) {
+-			dev_err(&client->dev, "power up failed\n");
+-			continue;
+-		}
+-
+-		ret = startup(sd);
+-		if (ret)
+-			dev_err(&client->dev, " startup() FAILED!\n");
+-		else
+-			break;
+-	}
+-	if (cnt == OV5693_POWER_UP_RETRY_NUM) {
+-		dev_err(&client->dev, "power up failed, gave up\n");
+-		goto mutex_unlock;
+-	}
+-
+-	/*
+-	 * After sensor settings are set to HW, sometimes stream is started.
+-	 * This would cause ISP timeout because ISP is not ready to receive
+-	 * data yet. So add stop streaming here.
+-	 */
+-	ret = ov5693_write_reg(client, OV5693_8BIT, OV5693_SW_STREAM,
+-			       OV5693_STOP_STREAMING);
+-	if (ret)
+-		dev_warn(&client->dev, "ov5693 stream off err\n");
+-
+ mutex_unlock:
+ 	mutex_unlock(&ov5693->lock);
+ 	return ret;
+-- 
+2.30.1
+
+From e3683a5e3542eeff0cc582088ca06c448546bc7f Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 12 Feb 2021 16:14:04 +0000
+Subject: [PATCH] media: i2c: cleanup macros in ov5693.h
+
+Lots of orphaned or duplicated macros in this header file. Clean
+those up a bit so it's less ugly.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 89 +-------------------------------------
+ 1 file changed, 2 insertions(+), 87 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index b78d3b474a43..6502777eb5f3 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -37,68 +37,23 @@
+  */
+ #define ENABLE_NON_PREVIEW	1
+ 
+-#define OV5693_POWER_UP_RETRY_NUM 5
+-
+ /* Defines for register writes and register array processing */
+-#define I2C_MSG_LENGTH		0x2
+-#define I2C_RETRY_COUNT		5
+-
+-#define OV5693_FOCAL_LENGTH_NUM	334	/*3.34mm*/
+-#define OV5693_FOCAL_LENGTH_DEM	100
+-#define OV5693_F_NUMBER_DEFAULT_NUM	24
+-#define OV5693_F_NUMBER_DEM	10
++#define I2C_MSG_LENGTH         0x2
+ 
+ #define MAX_FMTS		1
+ 
+-/* sensor_mode_data read_mode adaptation */
+-#define OV5693_READ_MODE_BINNING_ON	0x0400
+-#define OV5693_READ_MODE_BINNING_OFF	0x00
+-#define OV5693_INTEGRATION_TIME_MARGIN	8
+-
+-#define OV5693_MAX_EXPOSURE_VALUE	0xFFF1
+-#define OV5693_MAX_GAIN_VALUE		0xFF
+-
+-/*
+- * focal length bits definition:
+- * bits 31-16: numerator, bits 15-0: denominator
+- */
+-#define OV5693_FOCAL_LENGTH_DEFAULT 0x1B70064
+-
+-/*
+- * current f-number bits definition:
+- * bits 31-16: numerator, bits 15-0: denominator
+- */
+-#define OV5693_F_NUMBER_DEFAULT 0x18000a
+-
+-/*
+- * f-number range bits definition:
+- * bits 31-24: max f-number numerator
+- * bits 23-16: max f-number denominator
+- * bits 15-8: min f-number numerator
+- * bits 7-0: min f-number denominator
+- */
+-#define OV5693_F_NUMBER_RANGE 0x180a180a
+ #define OV5693_ID	0x5690
+ 
+-#define OV5693_FINE_INTG_TIME_MIN 0
+-#define OV5693_FINE_INTG_TIME_MAX_MARGIN 0
+-#define OV5693_COARSE_INTG_TIME_MIN 1
+-#define OV5693_COARSE_INTG_TIME_MAX_MARGIN 6
+-
+-#define OV5693_BIN_FACTOR_MAX 4
+ /*
+  * OV5693 System control registers
+  */
+-#define OV5693_SW_SLEEP				0x0100
+ #define OV5693_SW_RESET				0x0103
+ #define OV5693_SW_STREAM			0x0100
+ 
+ #define OV5693_SC_CMMN_CHIP_ID_H		0x300A
+ #define OV5693_SC_CMMN_CHIP_ID_L		0x300B
+-#define OV5693_SC_CMMN_SCCB_ID			0x300C
+ #define OV5693_SC_CMMN_SUB_ID			0x302A /* process, version*/
+-/*Bit[7:4] Group control, Bit[3:0] Group ID*/
+-#define OV5693_GROUP_ACCESS			0x3208
++
+ /*
+ *Bit[3:0] Bit[19:16] of exposure,
+ *remaining 16 bits lies in Reg0x3501&Reg0x3502
+@@ -110,18 +65,6 @@
+ #define OV5693_AGC_H				0x350A
+ #define OV5693_AGC_L				0x350B /*Bit[7:0] of gain*/
+ 
+-#define OV5693_HORIZONTAL_START_H		0x3800 /*Bit[11:8]*/
+-#define OV5693_HORIZONTAL_START_L		0x3801 /*Bit[7:0]*/
+-#define OV5693_VERTICAL_START_H			0x3802 /*Bit[11:8]*/
+-#define OV5693_VERTICAL_START_L			0x3803 /*Bit[7:0]*/
+-#define OV5693_HORIZONTAL_END_H			0x3804 /*Bit[11:8]*/
+-#define OV5693_HORIZONTAL_END_L			0x3805 /*Bit[7:0]*/
+-#define OV5693_VERTICAL_END_H			0x3806 /*Bit[11:8]*/
+-#define OV5693_VERTICAL_END_L			0x3807 /*Bit[7:0]*/
+-#define OV5693_HORIZONTAL_OUTPUT_SIZE_H		0x3808 /*Bit[3:0]*/
+-#define OV5693_HORIZONTAL_OUTPUT_SIZE_L		0x3809 /*Bit[7:0]*/
+-#define OV5693_VERTICAL_OUTPUT_SIZE_H		0x380a /*Bit[3:0]*/
+-#define OV5693_VERTICAL_OUTPUT_SIZE_L		0x380b /*Bit[7:0]*/
+ /*High 8-bit, and low 8-bit HTS address is 0x380d*/
+ #define OV5693_TIMING_HTS_H			0x380C
+ /*High 8-bit, and low 8-bit HTS address is 0x380d*/
+@@ -141,34 +84,6 @@
+ #define OV5693_START_STREAMING			0x01
+ #define OV5693_STOP_STREAMING			0x00
+ 
+-#define VCM_ADDR           0x0c
+-#define VCM_CODE_MSB       0x04
+-
+-#define OV5693_INVALID_CONFIG	0xffffffff
+-
+-#define OV5693_VCM_SLEW_STEP			0x30F0
+-#define OV5693_VCM_SLEW_STEP_MAX		0x7
+-#define OV5693_VCM_SLEW_STEP_MASK		0x7
+-#define OV5693_VCM_CODE				0x30F2
+-#define OV5693_VCM_SLEW_TIME			0x30F4
+-#define OV5693_VCM_SLEW_TIME_MAX		0xffff
+-#define OV5693_VCM_ENABLE			0x8000
+-
+-#define OV5693_VCM_MAX_FOCUS_NEG       -1023
+-#define OV5693_VCM_MAX_FOCUS_POS       1023
+-
+-#define DLC_ENABLE 1
+-#define DLC_DISABLE 0
+-#define VCM_PROTECTION_OFF     0xeca3
+-#define VCM_PROTECTION_ON      0xdc51
+-#define VCM_DEFAULT_S 0x0
+-#define vcm_step_s(a) (u8)(a & 0xf)
+-#define vcm_step_mclk(a) (u8)((a >> 4) & 0x3)
+-#define vcm_dlc_mclk(dlc, mclk) (u16)((dlc << 3) | mclk | 0xa104)
+-#define vcm_tsrc(tsrc) (u16)(tsrc << 3 | 0xf200)
+-#define vcm_val(data, s) (u16)(data << 4 | s)
+-#define DIRECT_VCM vcm_dlc_mclk(0, 0)
+-
+ /* Defines for OTP Data Registers */
+ #define OV5693_FRAME_OFF_NUM		0x4202
+ #define OV5693_OTP_BYTE_MAX		32	//change to 32 as needed by otpdata
+-- 
+2.30.1
+
+From 2cb9a2fe394eea0b1aa79effb5a6a6fd6c04664f Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 12 Feb 2021 16:19:09 +0000
+Subject: [PATCH] media: i2c: use devm_kzalloc() to initialise ov5693
+
+There's a memory leak in probe because we're not using devres; swtich
+so that we are.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 313bc9177328..d092ed698eb3 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1425,7 +1425,7 @@ static int ov5693_probe(struct i2c_client *client)
+ 
+ 	dev_info(&client->dev, "%s() called", __func__);
+ 
+-	ov5693 = kzalloc(sizeof(*ov5693), GFP_KERNEL);
++	ov5693 = devm_kzalloc(&client->dev, sizeof(*ov5693), GFP_KERNEL);
+ 	if (!ov5693)
+ 		return -ENOMEM;
+ 
+-- 
+2.30.1
+
+From c3881f7d460ab00663028af4fc1ebf3d18545664 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 12 Feb 2021 16:26:21 +0000
+Subject: [PATCH] media: i2c: Check for supported clk rate in probe
+
+The ov5693 driver is configured to support a 19.2MHz external clock only.
+Check that we do indeed have that value and if not, exit with -EINVAL.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 8 ++++++++
+ drivers/media/i2c/ov5693.h | 2 ++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index d092ed698eb3..8082d37841da 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1421,6 +1421,7 @@ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+ static int ov5693_probe(struct i2c_client *client)
+ {
+ 	struct ov5693_device *ov5693;
++	u32 clk_rate;
+ 	int ret = 0;
+ 
+ 	dev_info(&client->dev, "%s() called", __func__);
+@@ -1441,6 +1442,13 @@ static int ov5693_probe(struct i2c_client *client)
+ 		return -EINVAL;
+ 	}
+ 
++	clk_rate = clk_get_rate(ov5693->clk);
++	if (clk_rate != OV5693_XVCLK_FREQ) {
++		dev_err(&client->dev, "Unsupported clk freq %u, expected %u\n",
++			clk_rate, OV5693_XVCLK_FREQ);
++		return -EINVAL;
++	}
++
+ 	ret = ov5693_configure_gpios(ov5693);
+         if (ret)
+                 goto out_free;
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 6502777eb5f3..0dfbbe9a0ff2 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -100,6 +100,8 @@
+ #define OV5693_OTP_READ_ONETIME		16
+ #define OV5693_OTP_MODE_READ		1
+ 
++#define OV5693_XVCLK_FREQ		19200000
++
+ /* link freq and pixel rate required for IPU3 */
+ #define OV5693_LINK_FREQ_400MHZ		400000000
+ /* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
+-- 
+2.30.1
+
+From 8c9c4147b12bf81ca8ac1c2250fed0fb399546fb Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 23:17:50 +0000
+Subject: [PATCH] media: i2c: Use devres to fetch gpios
+
+Use devres; it'll simplify error handling through this function
+and probe.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 22 +++++-----------------
+ 1 file changed, 5 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 8082d37841da..c580159079d2 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1270,8 +1270,6 @@ static int ov5693_remove(struct i2c_client *client)
+ 
+ 	dev_info(&client->dev, "%s...\n", __func__);
+ 
+-	gpiod_put(ov5693->reset);
+-	gpiod_put(ov5693->indicator_led);
+ 	while (i--)
+ 		regulator_put(ov5693->supplies[i].consumer);
+ 
+@@ -1372,38 +1370,28 @@ static int ov5693_init_controls(struct ov5693_device *ov5693)
+ 
+ static int ov5693_configure_gpios(struct ov5693_device *ov5693)
+ {
+-	int ret;
+-
+-	ov5693->reset = gpiod_get_optional(&ov5693->client->dev, "reset",
++	ov5693->reset = devm_gpiod_get_optional(&ov5693->client->dev, "reset",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->reset)) {
+                 dev_err(&ov5693->client->dev, "Couldn't find reset GPIO\n");
+                 return PTR_ERR(ov5693->reset);
+         }
+ 
+-	ov5693->powerdown = gpiod_get_optional(&ov5693->client->dev, "powerdown",
++	ov5693->powerdown = devm_gpiod_get_optional(&ov5693->client->dev, "powerdown",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->powerdown)) {
+                 dev_err(&ov5693->client->dev, "Couldn't find powerdown GPIO\n");
+-                ret = PTR_ERR(ov5693->powerdown);
+-		goto err_put_reset;
++                return PTR_ERR(ov5693->powerdown);
+         }
+ 
+-        ov5693->indicator_led = gpiod_get_optional(&ov5693->client->dev, "indicator-led",
++        ov5693->indicator_led = devm_gpiod_get_optional(&ov5693->client->dev, "indicator-led",
+                                         GPIOD_OUT_HIGH);
+         if (IS_ERR(ov5693->indicator_led)) {
+                 dev_err(&ov5693->client->dev, "Couldn't find indicator-led GPIO\n");
+-                ret = PTR_ERR(ov5693->indicator_led);
+-		goto err_put_powerdown;
++                return PTR_ERR(ov5693->indicator_led);
+         }
+ 
+         return 0;
+-err_put_reset:
+-	gpiod_put(ov5693->reset);
+-err_put_powerdown:
+-	gpiod_put(ov5693->powerdown);
+-
+-	return ret;
+ }
+ 
+ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+-- 
+2.30.1
+
+From c3291b3ac09027634975e779df81fda093a35db8 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sat, 13 Feb 2021 23:20:47 +0000
+Subject: [PATCH] media: i2c: Use devres to fetch regulators
+
+As before, use devres to simplify error handling and driver removal
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index c580159079d2..9f61b470f8ba 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -1266,13 +1266,9 @@ static int ov5693_remove(struct i2c_client *client)
+ {
+ 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ 	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	unsigned int i = OV5693_NUM_SUPPLIES;
+ 
+ 	dev_info(&client->dev, "%s...\n", __func__);
+ 
+-	while (i--)
+-		regulator_put(ov5693->supplies[i].consumer);
+-
+ 	v4l2_async_unregister_subdev(sd);
+ 
+ 	media_entity_cleanup(&ov5693->sd.entity);
+@@ -1401,7 +1397,7 @@ static int ov5693_get_regulators(struct ov5693_device *ov5693)
+ 	for (i = 0; i < OV5693_NUM_SUPPLIES; i++)
+ 		ov5693->supplies[i].supply = ov5693_supply_names[i];
+ 
+-	return regulator_bulk_get(&ov5693->client->dev,
++	return devm_regulator_bulk_get(&ov5693->client->dev,
+ 				       OV5693_NUM_SUPPLIES,
+ 				       ov5693->supplies);
+ }
+-- 
+2.30.1
+
+From 28c672a3b4746e7423a3995361e0f78c2618b045 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sun, 14 Feb 2021 12:39:14 +0000
+Subject: [PATCH] media: i2c: remove debug print
+
+The exposure configure function has a debug print. It's working fine,
+so bin it.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 37 -------------------------------------
+ 1 file changed, 37 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 9f61b470f8ba..622a7ddf4063 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -526,41 +526,6 @@ static int ov5693_q_exposure(struct v4l2_subdev *sd, s32 *value)
+ }
+ 
+ /* Exposure */
+-
+-static int ov5693_get_exposure(struct ov5693_device *ov5693)
+-{
+-	u32 exposure = 0;
+-	u16 tmp;
+-	int ret = 0;
+-
+-	/* get exposure */
+-	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+-			      OV5693_EXPOSURE_L,
+-			      &tmp);
+-	if (ret)
+-		return ret;
+-
+-	exposure |= ((tmp >> 4) & 0b1111);
+-
+-	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+-			      OV5693_EXPOSURE_M,
+-			      &tmp);
+-	if (ret)
+-		return ret;
+-
+-	exposure |= (tmp << 4);
+-	ret = ov5693_read_reg(ov5693->client, OV5693_8BIT,
+-			      OV5693_EXPOSURE_H,
+-			      &tmp);
+-	if (ret)
+-		return ret;
+-
+-	exposure |= (tmp << 12);
+-
+-	printk("exposure set to: %u\n", exposure);
+-	return ret;
+-}
+-
+ static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ {
+ 	int ret;
+@@ -571,7 +536,6 @@ static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ 	 */
+ 	exposure = exposure * 16;
+ 
+-	ov5693_get_exposure(ov5693);
+ 	ret = ov5693_write_reg(ov5693->client, OV5693_8BIT,
+ 			OV5693_EXPOSURE_CTRL_HH_REG, OV5693_EXPOSURE_CTRL_HH(exposure));
+ 	if (ret)
+@@ -586,7 +550,6 @@ static int ov5693_exposure_configure(struct ov5693_device *ov5693, u32 exposure)
+ 			OV5693_EXPOSURE_CTRL_L_REG, OV5693_EXPOSURE_CTRL_L(exposure));
+ 	if (ret)
+ 		return ret;
+-	ov5693_get_exposure(ov5693);
+ 
+ 	return 0;
+ }
+-- 
+2.30.1
+
+From af898b2bae16e9e8afaf7408a2dc7ecf503ac2f2 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sun, 14 Feb 2021 14:32:50 +0000
+Subject: [PATCH] media: i2c: Remove unused resolutions from ov5693
+
+The list of resolutions in here is really unmaintanably long. For now just
+bin all of the ones that are not part of ov5693_res_video, which is the
+only array of resolutions in use anyway.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.h | 357 +------------------------------------
+ 1 file changed, 1 insertion(+), 356 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 0dfbbe9a0ff2..29e6735112da 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -474,34 +474,7 @@ static struct ov5693_reg const ov5693_global_setting[] = {
+ };
+ 
+ #if ENABLE_NON_PREVIEW
+-/*
+- * 654x496 30fps 17ms VBlanking 2lane 10Bit (Scaling)
+- */
+-static struct ov5693_reg const ov5693_654x496[] = {
+-	{OV5693_8BIT, 0x3501, 0x3d},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe6},
+-	{OV5693_8BIT, 0x3709, 0xc7},
+-	{OV5693_8BIT, 0x3803, 0x00},
+-	{OV5693_8BIT, 0x3806, 0x07},
+-	{OV5693_8BIT, 0x3807, 0xa3},
+-	{OV5693_8BIT, 0x3808, 0x02},
+-	{OV5693_8BIT, 0x3809, 0x90},
+-	{OV5693_8BIT, 0x380a, 0x01},
+-	{OV5693_8BIT, 0x380b, 0xf0},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x08},
+-	{OV5693_8BIT, 0x3813, 0x02},
+-	{OV5693_8BIT, 0x3814, 0x31},
+-	{OV5693_8BIT, 0x3815, 0x31},
+-	{OV5693_8BIT, 0x3820, 0x04},
+-	{OV5693_8BIT, 0x3821, 0x1f},
+-	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
++
+ 
+ /*
+  * 1296x976 30fps 17ms VBlanking 2lane 10Bit (Scaling)
+@@ -660,62 +633,10 @@ static struct ov5693_reg const ov5693_736x496[] = {
+ };
+ #endif
+ 
+-/*
+-static struct ov5693_reg const ov5693_736x496[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe6},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3803, 0x00},
+-	{OV5693_8BIT, 0x3806, 0x07},
+-	{OV5693_8BIT, 0x3807, 0xa3},
+-	{OV5693_8BIT, 0x3808, 0x02},
+-	{OV5693_8BIT, 0x3809, 0xe0},
+-	{OV5693_8BIT, 0x380a, 0x01},
+-	{OV5693_8BIT, 0x380b, 0xf0},
+-	{OV5693_8BIT, 0x380c, 0x0d},
+-	{OV5693_8BIT, 0x380d, 0xb0},
+-	{OV5693_8BIT, 0x380e, 0x05},
+-	{OV5693_8BIT, 0x380f, 0xf2},
+-	{OV5693_8BIT, 0x3811, 0x08},
+-	{OV5693_8BIT, 0x3813, 0x02},
+-	{OV5693_8BIT, 0x3814, 0x31},
+-	{OV5693_8BIT, 0x3815, 0x31},
+-	{OV5693_8BIT, 0x3820, 0x01},
+-	{OV5693_8BIT, 0x3821, 0x1f},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-*/
+ /*
+  * 976x556 30fps 8.8ms VBlanking 2lane 10Bit (Scaling)
+  */
+ #if ENABLE_NON_PREVIEW
+-static struct ov5693_reg const ov5693_976x556[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3803, 0xf0},
+-	{OV5693_8BIT, 0x3806, 0x06},
+-	{OV5693_8BIT, 0x3807, 0xa7},
+-	{OV5693_8BIT, 0x3808, 0x03},
+-	{OV5693_8BIT, 0x3809, 0xd0},
+-	{OV5693_8BIT, 0x380a, 0x02},
+-	{OV5693_8BIT, 0x380b, 0x2C},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x10},
+-	{OV5693_8BIT, 0x3813, 0x02},
+-	{OV5693_8BIT, 0x3814, 0x11},
+-	{OV5693_8BIT, 0x3815, 0x11},
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x80},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+ 
+ /*DS from 2624x1492*/
+ static struct ov5693_reg const ov5693_1296x736[] = {
+@@ -782,40 +703,6 @@ static struct ov5693_reg const ov5693_1636p_30fps[] = {
+ };
+ #endif
+ 
+-static struct ov5693_reg const ov5693_1616x1216_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x80},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3800, 0x00},	/*{3800,3801} Array X start*/
+-	{OV5693_8BIT, 0x3801, 0x08},	/* 04 //{3800,3801} Array X start*/
+-	{OV5693_8BIT, 0x3802, 0x00},	/*{3802,3803} Array Y start*/
+-	{OV5693_8BIT, 0x3803, 0x04},	/* 00  //{3802,3803} Array Y start*/
+-	{OV5693_8BIT, 0x3804, 0x0a},	/*{3804,3805} Array X end*/
+-	{OV5693_8BIT, 0x3805, 0x37},	/* 3b  //{3804,3805} Array X end*/
+-	{OV5693_8BIT, 0x3806, 0x07},	/*{3806,3807} Array Y end*/
+-	{OV5693_8BIT, 0x3807, 0x9f},	/* a3  //{3806,3807} Array Y end*/
+-	{OV5693_8BIT, 0x3808, 0x06},	/*{3808,3809} Final output H size*/
+-	{OV5693_8BIT, 0x3809, 0x50},	/*{3808,3809} Final output H size*/
+-	{OV5693_8BIT, 0x380a, 0x04},	/*{380a,380b} Final output V size*/
+-	{OV5693_8BIT, 0x380b, 0xc0},	/*{380a,380b} Final output V size*/
+-	{OV5693_8BIT, 0x380c, 0x0a},	/*{380c,380d} HTS*/
+-	{OV5693_8BIT, 0x380d, 0x80},	/*{380c,380d} HTS*/
+-	{OV5693_8BIT, 0x380e, 0x07},	/*{380e,380f} VTS*/
+-	{OV5693_8BIT, 0x380f, 0xc0},	/* bc	//{380e,380f} VTS*/
+-	{OV5693_8BIT, 0x3810, 0x00},	/*{3810,3811} windowing X offset*/
+-	{OV5693_8BIT, 0x3811, 0x10},	/*{3810,3811} windowing X offset*/
+-	{OV5693_8BIT, 0x3812, 0x00},	/*{3812,3813} windowing Y offset*/
+-	{OV5693_8BIT, 0x3813, 0x06},	/*{3812,3813} windowing Y offset*/
+-	{OV5693_8BIT, 0x3814, 0x11},	/*X subsample control*/
+-	{OV5693_8BIT, 0x3815, 0x11},	/*Y subsample control*/
+-	{OV5693_8BIT, 0x3820, 0x00},	/*FLIP/Binnning control*/
+-	{OV5693_8BIT, 0x3821, 0x1e},	/*MIRROR control*/
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x5041, 0x84},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-
+ /*
+  * 1940x1096 30fps 8.8ms VBlanking 2lane 10bit (Scaling)
+  */
+@@ -878,37 +765,6 @@ static struct ov5693_reg const ov5693_2592x1456_30fps[] = {
+ };
+ #endif
+ 
+-static struct ov5693_reg const ov5693_2576x1456_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3800, 0x00},
+-	{OV5693_8BIT, 0x3801, 0x00},
+-	{OV5693_8BIT, 0x3802, 0x00},
+-	{OV5693_8BIT, 0x3803, 0xf0},
+-	{OV5693_8BIT, 0x3804, 0x0a},
+-	{OV5693_8BIT, 0x3805, 0x3f},
+-	{OV5693_8BIT, 0x3806, 0x06},
+-	{OV5693_8BIT, 0x3807, 0xa4},
+-	{OV5693_8BIT, 0x3808, 0x0a},
+-	{OV5693_8BIT, 0x3809, 0x10},
+-	{OV5693_8BIT, 0x380a, 0x05},
+-	{OV5693_8BIT, 0x380b, 0xb0},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x18},
+-	{OV5693_8BIT, 0x3813, 0x00},
+-	{OV5693_8BIT, 0x3814, 0x11},
+-	{OV5693_8BIT, 0x3815, 0x11},
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-
+ /*
+  * 2592x1944 30fps 0.6ms VBlanking 2lane 10Bit
+  */
+@@ -940,49 +796,6 @@ static struct ov5693_reg const ov5693_2592x1944_30fps[] = {
+ };
+ #endif
+ 
+-/*
+- * 11:9 Full FOV Output, expected FOV Res: 2346x1920
+- * ISP Effect Res: 1408x1152
+- * Sensor out: 1424x1168, DS From: 2380x1952
+- *
+- * WA: Left Offset: 8, Hor scal: 64
+- */
+-#if ENABLE_NON_PREVIEW
+-static struct ov5693_reg const ov5693_1424x1168_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x3b}, /* long exposure[15:8] */
+-	{OV5693_8BIT, 0x3502, 0x80}, /* long exposure[7:0] */
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3800, 0x00}, /* TIMING_X_ADDR_START */
+-	{OV5693_8BIT, 0x3801, 0x50}, /* 80 */
+-	{OV5693_8BIT, 0x3802, 0x00}, /* TIMING_Y_ADDR_START */
+-	{OV5693_8BIT, 0x3803, 0x02}, /* 2 */
+-	{OV5693_8BIT, 0x3804, 0x09}, /* TIMING_X_ADDR_END */
+-	{OV5693_8BIT, 0x3805, 0xdd}, /* 2525 */
+-	{OV5693_8BIT, 0x3806, 0x07}, /* TIMING_Y_ADDR_END */
+-	{OV5693_8BIT, 0x3807, 0xa1}, /* 1953 */
+-	{OV5693_8BIT, 0x3808, 0x05}, /* TIMING_X_OUTPUT_SIZE */
+-	{OV5693_8BIT, 0x3809, 0x90}, /* 1424 */
+-	{OV5693_8BIT, 0x380a, 0x04}, /* TIMING_Y_OUTPUT_SIZE */
+-	{OV5693_8BIT, 0x380b, 0x90}, /* 1168 */
+-	{OV5693_8BIT, 0x380c, 0x0a}, /* TIMING_HTS */
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07}, /* TIMING_VTS */
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3810, 0x00}, /* TIMING_ISP_X_WIN */
+-	{OV5693_8BIT, 0x3811, 0x02}, /* 2 */
+-	{OV5693_8BIT, 0x3812, 0x00}, /* TIMING_ISP_Y_WIN */
+-	{OV5693_8BIT, 0x3813, 0x00}, /* 0 */
+-	{OV5693_8BIT, 0x3814, 0x11}, /* TIME_X_INC */
+-	{OV5693_8BIT, 0x3815, 0x11}, /* TIME_Y_INC */
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_8BIT, 0x5041, 0x84}, /* scale is auto enabled */
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-#endif
+-
+ /*
+  * 3:2 Full FOV Output, expected FOV Res: 2560x1706
+  * ISP Effect Res: 720x480
+@@ -1022,173 +835,6 @@ static struct ov5693_reg const ov5693_736x496_30fps[] = {
+ 	{OV5693_TOK_TERM, 0, 0}
+ };
+ 
+-static struct ov5693_reg const ov5693_2576x1936_30fps[] = {
+-	{OV5693_8BIT, 0x3501, 0x7b},
+-	{OV5693_8BIT, 0x3502, 0x00},
+-	{OV5693_8BIT, 0x3708, 0xe2},
+-	{OV5693_8BIT, 0x3709, 0xc3},
+-	{OV5693_8BIT, 0x3803, 0x00},
+-	{OV5693_8BIT, 0x3806, 0x07},
+-	{OV5693_8BIT, 0x3807, 0xa3},
+-	{OV5693_8BIT, 0x3808, 0x0a},
+-	{OV5693_8BIT, 0x3809, 0x10},
+-	{OV5693_8BIT, 0x380a, 0x07},
+-	{OV5693_8BIT, 0x380b, 0x90},
+-	{OV5693_8BIT, 0x380c, 0x0a},
+-	{OV5693_8BIT, 0x380d, 0x80},
+-	{OV5693_8BIT, 0x380e, 0x07},
+-	{OV5693_8BIT, 0x380f, 0xc0},
+-	{OV5693_8BIT, 0x3811, 0x18},
+-	{OV5693_8BIT, 0x3813, 0x00},
+-	{OV5693_8BIT, 0x3814, 0x11},
+-	{OV5693_8BIT, 0x3815, 0x11},
+-	{OV5693_8BIT, 0x3820, 0x00},
+-	{OV5693_8BIT, 0x3821, 0x1e},
+-	{OV5693_8BIT, 0x5002, 0x00},
+-	{OV5693_TOK_TERM, 0, 0}
+-};
+-
+-static struct ov5693_resolution ov5693_res_preview[] = {
+-	{
+-		.desc = "ov5693_736x496_30fps",
+-		.width = 736,
+-		.height = 496,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_736x496_30fps,
+-	},
+-	{
+-		.desc = "ov5693_1616x1216_30fps",
+-		.width = 1616,
+-		.height = 1216,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_1616x1216_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2576,
+-		.height = 1456,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2576x1456_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2576,
+-		.height = 1936,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2576x1936_30fps,
+-	},
+-};
+-
+-#define N_RES_PREVIEW (ARRAY_SIZE(ov5693_res_preview))
+-
+-/*
+- * Disable non-preview configurations until the configuration selection is
+- * improved.
+- */
+-#if ENABLE_NON_PREVIEW
+-struct ov5693_resolution ov5693_res_still[] = {
+-	{
+-		.desc = "ov5693_736x496_30fps",
+-		.width = 736,
+-		.height = 496,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_736x496_30fps,
+-	},
+-	{
+-		.desc = "ov5693_1424x1168_30fps",
+-		.width = 1424,
+-		.height = 1168,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_1424x1168_30fps,
+-	},
+-	{
+-		.desc = "ov5693_1616x1216_30fps",
+-		.width = 1616,
+-		.height = 1216,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_1616x1216_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2592,
+-		.height = 1456,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2592x1456_30fps,
+-	},
+-	{
+-		.desc = "ov5693_5M_30fps",
+-		.width = 2592,
+-		.height = 1944,
+-		.pix_clk_freq = 160,
+-		.fps = 30,
+-		.used = 0,
+-		.pixels_per_line = 2688,
+-		.lines_per_frame = 1984,
+-		.bin_factor_x = 1,
+-		.bin_factor_y = 1,
+-		.bin_mode = 0,
+-		.regs = ov5693_2592x1944_30fps,
+-	},
+-};
+-
+-#define N_RES_STILL (ARRAY_SIZE(ov5693_res_still))
+-
+ struct ov5693_resolution ov5693_res_video[] = {
+ 	{
+ 		.desc = "ov5693_736x496_30fps",
+@@ -1343,4 +989,3 @@ struct ov5693_resolution ov5693_res_video[] = {
+ 
+ static struct ov5693_resolution *ov5693_res = ov5693_res_video;
+ static unsigned long N_RES = N_RES_VIDEO;
+-#endif
+-- 
+2.30.1
+
+From b048c8cca08fbe28af012cd2d0bd305579bc0d40 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Sun, 14 Feb 2021 14:45:58 +0000
+Subject: [PATCH] media: i2c: update set_fmt() for ov5693
+
+The set_fmt() function is a bit messy still, using home grown solutions to
+find the closest supported resolution instead of the v4l2 helpers. It also
+fails to update control ranges to account for the new mode (though this is
+moot currently as they're all the same, but the probably shouldn't be).
+
+Fix it up a little.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/i2c/ov5693.c | 148 ++++++++++---------------------------
+ drivers/media/i2c/ov5693.h |   5 +-
+ 2 files changed, 40 insertions(+), 113 deletions(-)
+
+diff --git a/drivers/media/i2c/ov5693.c b/drivers/media/i2c/ov5693.c
+index 622a7ddf4063..09c84006d5c9 100644
+--- a/drivers/media/i2c/ov5693.c
++++ b/drivers/media/i2c/ov5693.c
+@@ -753,7 +753,7 @@ static int ov5693_sensor_init(struct ov5693_device *ov5693)
+ 		return ret;
+ 	}
+ 
+-	ret = ov5693_write_reg_array(client, ov5693_res[ov5693->fmt_idx].regs);
++	ret = ov5693_write_reg_array(client, ov5693->mode->regs);
+ 	if (ret) {
+ 		dev_err(&client->dev, "ov5693 write register err.\n");
+ 		return ret;
+@@ -866,128 +866,56 @@ static int __maybe_unused ov5693_sensor_resume(struct device *dev)
+ 	return ret;
+ }
+ 
+-/*
+- * distance - calculate the distance
+- * @res: resolution
+- * @w: width
+- * @h: height
+- *
+- * Get the gap between res_w/res_h and w/h.
+- * distance = (res_w/res_h - w/h) / (w/h) * 8192
+- * res->width/height smaller than w/h wouldn't be considered.
+- * The gap of ratio larger than 1/8 wouldn't be considered.
+- * Returns the value of gap or -1 if fail.
+- */
+-#define LARGEST_ALLOWED_RATIO_MISMATCH 1024
+-static int distance(struct ov5693_resolution *res, u32 w, u32 h)
+-{
+-	int ratio;
+-	int distance;
+-
+-	if (w == 0 || h == 0 ||
+-	    res->width < w || res->height < h)
+-		return -1;
+-
+-	ratio = res->width << 13;
+-	ratio /= w;
+-	ratio *= h;
+-	ratio /= res->height;
+-
+-	distance = abs(ratio - 8192);
+-
+-	if (distance > LARGEST_ALLOWED_RATIO_MISMATCH)
+-		return -1;
+-
+-	return distance;
+-}
+-
+-/* Return the nearest higher resolution index
+- * Firstly try to find the approximate aspect ratio resolution
+- * If we find multiple same AR resolutions, choose the
+- * minimal size.
+- */
+-static int nearest_resolution_index(int w, int h)
+-{
+-	int i;
+-	int idx = -1;
+-	int dist;
+-	int min_dist = INT_MAX;
+-	int min_res_w = INT_MAX;
+-	struct ov5693_resolution *tmp_res = NULL;
+-
+-	for (i = 0; i < N_RES; i++) {
+-		tmp_res = &ov5693_res[i];
+-		dist = distance(tmp_res, w, h);
+-		if (dist == -1)
+-			continue;
+-		if (dist < min_dist) {
+-			min_dist = dist;
+-			idx = i;
+-			min_res_w = ov5693_res[i].width;
+-			continue;
+-		}
+-		if (dist == min_dist && ov5693_res[i].width < min_res_w)
+-			idx = i;
+-	}
+-
+-	return idx;
+-}
+-
+-static int get_resolution_index(int w, int h)
+-{
+-	int i;
+-
+-	for (i = 0; i < N_RES; i++) {
+-		if (w != ov5693_res[i].width)
+-			continue;
+-		if (h != ov5693_res[i].height)
+-			continue;
+-
+-		return i;
+-	}
+-
+-	return -1;
+-}
+-
+ static int ov5693_set_fmt(struct v4l2_subdev *sd,
+ 			  struct v4l2_subdev_pad_config *cfg,
+ 			  struct v4l2_subdev_format *format)
+ {
+-	struct v4l2_mbus_framefmt *fmt = &format->format;
+ 	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+-	struct i2c_client *client = v4l2_get_subdevdata(sd);
++	const struct ov5693_resolution *mode;
++	int exposure_max;
+ 	int ret = 0;
+-	int idx;
++	int hblank;
+ 
+ 	if (format->pad)
+ 		return -EINVAL;
+-	if (!fmt)
+-		return -EINVAL;
+ 
+ 	mutex_lock(&ov5693->lock);
+-	idx = nearest_resolution_index(fmt->width, fmt->height);
+-	if (idx == -1) {
+-		/* return the largest resolution */
+-		fmt->width = ov5693_res[N_RES - 1].width;
+-		fmt->height = ov5693_res[N_RES - 1].height;
+-	} else {
+-		fmt->width = ov5693_res[idx].width;
+-		fmt->height = ov5693_res[idx].height;
+-	}
+ 
+-	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
++	mode = v4l2_find_nearest_size(ov5693_res_video, ARRAY_SIZE(ov5693_res_video),
++				      width, height, format->format.width,
++				      format->format.height);
++
++	if (!mode)
++		return -EINVAL;
++
++	format->format.width = mode->width;
++	format->format.height = mode->height;
++	format->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
++
+ 	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+-		cfg->try_fmt = *fmt;
+-		ret = 0;
++		*v4l2_subdev_get_try_format(sd, cfg, format->pad) = format->format;
+ 		goto mutex_unlock;
+ 	}
+ 
+-	ov5693->fmt_idx = get_resolution_index(fmt->width, fmt->height);
+-	if (ov5693->fmt_idx == -1) {
+-		dev_err(&client->dev, "get resolution fail\n");
+-		ret = -EINVAL;
+-		goto mutex_unlock;
+-	}
++	ov5693->mode = mode;
++
++	/* Update limits and set FPS to default */
++	__v4l2_ctrl_modify_range(ov5693->ctrls.vblank,
++				 mode->lines_per_frame - mode->height,
++				 OV5693_TIMING_MAX_VTS - mode->height,
++				 1, mode->lines_per_frame - mode->height);
++	__v4l2_ctrl_s_ctrl(ov5693->ctrls.vblank,
++			   mode->lines_per_frame - mode->height);
++
++	hblank = mode->pixels_per_line - mode->width;
++	__v4l2_ctrl_modify_range(ov5693->ctrls.hblank, hblank, hblank, 1, hblank);
++
++	exposure_max = mode->lines_per_frame - 8;
++	__v4l2_ctrl_modify_range(ov5693->ctrls.exposure,
++				 ov5693->ctrls.exposure->minimum, exposure_max,
++				 ov5693->ctrls.exposure->step,
++				 ov5693->ctrls.exposure->val < exposure_max ?
++				 ov5693->ctrls.exposure->val : exposure_max);
+ 
+ mutex_unlock:
+ 	mutex_unlock(&ov5693->lock);
+@@ -1056,8 +984,8 @@ static int ov5693_get_fmt(struct v4l2_subdev *sd,
+ 	if (!fmt)
+ 		return -EINVAL;
+ 
+-	fmt->width = ov5693_res[ov5693->fmt_idx].width;
+-	fmt->height = ov5693_res[ov5693->fmt_idx].height;
++	fmt->width = ov5693->mode->width;
++	fmt->height = ov5693->mode->height;
+ 	fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ 
+ 	return 0;
+@@ -1174,7 +1102,7 @@ static int ov5693_g_frame_interval(struct v4l2_subdev *sd,
+ 	struct ov5693_device *ov5693 = to_ov5693_sensor(sd);
+ 
+ 	interval->interval.numerator = 1;
+-	interval->interval.denominator = ov5693_res[ov5693->fmt_idx].fps;
++	interval->interval.denominator = ov5693->mode->fps;
+ 
+ 	return 0;
+ }
+diff --git a/drivers/media/i2c/ov5693.h b/drivers/media/i2c/ov5693.h
+index 29e6735112da..0377853f8b2b 100644
+--- a/drivers/media/i2c/ov5693.h
++++ b/drivers/media/i2c/ov5693.h
+@@ -127,8 +127,8 @@ struct ov5693_resolution {
+ 	u8 *desc;
+ 	const struct ov5693_reg *regs;
+ 	int res;
+-	int width;
+-	int height;
++	u32 width;
++	u32 height;
+ 	int fps;
+ 	int pix_clk_freq;
+ 	u16 pixels_per_line;
+@@ -178,7 +178,6 @@ struct ov5693_device {
+ 	struct camera_sensor_platform_data *platform_data;
+ 	ktime_t timestamp_t_focus_abs;
+ 	int vt_pix_clk_freq_mhz;
+-	int fmt_idx;
+ 	int run_mode;
+ 	int otp_size;
+ 	u8 *otp_data;
+-- 
+2.30.1
+

+ 10 - 10
pkg/arch/kernel/PKGBUILD

@@ -47,16 +47,16 @@ sha256sums=('8d2c3d8fc7b382c3db6b8bacbc7785e164150b952e706350f2a5a88d42939cb4'
             '47a5c0cbe4f75e77fe64953b516a6a9f277c1dfb812e31edf5cb25feb1b3819a'
             '3fbd134c61de6f4fa86567bb0faf02c4eb2c54111b6dc45367b8f6e9ef06556e'
             '8cd2b019aac6d3807a5cdcbbbe0aad81e63193ff3e8dffd7a79d4a1421b858f6'
-            'eca6f81db4efc8d71a4f5dbaf1d6ca5b46202cb9a8ef5a7eff6b0bbe26a34a82'
-            'a10905d215739fa148870e0a8fff03f3d101f48d1f7b8028e5460adfd1b8ac25'
-            '84438dad91d0375bf1c80859081e6b10d5fe9ce3127fed654d64a56aad820b13'
-            '34aab05229d9fb782ac8dad4ac411cfd7a4f24509ba385461997e1d40000153c'
-            'e04a672f6bec169d37ee6584c5f1aa252277af1cd38b322eb70602e5bcaeae4d'
-            '8510597e396b72f898e58abcb77b6d356627720741a76d2551aeb0df4af5919f'
-            'a6653fdaa655ee61dbc8118458a844fc9261ef2f2733b8ad83adda02cfbd65b2'
-            'a9f815bc52a2610b3f0b8f878f564acab1d437ac20b7d83790cc7f67d644522f'
-            '16a0d17039426b4c5fb27fb13de0a4dc0b5fb42cacc5100c99b610b0571b8a86'
-            '3645b929503176a4ea671d47ac2b3a5bf6f2bd517b54d848d93934b049a9d0aa')
+            '3b0c98c7692bfd4c0d7d445dea512f7324ce8fb50950e34083c6bb5af4012b5f'
+            '1e9f900c6751a63fec52df04cba9ced1534b23bbaa930badf90c588bdae2dd0f'
+            '039f9d4091011fa9cc958572cbe9950b5eff42b34b00b3486bda2f85fb8833c6'
+            'c47bdb34f113e0b1dfd8b4f6e6dbf6770386b55636d082b388645a55dbc76368'
+            '4d511f15b66e0de7bd3dcd1995b4c1b5f5ff0eb9c1ed489cb0c6d83d296e660a'
+            '7eb592269821aa028e5ae94d3e8a537b1c7ede50bea3afff5f5f8450f9ee8e87'
+            '09100432b00cfa9d1af9a45aa283e7272ab5984d0ef02395838a478671eb85f6'
+            'de6b091ea03d0abf8b222ba492aeba7e2dd698461f8fed76bb824fd8159e93bf'
+            'f3fc8a8d4e0504105abf17984234252893e324ed65410c0a60521ed7efe09a20'
+            'ecad3021e4eef96f4fadb4a9794df3532ad3fdafffe64165b9b6a03b2a690494')
 
 
 export KBUILD_BUILD_HOST=archlinux