diff --git a/patches/5.14/0007-surface-gpe.patch b/patches/5.14/0007-surface-gpe.patch index 7c692a5ef..2a2b0ab18 100644 --- a/patches/5.14/0007-surface-gpe.patch +++ b/patches/5.14/0007-surface-gpe.patch @@ -1,4 +1,4 @@ -From 38526ed70383d391d4283030b3e55ee7e95c3ecd Mon Sep 17 00:00:00 2001 +From 9195131f09011fad4734431a6db63c84350b02c2 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Sun, 10 Oct 2021 00:02:44 +0200 Subject: [PATCH] platform/surface: gpe: Add support for Surface Laptop Studio @@ -46,3 +46,40 @@ index 86f6991b1215..c1775db29efb 100644 -- 2.33.1 +From 1c5316d1b388b300aca9806ad998e54858757140 Mon Sep 17 00:00:00 2001 +From: Maximilian Luz +Date: Wed, 27 Oct 2021 00:56:11 +0200 +Subject: [PATCH] platform/surface: gpe: Add support for Surface Pro 8 + +The new Surface Pro 8 uses GPEs for lid events as well. Add an entry for +that so that the lid can be used to wake the device. Note that this is a +device with a keyboard type cover, where this acts as the "lid". + +Signed-off-by: Maximilian Luz +Patchset: surface-gpe +--- + drivers/platform/surface/surface_gpe.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c +index c1775db29efb..ec66fde28e75 100644 +--- a/drivers/platform/surface/surface_gpe.c ++++ b/drivers/platform/surface/surface_gpe.c +@@ -99,6 +99,14 @@ static const struct dmi_system_id dmi_lid_device_table[] = { + }, + .driver_data = (void *)lid_device_props_l4D, + }, ++ { ++ .ident = "Surface Pro 8", ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 8"), ++ }, ++ .driver_data = (void *)lid_device_props_l4B, ++ }, + { + .ident = "Surface Book 1", + .matches = { +-- +2.33.1 + diff --git a/patches/5.14/0008-surface-button.patch b/patches/5.14/0008-surface-button.patch index 6a123849f..7c94e83b7 100644 --- a/patches/5.14/0008-surface-button.patch +++ b/patches/5.14/0008-surface-button.patch @@ -1,4 +1,4 @@ -From e3f2af18e856b37e7c3a6db14d2d615eeb1c2128 Mon Sep 17 00:00:00 2001 +From f9bd511dc3469fbda058e1ef2b21494b872a01dd Mon Sep 17 00:00:00 2001 From: Sachi King Date: Tue, 5 Oct 2021 00:05:09 +1100 Subject: [PATCH] Input: soc_button_array - support AMD variant Surface devices @@ -75,7 +75,7 @@ index cb6ec59a045d..4e8944f59def 100644 -- 2.33.1 -From a1cfed02e3bce56182725820f9f56084eae3dcfb Mon Sep 17 00:00:00 2001 +From 6a18cab1a230d9afe68ad3c8cb97fbe7e32aa8e5 Mon Sep 17 00:00:00 2001 From: Sachi King Date: Tue, 5 Oct 2021 00:22:57 +1100 Subject: [PATCH] platform/surface: surfacepro3_button: don't load on amd diff --git a/patches/5.14/0009-surface-typecover.patch b/patches/5.14/0009-surface-typecover.patch index 642fe5d94..7e3f45966 100644 --- a/patches/5.14/0009-surface-typecover.patch +++ b/patches/5.14/0009-surface-typecover.patch @@ -1,4 +1,4 @@ -From 8e838bacc584629a31d1fe9e806f4c70934941ac Mon Sep 17 00:00:00 2001 +From 32ae6b9a94c0bd0f76969c66d5e8df30f630a2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= Date: Thu, 5 Nov 2020 13:09:45 +0100 Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when diff --git a/patches/5.14/0010-cameras.patch b/patches/5.14/0010-cameras.patch index 2a847fff8..067d7cbc5 100644 --- a/patches/5.14/0010-cameras.patch +++ b/patches/5.14/0010-cameras.patch @@ -1,4 +1,4 @@ -From fdf981721e40638b83ad739886f19d2cf16652bd Mon Sep 17 00:00:00 2001 +From 5f9ae359c03aa20563a4b911715b5948d1787d90 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Mon, 5 Apr 2021 23:56:53 +0100 Subject: [PATCH] media: ipu3-cio2: Toggle sensor streaming in pm runtime ops @@ -58,7 +58,7 @@ index 47db0ee0fcbf..7bb86e246ebe 100644 -- 2.33.1 -From 746ab4a4d4a3e5a8d4bfefef2631e009c6b1610c Mon Sep 17 00:00:00 2001 +From f3aeecca5092b89384255a9eb48ce82cc8e65021 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Mon, 5 Apr 2021 23:56:54 +0100 Subject: [PATCH] media: i2c: Add support for ov5693 sensor @@ -1701,7 +1701,7 @@ index 000000000000..9499ee10f56c -- 2.33.1 -From 52976d51c123c20d78de9f3e8da86983cf794cc5 Mon Sep 17 00:00:00 2001 +From e8f847b28355a22e8e26c32eff85e292b046bc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20W=C3=BCthrich?= Date: Fri, 22 Jan 2021 20:58:13 +0100 Subject: [PATCH] cio2-bridge: Parse sensor orientation and rotation @@ -1864,7 +1864,7 @@ index dd0ffcafa489..924d99d20328 100644 -- 2.33.1 -From 72426e52272104c090518f497612823fa5d6f228 Mon Sep 17 00:00:00 2001 +From 0f7a8adbb3f750bf47b8004289a366551c56ea52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20W=C3=BCthrich?= Date: Sun, 24 Jan 2021 11:07:42 +0100 Subject: [PATCH] cio2-bridge: Use macros and add warnings @@ -1968,7 +1968,7 @@ index 924d99d20328..e1e388cc9f45 100644 -- 2.33.1 -From b88a35b977755a52d09b784ab855ae46ea860054 Mon Sep 17 00:00:00 2001 +From b284187b06f1f472abb53d58aa48e1037e05f958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20W=C3=BCthrich?= Date: Thu, 6 May 2021 07:52:44 +0200 Subject: [PATCH] cio2-bridge: Use correct dev_properties size @@ -1994,7 +1994,7 @@ index e1e388cc9f45..deaf5804f70d 100644 -- 2.33.1 -From 6d8af17b4f89af0dd6c7e0f2733e9cb82a2af059 Mon Sep 17 00:00:00 2001 +From fcdc54e85381bc02b765c50a729656c3e4c844cb Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Thu, 20 May 2021 23:31:04 +0100 Subject: [PATCH] media: i2c: Fix vertical flip in ov5693 @@ -2029,7 +2029,7 @@ index 9499ee10f56c..c558f9b48c83 100644 -- 2.33.1 -From 45e04612a1ccf86dcd2499dea550b4c1470ccb67 Mon Sep 17 00:00:00 2001 +From 58d07597d34f7a026a032e4799ff1744b728c7c8 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Fri, 9 Jul 2021 16:39:18 +0100 Subject: [PATCH] media: i2c: Add ACPI support to ov8865 @@ -2045,24 +2045,24 @@ Patchset: cameras 1 file changed, 8 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index ce50f3ea87b8..fe60cda3dea7 100644 +index ce50f3ea87b8..7626c8608f8f 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -5,6 +5,7 @@ - * Author: Paul Kocialkowski - */ - -+#include - #include +@@ -9,6 +9,7 @@ #include #include + #include ++#include + #include + #include + #include @@ -2946,6 +2947,12 @@ static const struct dev_pm_ops ov8865_pm_ops = { SET_RUNTIME_PM_OPS(ov8865_suspend, ov8865_resume, NULL) }; +static const struct acpi_device_id ov8865_acpi_match[] = { + {"INT347A"}, -+ {}, ++ { } +}; +MODULE_DEVICE_TABLE(acpi, ov8865_acpi_match); + @@ -2080,7 +2080,7 @@ index ce50f3ea87b8..fe60cda3dea7 100644 -- 2.33.1 -From 5052157f7bf862128af54b26a6ac1095f2c42a12 Mon Sep 17 00:00:00 2001 +From 8074c45d00d0e8fb8689d3d7556cb4091dc28bd9 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Sat, 10 Jul 2021 21:20:17 +0100 Subject: [PATCH] media: i2c: Fix incorrect value in comment @@ -2088,6 +2088,7 @@ Subject: [PATCH] media: i2c: Fix incorrect value in comment The PLL configuration defined here sets 72MHz (which is correct), not 80MHz. Correct the comment. +Reviewed-by: Paul Kocialkowski Signed-off-by: Daniel Scally Patchset: cameras --- @@ -2095,7 +2096,7 @@ Patchset: cameras 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index fe60cda3dea7..2ef146e7e7ef 100644 +index 7626c8608f8f..8e3f8a554452 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -713,7 +713,7 @@ static const struct ov8865_pll2_config ov8865_pll2_config_native = { @@ -2110,47 +2111,35 @@ index fe60cda3dea7..2ef146e7e7ef 100644 -- 2.33.1 -From 8493859b2a445188a220f3de138b88856325f7bd Mon Sep 17 00:00:00 2001 +From 9fa6d8e07c78ad0f3ea2b39eaef40ab92af85bad Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Sat, 10 Jul 2021 22:21:52 +0100 -Subject: [PATCH] media: i2c: Check fwnode->secondary for endpoint +Subject: [PATCH] media: i2c: Defer probe if not endpoint found The ov8865 driver is one of those that can be connected to a CIO2 device by the cio2-bridge code. This means that the absence of an endpoint for this device is not necessarily fatal, as one might be -built by the cio2-bridge when it probes. Check fwnode->secondary for -an endpoint, and defer probing if one isn't found rather than fail. +built by the cio2-bridge when it probes. Return -EPROBE_DEFER if no +endpoint is found rather than a fatal error. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) + drivers/media/i2c/ov8865.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index 2ef146e7e7ef..a3199721bbca 100644 +index 8e3f8a554452..9bc8d5d8199b 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -2779,6 +2779,7 @@ static int ov8865_resume(struct device *dev) - static int ov8865_probe(struct i2c_client *client) - { - struct device *dev = &client->dev; -+ struct fwnode_handle *fwnode = dev_fwnode(dev); - struct fwnode_handle *handle; - struct ov8865_sensor *sensor; - struct v4l2_subdev *subdev; -@@ -2795,11 +2796,11 @@ static int ov8865_probe(struct i2c_client *client) - +@@ -2796,10 +2796,8 @@ static int ov8865_probe(struct i2c_client *client) /* Graph Endpoint */ -- handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); + handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); - if (!handle) { - dev_err(dev, "unable to find endpoint node\n"); - return -EINVAL; - } -+ handle = fwnode_graph_get_next_endpoint(fwnode, NULL); -+ if (!handle && !IS_ERR_OR_NULL(fwnode->secondary)) -+ handle = fwnode_graph_get_next_endpoint(fwnode->secondary, NULL); + if (!handle) + return -EPROBE_DEFER; @@ -2159,7 +2148,7 @@ index 2ef146e7e7ef..a3199721bbca 100644 -- 2.33.1 -From 2843edd4ac81db6afea5d4922be083fa8d9bceb2 Mon Sep 17 00:00:00 2001 +From e6e0c9c51eeac9c9d6caecf7b5819e6dafb03885 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Sat, 10 Jul 2021 22:00:25 +0100 Subject: [PATCH] media: i2c: Support 19.2MHz input clock in ov8865 @@ -2173,11 +2162,11 @@ during probe and set that rate if one is found. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 157 +++++++++++++++++++++++++++---------- - 1 file changed, 114 insertions(+), 43 deletions(-) + drivers/media/i2c/ov8865.c | 186 +++++++++++++++++++++++++++---------- + 1 file changed, 135 insertions(+), 51 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index a3199721bbca..53e6bcbe18d6 100644 +index 9bc8d5d8199b..4ddc1b277cc0 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -21,10 +21,6 @@ @@ -2191,17 +2180,54 @@ index a3199721bbca..53e6bcbe18d6 100644 /* Register definitions */ /* System */ -@@ -665,6 +661,9 @@ struct ov8865_sensor { +@@ -567,6 +563,25 @@ struct ov8865_sclk_config { + unsigned int sclk_div; + }; + ++struct ov8865_pll_configs { ++ const struct ov8865_pll1_config *pll1_config; ++ const struct ov8865_pll2_config *pll2_config_native; ++ const struct ov8865_pll2_config *pll2_config_binning; ++}; ++ ++/* Clock rate */ ++ ++enum extclk_rate { ++ OV8865_19_2_MHZ, ++ OV8865_24_MHZ, ++ OV8865_NUM_SUPPORTED_RATES ++}; ++ ++static const unsigned long supported_extclk_rates[] = { ++ [OV8865_19_2_MHZ] = 19200000, ++ [OV8865_24_MHZ] = 24000000, ++}; ++ + /* + * General formulas for (array-centered) mode calculation: + * - photo_array_width = 3296 +@@ -635,9 +650,7 @@ struct ov8865_mode { + + struct v4l2_fract frame_interval; + +- const struct ov8865_pll1_config *pll1_config; +- const struct ov8865_pll2_config *pll2_config; +- const struct ov8865_sclk_config *sclk_config; ++ bool pll2_binning; + + const struct ov8865_register_value *register_values; + unsigned int register_values_count; +@@ -665,6 +678,9 @@ struct ov8865_sensor { struct regulator *avdd; struct regulator *dvdd; struct regulator *dovdd; + + unsigned long extclk_rate; -+ unsigned int extclk_rate_idx; ++ const struct ov8865_pll_configs *pll_configs; struct clk *extclk; struct v4l2_fwnode_endpoint endpoint; -@@ -680,49 +679,83 @@ struct ov8865_sensor { +@@ -680,43 +696,70 @@ struct ov8865_sensor { /* Static definitions */ /* @@ -2219,8 +2245,7 @@ index a3199721bbca..53e6bcbe18d6 100644 - .sys_pre_div = 1, - .sys_div = 2, + -+static const struct ov8865_pll1_config ov8865_pll1_configs_native[] = { -+ { /* 19.2 MHz input clock */ ++static const struct ov8865_pll1_config ov8865_pll1_config_native_19_2mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 2, + .pll_mul = 75, @@ -2229,8 +2254,9 @@ index a3199721bbca..53e6bcbe18d6 100644 + .pclk_div = 1, + .sys_pre_div = 1, + .sys_div = 2, -+ }, -+ { /* 24MHz input clock */ ++}; ++ ++static const struct ov8865_pll1_config ov8865_pll1_config_native_24mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 0, + .pll_mul = 30, @@ -2239,7 +2265,6 @@ index a3199721bbca..53e6bcbe18d6 100644 + .pclk_div = 1, + .sys_pre_div = 1, + .sys_div = 2, -+ }, }; /* @@ -2255,25 +2280,22 @@ index a3199721bbca..53e6bcbe18d6 100644 - .dac_div = 2, - .sys_pre_div = 5, - .sys_div = 0, -+static const struct ov8865_pll2_config ov8865_pll2_configs_native[] = { -+ /* 19.2MHz input clock */ -+ { ++static const struct ov8865_pll2_config ov8865_pll2_config_native_19_2mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 5, + .pll_mul = 75, + .dac_div = 1, + .sys_pre_div = 1, + .sys_div = 3, -+ }, -+ /* 24MHz input clock */ -+ { ++}; ++ ++static const struct ov8865_pll2_config ov8865_pll2_config_native_24mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 0, + .pll_mul = 30, + .dac_div = 2, + .sys_pre_div = 5, + .sys_div = 0, -+ } }; /* @@ -2283,87 +2305,88 @@ index a3199721bbca..53e6bcbe18d6 100644 */ -static const struct ov8865_pll2_config ov8865_pll2_config_binning = { -+static const struct ov8865_pll2_config ov8865_pll2_configs_binning[] = { -+ /* 19.2MHz input clock */ -+ { ++static const struct ov8865_pll2_config ov8865_pll2_config_binning_19_2mhz = { + .pll_pre_div_half = 1, + .pll_pre_div = 2, + .pll_mul = 75, + .dac_div = 2, + .sys_pre_div = 10, + .sys_div = 0, -+ }, -+ /* 24MHz input clock */ -+ { ++}; ++ ++static const struct ov8865_pll2_config ov8865_pll2_config_binning_24mhz = { .pll_pre_div_half = 1, .pll_pre_div = 0, .pll_mul = 30, - .dac_div = 2, - .sys_pre_div = 10, +@@ -725,6 +768,23 @@ static const struct ov8865_pll2_config ov8865_pll2_config_binning = { .sys_div = 0, -+ } }; ++static struct ov8865_pll_configs ov8865_pll_configs_19_2mhz = { ++ .pll1_config = &ov8865_pll1_config_native_19_2mhz, ++ .pll2_config_native = &ov8865_pll2_config_native_19_2mhz, ++ .pll2_config_binning = &ov8865_pll2_config_binning_19_2mhz, ++}; ++ ++static struct ov8865_pll_configs ov8865_pll_configs_24mhz = { ++ .pll1_config = &ov8865_pll1_config_native_24mhz, ++ .pll2_config_native = &ov8865_pll2_config_native_24mhz, ++ .pll2_config_binning = &ov8865_pll2_config_binning_24mhz, ++}; ++ ++static const struct ov8865_pll_configs *ov8865_pll_configs[] = { ++ &ov8865_pll_configs_19_2mhz, ++ &ov8865_pll_configs_24mhz, ++}; ++ static const struct ov8865_sclk_config ov8865_sclk_config_native = { -@@ -934,8 +967,8 @@ static const struct ov8865_mode ov8865_modes[] = { + .sys_sel = 1, + .sclk_sel = 0, +@@ -934,9 +994,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 30 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_native, -+ .pll1_config = ov8865_pll1_configs_native, -+ .pll2_config = ov8865_pll2_configs_native, - .sclk_config = &ov8865_sclk_config_native, +- .sclk_config = &ov8865_sclk_config_native, ++ .pll2_binning = false, /* Registers */ -@@ -990,8 +1023,8 @@ static const struct ov8865_mode ov8865_modes[] = { + .register_values = ov8865_register_values_native, +@@ -990,9 +1048,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 30 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_native, -+ .pll1_config = ov8865_pll1_configs_native, -+ .pll2_config = ov8865_pll2_configs_native, - .sclk_config = &ov8865_sclk_config_native, +- .sclk_config = &ov8865_sclk_config_native, ++ .pll2_binning = false, /* Registers */ -@@ -1050,8 +1083,8 @@ static const struct ov8865_mode ov8865_modes[] = { + .register_values = ov8865_register_values_native, +@@ -1050,9 +1106,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 30 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_binning, -+ .pll1_config = ov8865_pll1_configs_native, -+ .pll2_config = ov8865_pll2_configs_binning, - .sclk_config = &ov8865_sclk_config_native, +- .sclk_config = &ov8865_sclk_config_native, ++ .pll2_binning = true, /* Registers */ -@@ -1116,8 +1149,8 @@ static const struct ov8865_mode ov8865_modes[] = { + .register_values = ov8865_register_values_binning, +@@ -1116,9 +1170,7 @@ static const struct ov8865_mode ov8865_modes[] = { .frame_interval = { 1, 90 }, /* PLL */ - .pll1_config = &ov8865_pll1_config_native, - .pll2_config = &ov8865_pll2_config_binning, -+ .pll1_config = ov8865_pll1_configs_native, -+ .pll2_config = ov8865_pll2_configs_binning, - .sclk_config = &ov8865_sclk_config_native, +- .sclk_config = &ov8865_sclk_config_native, ++ .pll2_binning = true, /* Registers */ -@@ -1266,6 +1299,13 @@ static const struct ov8865_register_value ov8865_init_sequence[] = { - { 0x4503, 0x10 }, - }; - -+/* Clock rate */ -+ -+static const unsigned long supported_extclk_rates[] = { -+ 19200000, -+ 24000000, -+}; -+ - static const s64 ov8865_link_freq_menu[] = { - 360000000, - }; -@@ -1513,12 +1553,11 @@ static int ov8865_isp_configure(struct ov8865_sensor *sensor) + .register_values = ov8865_register_values_binning, +@@ -1513,12 +1565,11 @@ static int ov8865_isp_configure(struct ov8865_sensor *sensor) static unsigned long ov8865_mode_pll1_rate(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { @@ -2374,12 +2397,12 @@ index a3199721bbca..53e6bcbe18d6 100644 - extclk_rate = clk_get_rate(sensor->extclk); - pll1_rate = extclk_rate * config->pll_mul / config->pll_pre_div_half; -+ config = &mode->pll1_config[sensor->extclk_rate_idx]; ++ config = sensor->pll_configs->pll1_config; + pll1_rate = sensor->extclk_rate * config->pll_mul / config->pll_pre_div_half; switch (config->pll_pre_div) { case 0: -@@ -1552,10 +1591,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor, +@@ -1552,10 +1603,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor, const struct ov8865_mode *mode, u32 mbus_code) { @@ -2388,12 +2411,12 @@ index a3199721bbca..53e6bcbe18d6 100644 u8 value; int ret; -+ config = &mode->pll1_config[sensor->extclk_rate_idx]; ++ config = sensor->pll_configs->pll1_config; + switch (mbus_code) { case MEDIA_BUS_FMT_SBGGR10_1X10: value = OV8865_MIPI_BIT_SEL(10); -@@ -1622,9 +1663,11 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor, +@@ -1622,9 +1675,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor, static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { @@ -2401,12 +2424,22 @@ index a3199721bbca..53e6bcbe18d6 100644 + const struct ov8865_pll2_config *config; int ret; -+ config = &mode->pll2_config[sensor->extclk_rate_idx]; ++ config = mode->pll2_binning ? sensor->pll_configs->pll2_config_binning : ++ sensor->pll_configs->pll2_config_native; + ret = ov8865_write(sensor, OV8865_PLL_CTRL12_REG, OV8865_PLL_CTRL12_PRE_DIV_HALF(config->pll_pre_div_half) | OV8865_PLL_CTRL12_DAC_DIV(config->dac_div)); -@@ -2053,9 +2096,11 @@ static int ov8865_mode_configure(struct ov8865_sensor *sensor, +@@ -1658,7 +1714,7 @@ static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor, + static int ov8865_mode_sclk_configure(struct ov8865_sensor *sensor, + const struct ov8865_mode *mode) + { +- const struct ov8865_sclk_config *config = mode->sclk_config; ++ const struct ov8865_sclk_config *config = &ov8865_sclk_config_native; + int ret; + + ret = ov8865_write(sensor, OV8865_CLK_SEL0_REG, +@@ -2053,9 +2109,11 @@ static int ov8865_mode_configure(struct ov8865_sensor *sensor, static unsigned long ov8865_mode_mipi_clk_rate(struct ov8865_sensor *sensor, const struct ov8865_mode *mode) { @@ -2414,12 +2447,12 @@ index a3199721bbca..53e6bcbe18d6 100644 + const struct ov8865_pll1_config *config; unsigned long pll1_rate; -+ config = &mode->pll1_config[sensor->extclk_rate_idx]; ++ config = sensor->pll_configs->pll1_config; + pll1_rate = ov8865_mode_pll1_rate(sensor, mode); return pll1_rate / config->m_div / 2; -@@ -2784,7 +2829,8 @@ static int ov8865_probe(struct i2c_client *client) +@@ -2783,7 +2841,8 @@ static int ov8865_probe(struct i2c_client *client) struct ov8865_sensor *sensor; struct v4l2_subdev *subdev; struct media_pad *pad; @@ -2429,7 +2462,7 @@ index a3199721bbca..53e6bcbe18d6 100644 int ret; sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL); -@@ -2861,13 +2907,38 @@ static int ov8865_probe(struct i2c_client *client) +@@ -2858,13 +2917,38 @@ static int ov8865_probe(struct i2c_client *client) goto error_endpoint; } @@ -2439,11 +2472,11 @@ index a3199721bbca..53e6bcbe18d6 100644 + /* + * We could have either a 24MHz or 19.2MHz clock rate. Check for a + * clock-frequency property and if found, set that rate. This should -+ * cover ACPI case. If the system uses devicetree then the configured -+ * rate should already be set, so we'll have to check it. ++ * cover the ACPI case. If the system uses devicetree then the ++ * configured rate should already be set, so we'll have to check it. + */ -+ -+ ret = fwnode_property_read_u32(fwnode, "clock-frequency", &rate); ++ ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency", ++ &rate); + if (!ret) { + ret = clk_set_rate(sensor->extclk, rate); + if (ret) { @@ -2466,7 +2499,7 @@ index a3199721bbca..53e6bcbe18d6 100644 goto error_endpoint; } -+ sensor->extclk_rate_idx = i; ++ sensor->pll_configs = ov8865_pll_configs[i]; + /* Subdev, entity and pad */ @@ -2474,22 +2507,22 @@ index a3199721bbca..53e6bcbe18d6 100644 -- 2.33.1 -From 5f7dc24434b811b81d3d44df5105ff109e0b8f7e Mon Sep 17 00:00:00 2001 +From e2475b63ceaab19f1e2b9092c3abefd933b140c9 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Sat, 10 Jul 2021 22:19:10 +0100 Subject: [PATCH] media: i2c: Add .get_selection() support to ov8865 -The ov8865 drivers media pad ops currently does not include +The ov8865 driver's v4l2_subdev_pad_ops currently does not include .get_selection() - add support for that callback. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 61 ++++++++++++++++++++++++++++++++++++++ - 1 file changed, 61 insertions(+) + drivers/media/i2c/ov8865.c | 64 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index 53e6bcbe18d6..2f487c25ed56 100644 +index 4ddc1b277cc0..0f2776390a8e 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -450,6 +450,15 @@ @@ -2508,7 +2541,7 @@ index 53e6bcbe18d6..2f487c25ed56 100644 /* Macros */ #define ov8865_subdev_sensor(s) \ -@@ -2743,12 +2752,64 @@ static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev, +@@ -2756,12 +2765,67 @@ static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev, return 0; } @@ -2517,15 +2550,17 @@ index 53e6bcbe18d6..2f487c25ed56 100644 + struct v4l2_subdev_state *state, unsigned int pad, + enum v4l2_subdev_format_whence which, struct v4l2_rect *r) +{ ++ const struct ov8865_mode *mode = sensor->state.mode; ++ + switch (which) { + case V4L2_SUBDEV_FORMAT_TRY: + *r = *v4l2_subdev_get_try_crop(&sensor->subdev, state, pad); + break; + case V4L2_SUBDEV_FORMAT_ACTIVE: -+ r->height = sensor->state.mode->output_size_y; -+ r->width = sensor->state.mode->output_size_x; -+ r->top = (OV8865_NATIVE_HEIGHT - sensor->state.mode->output_size_y) / 2; -+ r->left = (OV8865_NATIVE_WIDTH - sensor->state.mode->output_size_x) / 2; ++ r->height = mode->output_size_y; ++ r->width = mode->output_size_x; ++ r->top = (OV8865_NATIVE_HEIGHT - mode->output_size_y) / 2; ++ r->left = (OV8865_NATIVE_WIDTH - mode->output_size_x) / 2; + break; + } +} @@ -2570,13 +2605,14 @@ index 53e6bcbe18d6..2f487c25ed56 100644 .enum_frame_size = ov8865_enum_frame_size, .enum_frame_interval = ov8865_enum_frame_interval, + .get_selection = ov8865_get_selection, ++ .set_selection = ov8865_get_selection, }; static const struct v4l2_subdev_ops ov8865_subdev_ops = { -- 2.33.1 -From 8e56b0ca382f2905226824df11217998411588d3 Mon Sep 17 00:00:00 2001 +From ce8ca98a4c3e81c3952d22a6fd22c01eeb450815 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Sat, 10 Jul 2021 22:34:43 +0100 Subject: [PATCH] media: i2c: Switch control to V4L2_CID_ANALOGUE_GAIN @@ -2585,17 +2621,18 @@ The V4L2_CID_GAIN control for this driver configures registers that the datasheet specifies as analogue gain. Switch the control's ID to V4L2_CID_ANALOGUE_GAIN. +Reviewed-by: Paul Kocialkowski Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) + drivers/media/i2c/ov8865.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index 2f487c25ed56..b91c952b6ef9 100644 +index 0f2776390a8e..a832938c33b6 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -2137,7 +2137,7 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure) +@@ -2150,7 +2150,7 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure) /* Gain */ @@ -2604,7 +2641,7 @@ index 2f487c25ed56..b91c952b6ef9 100644 { int ret; -@@ -2447,8 +2447,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) +@@ -2460,8 +2460,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) if (ret) return ret; break; @@ -2615,19 +2652,20 @@ index 2f487c25ed56..b91c952b6ef9 100644 if (ret) return ret; break; -@@ -2493,7 +2493,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2506,7 +2506,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Gain */ - v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 128, 8191, 128, 128); -+ v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 8191, 128, 128); ++ v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 8191, 128, ++ 128); /* White Balance */ -- 2.33.1 -From 0b99e9b52d10d7051670e57e4ff44b03ecdb7779 Mon Sep 17 00:00:00 2001 +From 09cfff77db6e3f2131acf00be6116b43d4d1eb0d Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Mon, 12 Jul 2021 22:54:56 +0100 Subject: [PATCH] media: i2c: Add vblank control to ov8865 @@ -2641,7 +2679,7 @@ Patchset: cameras 1 file changed, 34 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index b91c952b6ef9..4430115607a4 100644 +index a832938c33b6..f741c0713ca4 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c @@ -183,6 +183,8 @@ @@ -2653,7 +2691,7 @@ index b91c952b6ef9..4430115607a4 100644 #define OV8865_OFFSET_X_H_REG 0x3810 #define OV8865_OFFSET_X_H(v) (((v) & GENMASK(15, 8)) >> 8) #define OV8865_OFFSET_X_L_REG 0x3811 -@@ -658,6 +660,7 @@ struct ov8865_state { +@@ -675,6 +677,7 @@ struct ov8865_state { struct ov8865_ctrls { struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; @@ -2661,7 +2699,7 @@ index b91c952b6ef9..4430115607a4 100644 struct v4l2_ctrl_handler handler; }; -@@ -2212,6 +2215,20 @@ static int ov8865_test_pattern_configure(struct ov8865_sensor *sensor, +@@ -2225,6 +2228,20 @@ static int ov8865_test_pattern_configure(struct ov8865_sensor *sensor, ov8865_test_pattern_bits[index]); } @@ -2682,7 +2720,7 @@ index b91c952b6ef9..4430115607a4 100644 /* State */ static int ov8865_state_mipi_configure(struct ov8865_sensor *sensor, -@@ -2463,6 +2480,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) +@@ -2476,6 +2493,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) case V4L2_CID_TEST_PATTERN: index = (unsigned int)ctrl->val; return ov8865_test_pattern_configure(sensor, index); @@ -2691,7 +2729,7 @@ index b91c952b6ef9..4430115607a4 100644 default: return -EINVAL; } -@@ -2479,6 +2498,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2492,6 +2511,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) struct ov8865_ctrls *ctrls = &sensor->ctrls; struct v4l2_ctrl_handler *handler = &ctrls->handler; const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; @@ -2700,7 +2738,7 @@ index b91c952b6ef9..4430115607a4 100644 int ret; v4l2_ctrl_handler_init(handler, 32); -@@ -2514,6 +2535,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2528,6 +2549,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) ARRAY_SIZE(ov8865_test_pattern_menu) - 1, 0, 0, ov8865_test_pattern_menu); @@ -2714,7 +2752,7 @@ index b91c952b6ef9..4430115607a4 100644 /* MIPI CSI-2 */ ctrls->link_freq = -@@ -2694,6 +2722,10 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, +@@ -2708,6 +2736,10 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, sensor->state.mbus_code != mbus_code) ret = ov8865_state_configure(sensor, mode, mbus_code); @@ -2725,7 +2763,7 @@ index b91c952b6ef9..4430115607a4 100644 complete: mutex_unlock(&sensor->mutex); -@@ -3021,6 +3053,8 @@ static int ov8865_probe(struct i2c_client *client) +@@ -3035,6 +3067,8 @@ static int ov8865_probe(struct i2c_client *client) /* Sensor */ @@ -2737,7 +2775,7 @@ index b91c952b6ef9..4430115607a4 100644 -- 2.33.1 -From 2d2686057aad3dd590a37d19e06d5b5501f174e3 Mon Sep 17 00:00:00 2001 +From c073b4c010146a85c44533dac3e8e1dea0fc5ad4 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 13 Jul 2021 23:40:33 +0100 Subject: [PATCH] media: i2c: Add hblank control to ov8865 @@ -2752,10 +2790,10 @@ Patchset: cameras 1 file changed, 14 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index 4430115607a4..e9b5f4d8e79b 100644 +index f741c0713ca4..4b18cc80f985 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -660,6 +660,7 @@ struct ov8865_state { +@@ -677,6 +677,7 @@ struct ov8865_state { struct ov8865_ctrls { struct v4l2_ctrl *link_freq; struct v4l2_ctrl *pixel_rate; @@ -2763,7 +2801,7 @@ index 4430115607a4..e9b5f4d8e79b 100644 struct v4l2_ctrl *vblank; struct v4l2_ctrl_handler handler; -@@ -2500,6 +2501,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2513,6 +2514,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; const struct ov8865_mode *mode = sensor->state.mode; unsigned int vblank_max, vblank_def; @@ -2771,11 +2809,11 @@ index 4430115607a4..e9b5f4d8e79b 100644 int ret; v4l2_ctrl_handler_init(handler, 32); -@@ -2536,6 +2538,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2550,6 +2552,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) 0, 0, ov8865_test_pattern_menu); /* Blanking */ -+ hblank = mode->hts < mode->output_size_x ? 0 : mode->hts - mode->output_size_x; ++ hblank = mode->hts - mode->output_size_x; + ctrls->hblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HBLANK, hblank, + hblank, 1, hblank); + @@ -2785,7 +2823,7 @@ index 4430115607a4..e9b5f4d8e79b 100644 vblank_max = OV8865_TIMING_MAX_VTS - mode->output_size_y; vblank_def = mode->vts - mode->output_size_y; ctrls->vblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_VBLANK, -@@ -2682,6 +2691,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, +@@ -2696,6 +2705,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, struct v4l2_mbus_framefmt *mbus_format = &format->format; const struct ov8865_mode *mode; u32 mbus_code = 0; @@ -2793,11 +2831,11 @@ index 4430115607a4..e9b5f4d8e79b 100644 unsigned int index; int ret = 0; -@@ -2726,6 +2736,10 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, +@@ -2740,6 +2750,10 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, OV8865_TIMING_MAX_VTS - mode->output_size_y, 1, mode->vts - mode->output_size_y); -+ hblank = mode->hts < mode->output_size_x ? 0 : mode->hts - mode->output_size_x; ++ hblank = mode->hts - mode->output_size_x; + __v4l2_ctrl_modify_range(sensor->ctrls.hblank, hblank, hblank, 1, + hblank); + @@ -2807,7 +2845,183 @@ index 4430115607a4..e9b5f4d8e79b 100644 -- 2.33.1 -From 3a3b7c516592432ca9f58a456e5529f4af3bb366 Mon Sep 17 00:00:00 2001 +From 8e28b45790495280ee24c11e2faa08ba120ed29f Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Wed, 20 Oct 2021 22:43:54 +0100 +Subject: [PATCH] media: i2c: Update HTS values in ov8865 + +The HTS values for some of the modes in the ov8865 driver are a bit +unusual, coming in lower than the output_size_x is set to. It seems +like they might be calculated to fit the desired framerate into a +configuration with just two data lanes. To bring this more in line +with expected behaviour, raise the HTS values above the output_size_x. + +The corollary of that change is that the hardcoded frame intervals +against the modes no longer make sense, so remove those entirely. +Update the .g/s_frame_interval() callbacks to calculate the frame +interval based on the current mode and the vblank and hblank settings +plus the number of data lanes detected from firmware. + +The implementation of the .enum_frame_interval() callback is no longer +suitable since the possible frame rate is now a continuous range depending +on the vblank control setting, so remove that callback entirely. + +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/media/i2c/ov8865.c | 65 +++++++------------------------------- + 1 file changed, 11 insertions(+), 54 deletions(-) + +diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c +index 4b18cc80f985..1b8674152750 100644 +--- a/drivers/media/i2c/ov8865.c ++++ b/drivers/media/i2c/ov8865.c +@@ -659,8 +659,6 @@ struct ov8865_mode { + unsigned int blc_anchor_right_start; + unsigned int blc_anchor_right_end; + +- struct v4l2_fract frame_interval; +- + bool pll2_binning; + + const struct ov8865_register_value *register_values; +@@ -964,7 +962,7 @@ static const struct ov8865_mode ov8865_modes[] = { + { + /* Horizontal */ + .output_size_x = 3264, +- .hts = 1944, ++ .hts = 3888, + + /* Vertical */ + .output_size_y = 2448, +@@ -1003,9 +1001,6 @@ static const struct ov8865_mode ov8865_modes[] = { + .blc_anchor_right_start = 1984, + .blc_anchor_right_end = 2239, + +- /* Frame Interval */ +- .frame_interval = { 1, 30 }, +- + /* PLL */ + .pll2_binning = false, + +@@ -1018,11 +1013,11 @@ static const struct ov8865_mode ov8865_modes[] = { + { + /* Horizontal */ + .output_size_x = 3264, +- .hts = 2582, ++ .hts = 3888, + + /* Vertical */ + .output_size_y = 1836, +- .vts = 2002, ++ .vts = 2470, + + .size_auto = true, + .size_auto_boundary_x = 8, +@@ -1057,9 +1052,6 @@ static const struct ov8865_mode ov8865_modes[] = { + .blc_anchor_right_start = 1984, + .blc_anchor_right_end = 2239, + +- /* Frame Interval */ +- .frame_interval = { 1, 30 }, +- + /* PLL */ + .pll2_binning = false, + +@@ -1115,9 +1107,6 @@ static const struct ov8865_mode ov8865_modes[] = { + .blc_anchor_right_start = 992, + .blc_anchor_right_end = 1119, + +- /* Frame Interval */ +- .frame_interval = { 1, 30 }, +- + /* PLL */ + .pll2_binning = true, + +@@ -1179,9 +1168,6 @@ static const struct ov8865_mode ov8865_modes[] = { + .blc_anchor_right_start = 992, + .blc_anchor_right_end = 1119, + +- /* Frame Interval */ +- .frame_interval = { 1, 90 }, +- + /* PLL */ + .pll2_binning = true, + +@@ -2628,11 +2614,18 @@ static int ov8865_g_frame_interval(struct v4l2_subdev *subdev, + { + struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev); + const struct ov8865_mode *mode; ++ unsigned int framesize; ++ unsigned int fps; + + mutex_lock(&sensor->mutex); + + mode = sensor->state.mode; +- interval->interval = mode->frame_interval; ++ framesize = mode->hts * (mode->output_size_y + ++ sensor->ctrls.vblank->val); ++ fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize); ++ ++ interval->interval.numerator = 1; ++ interval->interval.denominator = fps; + + mutex_unlock(&sensor->mutex); + +@@ -2777,41 +2770,6 @@ static int ov8865_enum_frame_size(struct v4l2_subdev *subdev, + return 0; + } + +-static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev, +- struct v4l2_subdev_state *sd_state, +- struct v4l2_subdev_frame_interval_enum *interval_enum) +-{ +- const struct ov8865_mode *mode = NULL; +- unsigned int mode_index; +- unsigned int interval_index; +- +- if (interval_enum->index > 0) +- return -EINVAL; +- /* +- * Multiple modes with the same dimensions may have different frame +- * intervals, so look up each relevant mode. +- */ +- for (mode_index = 0, interval_index = 0; +- mode_index < ARRAY_SIZE(ov8865_modes); mode_index++) { +- mode = &ov8865_modes[mode_index]; +- +- if (mode->output_size_x == interval_enum->width && +- mode->output_size_y == interval_enum->height) { +- if (interval_index == interval_enum->index) +- break; +- +- interval_index++; +- } +- } +- +- if (mode_index == ARRAY_SIZE(ov8865_modes)) +- return -EINVAL; +- +- interval_enum->interval = mode->frame_interval; +- +- return 0; +-} +- + static void + __ov8865_get_pad_crop(struct ov8865_sensor *sensor, + struct v4l2_subdev_state *state, unsigned int pad, +@@ -2870,7 +2828,6 @@ static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = { + .get_fmt = ov8865_get_fmt, + .set_fmt = ov8865_set_fmt, + .enum_frame_size = ov8865_enum_frame_size, +- .enum_frame_interval = ov8865_enum_frame_interval, + .get_selection = ov8865_get_selection, + .set_selection = ov8865_get_selection, + }; +-- +2.33.1 + +From 68dddf4d236c636adcf2ae73a9767b6893d1c52f Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Tue, 13 Jul 2021 23:43:17 +0100 Subject: [PATCH] media: i2c: cap exposure at height + vblank in ov8865 @@ -2819,14 +3033,14 @@ the new cap. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 24 ++++++++++++++++++++++-- - 1 file changed, 22 insertions(+), 2 deletions(-) + drivers/media/i2c/ov8865.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index e9b5f4d8e79b..893cc58dc265 100644 +index 1b8674152750..99548ad15dcd 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -662,6 +662,7 @@ struct ov8865_ctrls { +@@ -677,6 +677,7 @@ struct ov8865_ctrls { struct v4l2_ctrl *pixel_rate; struct v4l2_ctrl *hblank; struct v4l2_ctrl *vblank; @@ -2834,7 +3048,7 @@ index e9b5f4d8e79b..893cc58dc265 100644 struct v4l2_ctrl_handler handler; }; -@@ -2455,6 +2456,18 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) +@@ -2454,6 +2455,19 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl) unsigned int index; int ret; @@ -2847,13 +3061,14 @@ index e9b5f4d8e79b..893cc58dc265 100644 + sensor->ctrls.exposure->minimum, + exposure_max, + sensor->ctrls.exposure->step, -+ min(sensor->ctrls.exposure->val, exposure_max)); ++ min(sensor->ctrls.exposure->val, ++ exposure_max)); + } + /* Wait for the sensor to be on before setting controls. */ if (pm_runtime_suspended(sensor->dev)) return 0; -@@ -2511,8 +2524,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2510,8 +2524,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Exposure */ @@ -2864,7 +3079,7 @@ index e9b5f4d8e79b..893cc58dc265 100644 /* Gain */ -@@ -2693,6 +2706,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, +@@ -2700,6 +2714,7 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, u32 mbus_code = 0; unsigned int hblank; unsigned int index; @@ -2872,7 +3087,7 @@ index e9b5f4d8e79b..893cc58dc265 100644 int ret = 0; mutex_lock(&sensor->mutex); -@@ -2740,6 +2754,12 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, +@@ -2747,6 +2762,13 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev, __v4l2_ctrl_modify_range(sensor->ctrls.hblank, hblank, hblank, 1, hblank); @@ -2880,7 +3095,8 @@ index e9b5f4d8e79b..893cc58dc265 100644 + __v4l2_ctrl_modify_range(sensor->ctrls.exposure, + sensor->ctrls.exposure->minimum, exposure_max, + sensor->ctrls.exposure->step, -+ min(sensor->ctrls.exposure->val, exposure_max)); ++ min(sensor->ctrls.exposure->val, ++ exposure_max)); + complete: mutex_unlock(&sensor->mutex); @@ -2888,281 +3104,52 @@ index e9b5f4d8e79b..893cc58dc265 100644 -- 2.33.1 -From 65ec8959150d267a224b79596230ca02cfe8e6c3 Mon Sep 17 00:00:00 2001 +From bea0858391d47c156b60dd9661231f96d1afec19 Mon Sep 17 00:00:00 2001 From: Daniel Scally -Date: Wed, 14 Jul 2021 18:05:44 +0100 -Subject: [PATCH] media: i2c: Remove unused macros from ov8865 +Date: Fri, 16 Jul 2021 22:56:15 +0100 +Subject: [PATCH] media: i2c: Add controls from fwnode to ov8865 -There are a number of macros defined in this driver that aren't actually -used within it. There's a lot of macros defined in total, so removing the -unused ones helps make it a bit less busy. +Add V4L2_CID_CAMERA_ORIENTATION and V4L2_CID_CAMERA_SENSOR_ROTATION +controls to the ov8865 driver by attempting to parse them from firmware. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 137 +------------------------------------ - 1 file changed, 1 insertion(+), 136 deletions(-) + drivers/media/i2c/ov8865.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index 893cc58dc265..fb81b822987d 100644 +index 99548ad15dcd..dfb5095ef16b 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -46,8 +46,6 @@ - #define OV8865_PLL_CTRL6_REG 0x306 - #define OV8865_PLL_CTRL6_SYS_DIV(v) (((v) - 1) & BIT(0)) +@@ -2513,6 +2513,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) + struct v4l2_ctrl_handler *handler = &ctrls->handler; + const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; + const struct ov8865_mode *mode = sensor->state.mode; ++ struct v4l2_fwnode_device_properties props; + unsigned int vblank_max, vblank_def; + unsigned int hblank; + int ret; +@@ -2576,6 +2577,15 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) + v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1, + INT_MAX, 1, 1); --#define OV8865_PLL_CTRL8_REG 0x308 --#define OV8865_PLL_CTRL9_REG 0x309 - #define OV8865_PLL_CTRLA_REG 0x30a - #define OV8865_PLL_CTRLA_PRE_DIV_HALF(v) (((v) - 1) & BIT(0)) - #define OV8865_PLL_CTRLB_REG 0x30b -@@ -60,41 +58,21 @@ - #define OV8865_PLL_CTRLE_SYS_DIV(v) ((v) & GENMASK(2, 0)) - #define OV8865_PLL_CTRLF_REG 0x30f - #define OV8865_PLL_CTRLF_SYS_PRE_DIV(v) (((v) - 1) & GENMASK(3, 0)) --#define OV8865_PLL_CTRL10_REG 0x310 --#define OV8865_PLL_CTRL11_REG 0x311 - #define OV8865_PLL_CTRL12_REG 0x312 - #define OV8865_PLL_CTRL12_PRE_DIV_HALF(v) ((((v) - 1) << 4) & BIT(4)) - #define OV8865_PLL_CTRL12_DAC_DIV(v) (((v) - 1) & GENMASK(3, 0)) - --#define OV8865_PLL_CTRL1B_REG 0x31b --#define OV8865_PLL_CTRL1C_REG 0x31c -- - #define OV8865_PLL_CTRL1E_REG 0x31e - #define OV8865_PLL_CTRL1E_PLL1_NO_LAT BIT(3) - --#define OV8865_PAD_OEN0_REG 0x3000 -- --#define OV8865_PAD_OEN2_REG 0x3002 -- --#define OV8865_CLK_RST5_REG 0x3005 -- - #define OV8865_CHIP_ID_HH_REG 0x300a - #define OV8865_CHIP_ID_HH_VALUE 0x00 - #define OV8865_CHIP_ID_H_REG 0x300b - #define OV8865_CHIP_ID_H_VALUE 0x88 - #define OV8865_CHIP_ID_L_REG 0x300c - #define OV8865_CHIP_ID_L_VALUE 0x65 --#define OV8865_PAD_OUT2_REG 0x300d -- --#define OV8865_PAD_SEL2_REG 0x3010 --#define OV8865_PAD_PK_REG 0x3011 --#define OV8865_PAD_PK_DRIVE_STRENGTH_1X (0 << 5) --#define OV8865_PAD_PK_DRIVE_STRENGTH_2X (1 << 5) --#define OV8865_PAD_PK_DRIVE_STRENGTH_3X (2 << 5) --#define OV8865_PAD_PK_DRIVE_STRENGTH_4X (3 << 5) - - #define OV8865_PUMP_CLK_DIV_REG 0x3015 --#define OV8865_PUMP_CLK_DIV_PUMP_N(v) (((v) << 4) & GENMASK(6, 4)) - #define OV8865_PUMP_CLK_DIV_PUMP_P(v) ((v) & GENMASK(2, 0)) - - #define OV8865_MIPI_SC_CTRL0_REG 0x3018 -@@ -102,21 +80,12 @@ - GENMASK(7, 5)) - #define OV8865_MIPI_SC_CTRL0_MIPI_EN BIT(4) - #define OV8865_MIPI_SC_CTRL0_UNKNOWN BIT(1) --#define OV8865_MIPI_SC_CTRL0_LANES_PD_MIPI BIT(0) --#define OV8865_MIPI_SC_CTRL1_REG 0x3019 --#define OV8865_CLK_RST0_REG 0x301a --#define OV8865_CLK_RST1_REG 0x301b --#define OV8865_CLK_RST2_REG 0x301c --#define OV8865_CLK_RST3_REG 0x301d --#define OV8865_CLK_RST4_REG 0x301e - - #define OV8865_PCLK_SEL_REG 0x3020 - #define OV8865_PCLK_SEL_PCLK_DIV_MASK BIT(3) - #define OV8865_PCLK_SEL_PCLK_DIV(v) ((((v) - 1) << 3) & BIT(3)) - --#define OV8865_MISC_CTRL_REG 0x3021 - #define OV8865_MIPI_SC_CTRL2_REG 0x3022 --#define OV8865_MIPI_SC_CTRL2_CLK_LANES_PD_MIPI BIT(1) - #define OV8865_MIPI_SC_CTRL2_PD_MIPI_RST_SYNC BIT(0) - - #define OV8865_MIPI_BIT_SEL_REG 0x3031 -@@ -125,7 +94,6 @@ - #define OV8865_CLK_SEL0_PLL1_SYS_SEL(v) (((v) << 7) & BIT(7)) - #define OV8865_CLK_SEL1_REG 0x3033 - #define OV8865_CLK_SEL1_MIPI_EOF BIT(5) --#define OV8865_CLK_SEL1_UNKNOWN BIT(2) - #define OV8865_CLK_SEL1_PLL_SCLK_SEL_MASK BIT(1) - #define OV8865_CLK_SEL1_PLL_SCLK_SEL(v) (((v) << 1) & BIT(1)) - -@@ -142,7 +110,6 @@ - #define OV8865_EXPOSURE_CTRL_H(v) (((v) & GENMASK(15, 8)) >> 8) - #define OV8865_EXPOSURE_CTRL_L_REG 0x3502 - #define OV8865_EXPOSURE_CTRL_L(v) ((v) & GENMASK(7, 0)) --#define OV8865_EXPOSURE_GAIN_MANUAL_REG 0x3503 - - #define OV8865_GAIN_CTRL_H_REG 0x3508 - #define OV8865_GAIN_CTRL_H(v) (((v) & GENMASK(12, 8)) >> 8) -@@ -197,18 +164,6 @@ - #define OV8865_INC_X_ODD(v) ((v) & GENMASK(4, 0)) - #define OV8865_INC_X_EVEN_REG 0x3815 - #define OV8865_INC_X_EVEN(v) ((v) & GENMASK(4, 0)) --#define OV8865_VSYNC_START_H_REG 0x3816 --#define OV8865_VSYNC_START_H(v) (((v) & GENMASK(15, 8)) >> 8) --#define OV8865_VSYNC_START_L_REG 0x3817 --#define OV8865_VSYNC_START_L(v) ((v) & GENMASK(7, 0)) --#define OV8865_VSYNC_END_H_REG 0x3818 --#define OV8865_VSYNC_END_H(v) (((v) & GENMASK(15, 8)) >> 8) --#define OV8865_VSYNC_END_L_REG 0x3819 --#define OV8865_VSYNC_END_L(v) ((v) & GENMASK(7, 0)) --#define OV8865_HSYNC_FIRST_H_REG 0x381a --#define OV8865_HSYNC_FIRST_H(v) (((v) & GENMASK(15, 8)) >> 8) --#define OV8865_HSYNC_FIRST_L_REG 0x381b --#define OV8865_HSYNC_FIRST_L(v) ((v) & GENMASK(7, 0)) - - #define OV8865_FORMAT1_REG 0x3820 - #define OV8865_FORMAT1_FLIP_VERT_ISP_EN BIT(2) -@@ -240,10 +195,6 @@ - #define OV8865_AUTO_SIZE_CTRL_CROP_END_X_REG BIT(2) - #define OV8865_AUTO_SIZE_CTRL_CROP_START_Y_REG BIT(1) - #define OV8865_AUTO_SIZE_CTRL_CROP_START_X_REG BIT(0) --#define OV8865_AUTO_SIZE_X_OFFSET_H_REG 0x3842 --#define OV8865_AUTO_SIZE_X_OFFSET_L_REG 0x3843 --#define OV8865_AUTO_SIZE_Y_OFFSET_H_REG 0x3844 --#define OV8865_AUTO_SIZE_Y_OFFSET_L_REG 0x3845 - #define OV8865_AUTO_SIZE_BOUNDARIES_REG 0x3846 - #define OV8865_AUTO_SIZE_BOUNDARIES_Y(v) (((v) << 4) & GENMASK(7, 4)) - #define OV8865_AUTO_SIZE_BOUNDARIES_X(v) ((v) & GENMASK(3, 0)) -@@ -259,30 +210,10 @@ - #define OV8865_BLC_CTRL0_TRIG_FORMAT_EN BIT(6) - #define OV8865_BLC_CTRL0_TRIG_GAIN_EN BIT(5) - #define OV8865_BLC_CTRL0_TRIG_EXPOSURE_EN BIT(4) --#define OV8865_BLC_CTRL0_TRIG_MANUAL_EN BIT(3) --#define OV8865_BLC_CTRL0_FREEZE_EN BIT(2) --#define OV8865_BLC_CTRL0_ALWAYS_EN BIT(1) - #define OV8865_BLC_CTRL0_FILTER_EN BIT(0) - #define OV8865_BLC_CTRL1_REG 0x4001 --#define OV8865_BLC_CTRL1_DITHER_EN BIT(7) --#define OV8865_BLC_CTRL1_ZERO_LINE_DIFF_EN BIT(6) --#define OV8865_BLC_CTRL1_COL_SHIFT_256 (0 << 4) - #define OV8865_BLC_CTRL1_COL_SHIFT_128 (1 << 4) --#define OV8865_BLC_CTRL1_COL_SHIFT_64 (2 << 4) --#define OV8865_BLC_CTRL1_COL_SHIFT_32 (3 << 4) - #define OV8865_BLC_CTRL1_OFFSET_LIMIT_EN BIT(2) --#define OV8865_BLC_CTRL1_COLUMN_CANCEL_EN BIT(1) --#define OV8865_BLC_CTRL2_REG 0x4002 --#define OV8865_BLC_CTRL3_REG 0x4003 --#define OV8865_BLC_CTRL4_REG 0x4004 --#define OV8865_BLC_CTRL5_REG 0x4005 --#define OV8865_BLC_CTRL6_REG 0x4006 --#define OV8865_BLC_CTRL7_REG 0x4007 --#define OV8865_BLC_CTRL8_REG 0x4008 --#define OV8865_BLC_CTRL9_REG 0x4009 --#define OV8865_BLC_CTRLA_REG 0x400a --#define OV8865_BLC_CTRLB_REG 0x400b --#define OV8865_BLC_CTRLC_REG 0x400c - #define OV8865_BLC_CTRLD_REG 0x400d - #define OV8865_BLC_CTRLD_OFFSET_TRIGGER(v) ((v) & GENMASK(7, 0)) - -@@ -337,66 +268,8 @@ - - /* MIPI */ - --#define OV8865_MIPI_CTRL0_REG 0x4800 --#define OV8865_MIPI_CTRL1_REG 0x4801 --#define OV8865_MIPI_CTRL2_REG 0x4802 --#define OV8865_MIPI_CTRL3_REG 0x4803 --#define OV8865_MIPI_CTRL4_REG 0x4804 --#define OV8865_MIPI_CTRL5_REG 0x4805 --#define OV8865_MIPI_CTRL6_REG 0x4806 --#define OV8865_MIPI_CTRL7_REG 0x4807 --#define OV8865_MIPI_CTRL8_REG 0x4808 -- --#define OV8865_MIPI_FCNT_MAX_H_REG 0x4810 --#define OV8865_MIPI_FCNT_MAX_L_REG 0x4811 -- --#define OV8865_MIPI_CTRL13_REG 0x4813 --#define OV8865_MIPI_CTRL14_REG 0x4814 --#define OV8865_MIPI_CTRL15_REG 0x4815 --#define OV8865_MIPI_EMBEDDED_DT_REG 0x4816 -- --#define OV8865_MIPI_HS_ZERO_MIN_H_REG 0x4818 --#define OV8865_MIPI_HS_ZERO_MIN_L_REG 0x4819 --#define OV8865_MIPI_HS_TRAIL_MIN_H_REG 0x481a --#define OV8865_MIPI_HS_TRAIL_MIN_L_REG 0x481b --#define OV8865_MIPI_CLK_ZERO_MIN_H_REG 0x481c --#define OV8865_MIPI_CLK_ZERO_MIN_L_REG 0x481d --#define OV8865_MIPI_CLK_PREPARE_MAX_REG 0x481e --#define OV8865_MIPI_CLK_PREPARE_MIN_REG 0x481f --#define OV8865_MIPI_CLK_POST_MIN_H_REG 0x4820 --#define OV8865_MIPI_CLK_POST_MIN_L_REG 0x4821 --#define OV8865_MIPI_CLK_TRAIL_MIN_H_REG 0x4822 --#define OV8865_MIPI_CLK_TRAIL_MIN_L_REG 0x4823 --#define OV8865_MIPI_LPX_P_MIN_H_REG 0x4824 --#define OV8865_MIPI_LPX_P_MIN_L_REG 0x4825 --#define OV8865_MIPI_HS_PREPARE_MIN_REG 0x4826 --#define OV8865_MIPI_HS_PREPARE_MAX_REG 0x4827 --#define OV8865_MIPI_HS_EXIT_MIN_H_REG 0x4828 --#define OV8865_MIPI_HS_EXIT_MIN_L_REG 0x4829 --#define OV8865_MIPI_UI_HS_ZERO_MIN_REG 0x482a --#define OV8865_MIPI_UI_HS_TRAIL_MIN_REG 0x482b --#define OV8865_MIPI_UI_CLK_ZERO_MIN_REG 0x482c --#define OV8865_MIPI_UI_CLK_PREPARE_REG 0x482d --#define OV8865_MIPI_UI_CLK_POST_MIN_REG 0x482e --#define OV8865_MIPI_UI_CLK_TRAIL_MIN_REG 0x482f --#define OV8865_MIPI_UI_LPX_P_MIN_REG 0x4830 --#define OV8865_MIPI_UI_HS_PREPARE_REG 0x4831 --#define OV8865_MIPI_UI_HS_EXIT_MIN_REG 0x4832 --#define OV8865_MIPI_PKT_START_SIZE_REG 0x4833 -- - #define OV8865_MIPI_PCLK_PERIOD_REG 0x4837 --#define OV8865_MIPI_LP_GPIO0_REG 0x4838 --#define OV8865_MIPI_LP_GPIO1_REG 0x4839 -- --#define OV8865_MIPI_CTRL3C_REG 0x483c --#define OV8865_MIPI_LP_GPIO4_REG 0x483d -- --#define OV8865_MIPI_CTRL4A_REG 0x484a --#define OV8865_MIPI_CTRL4B_REG 0x484b --#define OV8865_MIPI_CTRL4C_REG 0x484c --#define OV8865_MIPI_LANE_TEST_PATTERN_REG 0x484d --#define OV8865_MIPI_FRAME_END_DELAY_REG 0x484e --#define OV8865_MIPI_CLOCK_TEST_PATTERN_REG 0x484f ++ /* set properties from fwnode (e.g. rotation, orientation) */ ++ ret = v4l2_fwnode_device_parse(sensor->dev, &props); ++ if (ret) ++ goto error_ctrls; + - #define OV8865_MIPI_LANE_SEL01_REG 0x4850 - #define OV8865_MIPI_LANE_SEL01_LANE0(v) (((v) << 0) & GENMASK(2, 0)) - #define OV8865_MIPI_LANE_SEL01_LANE1(v) (((v) << 4) & GENMASK(6, 4)) -@@ -407,7 +280,6 @@ - /* ISP */ - - #define OV8865_ISP_CTRL0_REG 0x5000 --#define OV8865_ISP_CTRL0_LENC_EN BIT(7) - #define OV8865_ISP_CTRL0_WHITE_BALANCE_EN BIT(4) - #define OV8865_ISP_CTRL0_DPC_BLACK_EN BIT(2) - #define OV8865_ISP_CTRL0_DPC_WHITE_EN BIT(1) -@@ -416,17 +288,11 @@ - #define OV8865_ISP_CTRL2_REG 0x5002 - #define OV8865_ISP_CTRL2_DEBUG BIT(3) - #define OV8865_ISP_CTRL2_VARIOPIXEL_EN BIT(2) --#define OV8865_ISP_CTRL2_VSYNC_LATCH_EN BIT(0) --#define OV8865_ISP_CTRL3_REG 0x5003 - - #define OV8865_ISP_GAIN_RED_H_REG 0x5018 - #define OV8865_ISP_GAIN_RED_H(v) (((v) & GENMASK(13, 6)) >> 6) - #define OV8865_ISP_GAIN_RED_L_REG 0x5019 - #define OV8865_ISP_GAIN_RED_L(v) ((v) & GENMASK(5, 0)) --#define OV8865_ISP_GAIN_GREEN_H_REG 0x501a --#define OV8865_ISP_GAIN_GREEN_H(v) (((v) & GENMASK(13, 6)) >> 6) --#define OV8865_ISP_GAIN_GREEN_L_REG 0x501b --#define OV8865_ISP_GAIN_GREEN_L(v) ((v) & GENMASK(5, 0)) - #define OV8865_ISP_GAIN_BLUE_H_REG 0x501c - #define OV8865_ISP_GAIN_BLUE_H(v) (((v) & GENMASK(13, 6)) >> 6) - #define OV8865_ISP_GAIN_BLUE_L_REG 0x501d -@@ -434,7 +300,6 @@ - - /* VarioPixel */ - --#define OV8865_VAP_CTRL0_REG 0x5900 - #define OV8865_VAP_CTRL1_REG 0x5901 - #define OV8865_VAP_CTRL1_HSUB_COEF(v) ((((v) - 1) << 2) & \ - GENMASK(3, 2)) ++ ret = v4l2_ctrl_new_fwnode_properties(handler, ops, &props); ++ if (ret) ++ goto error_ctrls; ++ + if (handler->error) { + ret = handler->error; + goto error_ctrls; -- 2.33.1 -From 690e2dbe299f382eca02bafdeb8f09b0208cece7 Mon Sep 17 00:00:00 2001 +From 209125bbd208e5f07660f3c65e297268682409fa Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Fri, 16 Jul 2021 00:00:54 +0100 Subject: [PATCH] media: i2c: Switch exposure control unit to lines @@ -3182,10 +3169,10 @@ Patchset: cameras 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index fb81b822987d..27520c731e47 100644 +index dfb5095ef16b..5f19d82554df 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -1991,6 +1991,9 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure) +@@ -2125,6 +2125,9 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure) { int ret; @@ -3195,7 +3182,7 @@ index fb81b822987d..27520c731e47 100644 ret = ov8865_write(sensor, OV8865_EXPOSURE_CTRL_HH_REG, OV8865_EXPOSURE_CTRL_HH(exposure)); if (ret) -@@ -2389,8 +2392,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) +@@ -2525,8 +2528,8 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) /* Exposure */ @@ -3209,52 +3196,126 @@ index fb81b822987d..27520c731e47 100644 -- 2.33.1 -From 674802866720eae5cbd24311338ac63ca4dc99ab Mon Sep 17 00:00:00 2001 +From 566ba771fd2b85070d1a28c16ad0e834d0e7ba20 Mon Sep 17 00:00:00 2001 From: Daniel Scally -Date: Fri, 16 Jul 2021 22:56:15 +0100 -Subject: [PATCH] media: i2c: Add controls from fwnode to ov8865 +Date: Tue, 24 Aug 2021 22:39:02 +0100 +Subject: [PATCH] media: i2c: Re-order runtime pm initialisation -Add V4L2_CID_ORIENTATION and V4L2_CID_ROTATION controls to the ov8865 -driver by attempting to parse them from firmware. +The kerneldoc for pm_runtime_set_suspended() says: + +"It is not valid to call this function for devices with runtime PM +enabled" + +To satisfy that requirement, re-order the calls so that +pm_runtime_enable() is the last one. Signed-off-by: Daniel Scally Patchset: cameras --- - drivers/media/i2c/ov8865.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) + drivers/media/i2c/ov8865.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c -index 27520c731e47..f746917719ae 100644 +index 5f19d82554df..18b5f1e8e9a7 100644 --- a/drivers/media/i2c/ov8865.c +++ b/drivers/media/i2c/ov8865.c -@@ -2381,6 +2381,7 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) - struct v4l2_ctrl_handler *handler = &ctrls->handler; - const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops; - const struct ov8865_mode *mode = sensor->state.mode; -+ struct v4l2_fwnode_device_properties props; - unsigned int vblank_max, vblank_def; - unsigned int hblank; - int ret; -@@ -2443,6 +2444,15 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor) - v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1, - INT_MAX, 1, 1); +@@ -3085,8 +3085,8 @@ static int ov8865_probe(struct i2c_client *client) + + /* Runtime PM */ + +- pm_runtime_enable(sensor->dev); + pm_runtime_set_suspended(sensor->dev); ++ pm_runtime_enable(sensor->dev); + + /* V4L2 subdev register */ -+ /* set properties from fwnode (e.g. rotation, orientation) */ -+ ret = v4l2_fwnode_device_parse(sensor->dev, &props); -+ if (ret) -+ goto error_ctrls; -+ -+ ret = v4l2_ctrl_new_fwnode_properties(handler, ops, &props); -+ if (ret) -+ goto error_ctrls; -+ - if (handler->error) { - ret = handler->error; - goto error_ctrls; -- 2.33.1 -From 7cf93c124465b8bcaad195decc4b887ccd7c2beb Mon Sep 17 00:00:00 2001 +From e771d413a2892c07b576b2967edcefa820269d9b Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Tue, 24 Aug 2021 23:17:39 +0100 +Subject: [PATCH] media: i2c: Use dev_err_probe() in ov8865 + +There is a chance that regulator_get() returns -EPROBE_DEFER, in which +case printing an error message is undesirable. To avoid spurious messages +in dmesg in the event that -EPROBE_DEFER is returned, use dev_err_probe() +on error paths for regulator_get(). + +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/media/i2c/ov8865.c | 46 +++++++++++++++++--------------------- + 1 file changed, 20 insertions(+), 26 deletions(-) + +diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c +index 18b5f1e8e9a7..19e6bebf340d 100644 +--- a/drivers/media/i2c/ov8865.c ++++ b/drivers/media/i2c/ov8865.c +@@ -2955,6 +2955,26 @@ static int ov8865_probe(struct i2c_client *client) + sensor->dev = dev; + sensor->i2c_client = client; + ++ /* Regulators */ ++ ++ /* DVDD: digital core */ ++ sensor->dvdd = devm_regulator_get(dev, "dvdd"); ++ if (IS_ERR(sensor->dvdd)) ++ return dev_err_probe(dev, PTR_ERR(sensor->dvdd), ++ "cannot get DVDD regulator\n"); ++ ++ /* DOVDD: digital I/O */ ++ sensor->dovdd = devm_regulator_get(dev, "dovdd"); ++ if (IS_ERR(sensor->dovdd)) ++ return dev_err_probe(dev, PTR_ERR(sensor->dovdd), ++ "cannot get DOVDD regulator\n"); ++ ++ /* AVDD: analog */ ++ sensor->avdd = devm_regulator_get(dev, "avdd"); ++ if (IS_ERR(sensor->avdd)) ++ return dev_err_probe(dev, PTR_ERR(sensor->avdd), ++ "cannot get AVDD regulator\n"); ++ + /* Graph Endpoint */ + + handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); +@@ -2985,32 +3005,6 @@ static int ov8865_probe(struct i2c_client *client) + goto error_endpoint; + } + +- /* Regulators */ +- +- /* DVDD: digital core */ +- sensor->dvdd = devm_regulator_get(dev, "dvdd"); +- if (IS_ERR(sensor->dvdd)) { +- dev_err(dev, "cannot get DVDD (digital core) regulator\n"); +- ret = PTR_ERR(sensor->dvdd); +- goto error_endpoint; +- } +- +- /* DOVDD: digital I/O */ +- sensor->dovdd = devm_regulator_get(dev, "dovdd"); +- if (IS_ERR(sensor->dovdd)) { +- dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n"); +- ret = PTR_ERR(sensor->dovdd); +- goto error_endpoint; +- } +- +- /* AVDD: analog */ +- sensor->avdd = devm_regulator_get(dev, "avdd"); +- if (IS_ERR(sensor->avdd)) { +- dev_err(dev, "cannot get AVDD (analog) regulator\n"); +- ret = PTR_ERR(sensor->avdd); +- goto error_endpoint; +- } +- + /* External Clock */ + + sensor->extclk = devm_clk_get(dev, NULL); +-- +2.33.1 + +From 862668e9e6feedfcefe5a51a17da42529d847621 Mon Sep 17 00:00:00 2001 From: Daniel Scally Date: Wed, 14 Jul 2021 00:05:04 +0100 Subject: [PATCH] media: ipu3-cio2: Add INT347A to cio2-bridge @@ -3264,6 +3325,7 @@ support the platforms that the cio2-bridge serves. Add it to the array of supported sensors so the bridge will connect the sensor to the CIO2 device. +Reviewed-by: Andy Shevchenko Signed-off-by: Daniel Scally Patchset: cameras --- @@ -3271,18 +3333,1951 @@ Patchset: cameras 1 file changed, 2 insertions(+) diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c -index 7e582135dfb8..045b15498aca 100644 +index 7e582135dfb8..0132f0bd9b41 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c -@@ -24,6 +24,8 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = { +@@ -22,6 +22,8 @@ + static const struct cio2_sensor_config cio2_supported_sensors[] = { + /* Omnivision OV5693 */ CIO2_SENSOR_CONFIG("INT33BE", 0), - /* Omnivision OV2680 */ - CIO2_SENSOR_CONFIG("OVTI2680", 0), + /* Omnivision OV8865 */ + CIO2_SENSOR_CONFIG("INT347A", 1, 360000000), + /* Omnivision OV2680 */ + CIO2_SENSOR_CONFIG("OVTI2680", 0), }; - - static const struct cio2_property_names prop_names = { +-- +2.33.1 + +From d6e8bc9451c581e73f17db5eed00f982353c2723 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 7 Oct 2021 15:34:52 +0200 +Subject: [PATCH] media: i2c: ov8865: Fix lockdep error + +ov8865_state_init() calls ov8865_state_mipi_configure() which uses +__v4l2_ctrl_s_ctrl[_int64](). This means that sensor->mutex (which +is also sensor->ctrls.handler.lock) must be locked before calling +ov8865_state_init(). + +Note ov8865_state_mipi_configure() is also used in other places where +the lock is already held so it cannot be changed itself. + +This fixes the following lockdep kernel WARN: + +[ 13.233413] ------------[ cut here ]------------ +[ 13.233421] WARNING: CPU: 0 PID: 8 at drivers/media/v4l2-core/v4l2-ctrls-api.c:833 __v4l2_ctrl_s_ctrl+0x4d/0x60 [videodev] +... +[ 13.234063] Call Trace: +[ 13.234074] ov8865_state_configure+0x98b/0xc00 [ov8865] +[ 13.234095] ov8865_probe+0x4b1/0x54c [ov8865] +[ 13.234117] i2c_device_probe+0x13c/0x2d0 + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/media/i2c/ov8865.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/i2c/ov8865.c b/drivers/media/i2c/ov8865.c +index 19e6bebf340d..d5af8aedf5e8 100644 +--- a/drivers/media/i2c/ov8865.c ++++ b/drivers/media/i2c/ov8865.c +@@ -3073,7 +3073,9 @@ static int ov8865_probe(struct i2c_client *client) + if (ret) + goto error_mutex; + ++ mutex_lock(&sensor->mutex); + ret = ov8865_state_init(sensor); ++ mutex_unlock(&sensor->mutex); + if (ret) + goto error_ctrls; + +-- +2.33.1 + +From 9f35a2c4946516acb37212b9b4bdc71c2fa761dc Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:56:57 +0200 +Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an + INT3472 device + +The clk and regulator frameworks expect clk/regulator consumer-devices +to have info about the consumed clks/regulators described in the device's +fw_node. + +To work around cases where this info is not present in the firmware tables, +which is often the case on x86/ACPI devices, both frameworks allow the +provider-driver to attach info about consumers to the clks/regulators +when registering these. + +This causes problems with the probe ordering wrt drivers for consumers +of these clks/regulators. Since the lookups are only registered when the +provider-driver binds, trying to get these clks/regulators before then +results in a -ENOENT error for clks and a dummy regulator for regulators. + +One case where we hit this issue is camera sensors such as e.g. the OV8865 +sensor found on the Microsoft Surface Go. The sensor uses clks, regulators +and GPIOs provided by a TPS68470 PMIC which is described in an INT3472 +ACPI device. There is special platform code handling this and setting +platform_data with the necessary consumer info on the MFD cells +instantiated for the PMIC under: drivers/platform/x86/intel/int3472. + +For this to work properly the ov8865 driver must not bind to the I2C-client +for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and +clk MFD cells have all been fully setup. + +The OV8865 on the Microsoft Surface Go is just one example, all X86 +devices using the Intel IPU3 camera block found on recent Intel SoCs +have similar issues where there is an INT3472 HID ACPI-device, which +describes the clks and regulators, and the driver for this INT3472 device +must be fully initialized before the sensor driver (any sensor driver) +binds for things to work properly. + +On these devices the ACPI nodes describing the sensors all have a _DEP +dependency on the matching INT3472 ACPI device (there is one per sensor). + +This allows solving the probe-ordering problem by delaying the enumeration +(instantiation of the I2C-client in the ov8865 example) of ACPI-devices +which have a _DEP dependency on an INT3472 device. + +The new acpi_dev_ready_for_enumeration() helper used for this is also +exported because for devices, which have the enumeration_by_parent flag +set, the parent-driver will do its own scan of child ACPI devices and +it will try to enumerate those during its probe(). Code doing this such +as e.g. the i2c-core-acpi.c code must call this new helper to ensure +that it too delays the enumeration until all the _DEP dependencies are +met on devices which have the new honor_deps flag set. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/acpi/scan.c | 36 ++++++++++++++++++++++++++++++++++-- + include/acpi/acpi_bus.h | 5 ++++- + 2 files changed, 38 insertions(+), 3 deletions(-) + +diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c +index b24513ec3fae..e7ecf07e2f54 100644 +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = { + NULL + }; + ++/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */ ++static const char * const acpi_honor_dep_ids[] = { ++ "INT3472", /* Camera sensor PMIC / clk and regulator info */ ++ NULL ++}; ++ + static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) + { + struct acpi_device *device = NULL; +@@ -1758,8 +1764,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev) + struct acpi_dep_data *dep; + + list_for_each_entry(dep, &acpi_dep_list, node) { +- if (dep->consumer == adev->handle) ++ if (dep->consumer == adev->handle) { ++ if (dep->honor_dep) ++ adev->flags.honor_deps = 1; ++ + adev->dep_unmet++; ++ } + } + } + +@@ -1963,7 +1973,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) + for (count = 0, i = 0; i < dep_devices.count; i++) { + struct acpi_device_info *info; + struct acpi_dep_data *dep; +- bool skip; ++ bool skip, honor_dep; + + status = acpi_get_object_info(dep_devices.handles[i], &info); + if (ACPI_FAILURE(status)) { +@@ -1972,6 +1982,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) + } + + skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids); ++ honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids); + kfree(info); + + if (skip) +@@ -1985,6 +1996,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) + + dep->supplier = dep_devices.handles[i]; + dep->consumer = handle; ++ dep->honor_dep = honor_dep; + + mutex_lock(&acpi_dep_list_lock); + list_add_tail(&dep->node , &acpi_dep_list); +@@ -2072,6 +2084,9 @@ static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used, + + static void acpi_default_enumeration(struct acpi_device *device) + { ++ if (!acpi_dev_ready_for_enumeration(device)) ++ return; ++ + /* + * Do not enumerate devices with enumeration_by_parent flag set as + * they will be enumerated by their respective parents. +@@ -2314,6 +2329,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier) + } + EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies); + ++/** ++ * acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration ++ * @device: Pointer to the &struct acpi_device to check ++ * ++ * Check if the device is present and has no unmet dependencies. ++ * ++ * Return true if the device is ready for enumeratino. Otherwise, return false. ++ */ ++bool acpi_dev_ready_for_enumeration(const struct acpi_device *device) ++{ ++ if (device->flags.honor_deps && device->dep_unmet) ++ return false; ++ ++ return acpi_device_is_present(device); ++} ++EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration); ++ + /** + * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier + * @supplier: Pointer to the dependee device +diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h +index 13d93371790e..2da53b7b4965 100644 +--- a/include/acpi/acpi_bus.h ++++ b/include/acpi/acpi_bus.h +@@ -202,7 +202,8 @@ struct acpi_device_flags { + u32 coherent_dma:1; + u32 cca_seen:1; + u32 enumeration_by_parent:1; +- u32 reserved:19; ++ u32 honor_deps:1; ++ u32 reserved:18; + }; + + /* File System */ +@@ -284,6 +285,7 @@ struct acpi_dep_data { + struct list_head node; + acpi_handle supplier; + acpi_handle consumer; ++ bool honor_dep; + }; + + /* Performance Management */ +@@ -693,6 +695,7 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev) + bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2); + + void acpi_dev_clear_dependencies(struct acpi_device *supplier); ++bool acpi_dev_ready_for_enumeration(const struct acpi_device *device); + struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier); + struct acpi_device * + acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv); +-- +2.33.1 + +From 4380dab5d9e986ee0b80412e481315c862f7fa25 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:56:58 +0200 +Subject: [PATCH] i2c: acpi: Use acpi_dev_ready_for_enumeration() helper + +The clk and regulator frameworks expect clk/regulator consumer-devices +to have info about the consumed clks/regulators described in the device's +fw_node. + +To work around cases where this info is not present in the firmware tables, +which is often the case on x86/ACPI devices, both frameworks allow the +provider-driver to attach info about consumers to the clks/regulators +when registering these. + +This causes problems with the probe ordering wrt drivers for consumers +of these clks/regulators. Since the lookups are only registered when the +provider-driver binds, trying to get these clks/regulators before then +results in a -ENOENT error for clks and a dummy regulator for regulators. + +To ensure the correct probe-ordering the ACPI core has code to defer the +enumeration of consumers affected by this until the providers are ready. + +Call the new acpi_dev_ready_for_enumeration() helper to avoid +enumerating / instantiating i2c-clients too early. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/i2c/i2c-core-acpi.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c +index 169713964358..9f0e719cd2c8 100644 +--- a/drivers/i2c/i2c-core-acpi.c ++++ b/drivers/i2c/i2c-core-acpi.c +@@ -112,9 +112,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev, + struct list_head resource_list; + int ret; + +- if (acpi_bus_get_status(adev) || !adev->status.present) ++ if (acpi_bus_get_status(adev)) + return -EINVAL; + ++ if (!acpi_dev_ready_for_enumeration(adev)) ++ return -ENODEV; ++ + if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0) + return -ENODEV; + +-- +2.33.1 + +From 97aee8e13cd124b7736f1b53e6e96881ac55f84c Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:56:59 +0200 +Subject: [PATCH] platform_data: Add linux/platform_data/tps68470.h file + +The clk and regulator frameworks expect clk/regulator consumer-devices +to have info about the consumed clks/regulators described in the device's +fw_node. + +To work around cases where this info is not present in the firmware tables, +which is often the case on x86/ACPI devices, both frameworks allow the +provider-driver to attach info about consumers to the provider-device +during probe/registration of the provider device. + +The TI TPS68470 PMIC is used x86/ACPI devices with the consumer-info +missing from the ACPI tables. Thus the tps68470-clk and tps68470-regulator +drivers must provide the consumer-info at probe time. + +Define tps68470_clk_platform_data and tps68470_regulator_platform_data +structs to allow the x86 platform code to pass the necessary consumer info +to these drivers. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + include/linux/platform_data/tps68470.h | 35 ++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + create mode 100644 include/linux/platform_data/tps68470.h + +diff --git a/include/linux/platform_data/tps68470.h b/include/linux/platform_data/tps68470.h +new file mode 100644 +index 000000000000..126d082c3f2e +--- /dev/null ++++ b/include/linux/platform_data/tps68470.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * TI TPS68470 PMIC platform data definition. ++ * ++ * Copyright (c) 2021 Red Hat Inc. ++ * ++ * Red Hat authors: ++ * Hans de Goede ++ */ ++#ifndef __PDATA_TPS68470_H ++#define __PDATA_TPS68470_H ++ ++enum tps68470_regulators { ++ TPS68470_CORE, ++ TPS68470_ANA, ++ TPS68470_VCM, ++ TPS68470_VIO, ++ TPS68470_VSIO, ++ TPS68470_AUX1, ++ TPS68470_AUX2, ++ TPS68470_NUM_REGULATORS ++}; ++ ++struct regulator_init_data; ++ ++struct tps68470_regulator_platform_data { ++ const struct regulator_init_data *reg_init_data[TPS68470_NUM_REGULATORS]; ++}; ++ ++struct tps68470_clk_platform_data { ++ const char *consumer_dev_name; ++ const char *consumer_con_id; ++}; ++ ++#endif +-- +2.33.1 + +From 313394c42ef2b3e91a4064241c6f58c4bd9776ae Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:00 +0200 +Subject: [PATCH] regulator: Introduce tps68470-regulator driver + +The TPS68470 PMIC provides Clocks, GPIOs and Regulators. At present in +the kernel the Regulators and Clocks are controlled by an OpRegion +driver designed to work with power control methods defined in ACPI, but +some platforms lack those methods, meaning drivers need to be able to +consume the resources of these chips through the usual frameworks. + +This commit adds a driver for the regulators provided by the tps68470, +and is designed to bind to the platform_device registered by the +intel_skl_int3472 module. + +This is based on this out of tree driver written by Intel: +https://github.com/intel/linux-intel-lts/blob/4.14/base/drivers/regulator/tps68470-regulator.c +with various cleanups added. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/regulator/Kconfig | 9 ++ + drivers/regulator/Makefile | 1 + + drivers/regulator/tps68470-regulator.c | 193 +++++++++++++++++++++++++ + 3 files changed, 203 insertions(+) + create mode 100644 drivers/regulator/tps68470-regulator.c + +diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig +index 24ce9a17ab4f..97caab5f7f9f 100644 +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -1319,6 +1319,15 @@ config REGULATOR_TPS65912 + help + This driver supports TPS65912 voltage regulator chip. + ++config REGULATOR_TPS68470 ++ tristate "TI TPS68370 PMIC Regulators Driver" ++ depends on INTEL_SKL_INT3472 ++ help ++ This driver adds support for the TPS68470 PMIC to register ++ regulators against the usual framework. ++ ++ The module will be called "tps68470-regulator" ++ + config REGULATOR_TPS80031 + tristate "TI TPS80031/TPS80032 power regulator driver" + depends on MFD_TPS80031 +diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile +index 8c2f82206b94..8dcc4506ecf8 100644 +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -156,6 +156,7 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o + obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o + obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o + obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o ++obj-$(CONFIG_REGULATOR_TPS68470) += tps68470-regulator.o + obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o + obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o + obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o +diff --git a/drivers/regulator/tps68470-regulator.c b/drivers/regulator/tps68470-regulator.c +new file mode 100644 +index 000000000000..3129fa13a122 +--- /dev/null ++++ b/drivers/regulator/tps68470-regulator.c +@@ -0,0 +1,193 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Regulator driver for TPS68470 PMIC ++ * ++ * Copyright (C) 2018 Intel Corporation ++ * ++ * Authors: ++ * Zaikuo Wang ++ * Tianshu Qiu ++ * Jian Xu Zheng ++ * Yuning Pu ++ * Rajmohan Mani ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TPS68470_REGULATOR(_name, _id, _ops, _n, _vr, \ ++ _vm, _er, _em, _t, _lr, _nlr) \ ++ [TPS68470_ ## _name] = { \ ++ .name = # _name, \ ++ .id = _id, \ ++ .ops = &_ops, \ ++ .n_voltages = _n, \ ++ .type = REGULATOR_VOLTAGE, \ ++ .owner = THIS_MODULE, \ ++ .vsel_reg = _vr, \ ++ .vsel_mask = _vm, \ ++ .enable_reg = _er, \ ++ .enable_mask = _em, \ ++ .volt_table = _t, \ ++ .linear_ranges = _lr, \ ++ .n_linear_ranges = _nlr, \ ++ } ++ ++static const struct linear_range tps68470_ldo_ranges[] = { ++ REGULATOR_LINEAR_RANGE(875000, 0, 125, 17800), ++}; ++ ++static const struct linear_range tps68470_core_ranges[] = { ++ REGULATOR_LINEAR_RANGE(900000, 0, 42, 25000), ++}; ++ ++/* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */ ++static const struct regulator_ops tps68470_regulator_ops = { ++ .is_enabled = regulator_is_enabled_regmap, ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++ .list_voltage = regulator_list_voltage_linear_range, ++ .map_voltage = regulator_map_voltage_linear_range, ++}; ++ ++static const struct regulator_desc regulators[] = { ++ TPS68470_REGULATOR(CORE, TPS68470_CORE, ++ tps68470_regulator_ops, 43, TPS68470_REG_VDVAL, ++ TPS68470_VDVAL_DVOLT_MASK, TPS68470_REG_VDCTL, ++ TPS68470_VDCTL_EN_MASK, ++ NULL, tps68470_core_ranges, ++ ARRAY_SIZE(tps68470_core_ranges)), ++ TPS68470_REGULATOR(ANA, TPS68470_ANA, ++ tps68470_regulator_ops, 126, TPS68470_REG_VAVAL, ++ TPS68470_VAVAL_AVOLT_MASK, TPS68470_REG_VACTL, ++ TPS68470_VACTL_EN_MASK, ++ NULL, tps68470_ldo_ranges, ++ ARRAY_SIZE(tps68470_ldo_ranges)), ++ TPS68470_REGULATOR(VCM, TPS68470_VCM, ++ tps68470_regulator_ops, 126, TPS68470_REG_VCMVAL, ++ TPS68470_VCMVAL_VCVOLT_MASK, TPS68470_REG_VCMCTL, ++ TPS68470_VCMCTL_EN_MASK, ++ NULL, tps68470_ldo_ranges, ++ ARRAY_SIZE(tps68470_ldo_ranges)), ++ TPS68470_REGULATOR(VIO, TPS68470_VIO, ++ tps68470_regulator_ops, 126, TPS68470_REG_VIOVAL, ++ TPS68470_VIOVAL_IOVOLT_MASK, TPS68470_REG_S_I2C_CTL, ++ TPS68470_S_I2C_CTL_EN_MASK, ++ NULL, tps68470_ldo_ranges, ++ ARRAY_SIZE(tps68470_ldo_ranges)), ++ ++/* ++ * (1) This register must have same setting as VIOVAL if S_IO LDO is used to ++ * power daisy chained IOs in the receive side. ++ * (2) If there is no I2C daisy chain it can be set freely. ++ * ++ */ ++ TPS68470_REGULATOR(VSIO, TPS68470_VSIO, ++ tps68470_regulator_ops, 126, TPS68470_REG_VSIOVAL, ++ TPS68470_VSIOVAL_IOVOLT_MASK, TPS68470_REG_S_I2C_CTL, ++ TPS68470_S_I2C_CTL_EN_MASK, ++ NULL, tps68470_ldo_ranges, ++ ARRAY_SIZE(tps68470_ldo_ranges)), ++ TPS68470_REGULATOR(AUX1, TPS68470_AUX1, ++ tps68470_regulator_ops, 126, TPS68470_REG_VAUX1VAL, ++ TPS68470_VAUX1VAL_AUX1VOLT_MASK, ++ TPS68470_REG_VAUX1CTL, ++ TPS68470_VAUX1CTL_EN_MASK, ++ NULL, tps68470_ldo_ranges, ++ ARRAY_SIZE(tps68470_ldo_ranges)), ++ TPS68470_REGULATOR(AUX2, TPS68470_AUX2, ++ tps68470_regulator_ops, 126, TPS68470_REG_VAUX2VAL, ++ TPS68470_VAUX2VAL_AUX2VOLT_MASK, ++ TPS68470_REG_VAUX2CTL, ++ TPS68470_VAUX2CTL_EN_MASK, ++ NULL, tps68470_ldo_ranges, ++ ARRAY_SIZE(tps68470_ldo_ranges)), ++}; ++ ++#define TPS68470_REG_INIT_DATA(_name, _min_uV, _max_uV) \ ++ [TPS68470_ ## _name] = { \ ++ .constraints = { \ ++ .name = # _name, \ ++ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | \ ++ REGULATOR_CHANGE_STATUS, \ ++ .min_uV = _min_uV, \ ++ .max_uV = _max_uV, \ ++ }, \ ++ } ++ ++struct regulator_init_data tps68470_init[] = { ++ TPS68470_REG_INIT_DATA(CORE, 900000, 1950000), ++ TPS68470_REG_INIT_DATA(ANA, 875000, 3100000), ++ TPS68470_REG_INIT_DATA(VCM, 875000, 3100000), ++ TPS68470_REG_INIT_DATA(VIO, 875000, 3100000), ++ TPS68470_REG_INIT_DATA(VSIO, 875000, 3100000), ++ TPS68470_REG_INIT_DATA(AUX1, 875000, 3100000), ++ TPS68470_REG_INIT_DATA(AUX2, 875000, 3100000), ++}; ++ ++static int tps68470_regulator_probe(struct platform_device *pdev) ++{ ++ struct tps68470_regulator_platform_data *pdata = pdev->dev.platform_data; ++ struct regulator_config config = { }; ++ struct regmap *tps68470_regmap; ++ struct regulator_dev *rdev; ++ int i; ++ ++ tps68470_regmap = dev_get_drvdata(pdev->dev.parent); ++ ++ for (i = 0; i < TPS68470_NUM_REGULATORS; i++) { ++ config.dev = pdev->dev.parent; ++ config.regmap = tps68470_regmap; ++ if (pdata && pdata->reg_init_data[i]) ++ config.init_data = pdata->reg_init_data[i]; ++ else ++ config.init_data = &tps68470_init[i]; ++ ++ rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); ++ if (IS_ERR(rdev)) { ++ dev_err(&pdev->dev, "failed to register %s regulator\n", ++ regulators[i].name); ++ return PTR_ERR(rdev); ++ } ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver tps68470_regulator_driver = { ++ .driver = { ++ .name = "tps68470-regulator", ++ }, ++ .probe = tps68470_regulator_probe, ++}; ++ ++/* ++ * The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers ++ * registering before the drivers for the camera-sensors which use them bind. ++ * subsys_initcall() ensures this when the drivers are builtin. ++ */ ++static int __init tps68470_regulator_init(void) ++{ ++ return platform_driver_register(&tps68470_regulator_driver); ++} ++subsys_initcall(tps68470_regulator_init); ++ ++static void __exit tps68470_regulator_exit(void) ++{ ++ platform_driver_unregister(&tps68470_regulator_driver); ++} ++module_exit(tps68470_regulator_exit); ++ ++MODULE_ALIAS("platform:tps68470-regulator"); ++MODULE_DESCRIPTION("TPS68470 voltage regulator driver"); ++MODULE_LICENSE("GPL v2"); +-- +2.33.1 + +From 181225a6450777154be1b438d703195721f50aae Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:01 +0200 +Subject: [PATCH] clk: Introduce clk-tps68470 driver + +The TPS68470 PMIC provides Clocks, GPIOs and Regulators. At present in +the kernel the Regulators and Clocks are controlled by an OpRegion +driver designed to work with power control methods defined in ACPI, but +some platforms lack those methods, meaning drivers need to be able to +consume the resources of these chips through the usual frameworks. + +This commit adds a driver for the clocks provided by the tps68470, +and is designed to bind to the platform_device registered by the +intel_skl_int3472 module. + +This is based on this out of tree driver written by Intel: +https://github.com/intel/linux-intel-lts/blob/4.14/base/drivers/clk/clk-tps68470.c +with various cleanups added. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/clk/Kconfig | 6 + + drivers/clk/Makefile | 1 + + drivers/clk/clk-tps68470.c | 256 +++++++++++++++++++++++++++++++++++ + include/linux/mfd/tps68470.h | 11 ++ + 4 files changed, 274 insertions(+) + create mode 100644 drivers/clk/clk-tps68470.c + +diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig +index e873f9ea2e65..f5255b085fe2 100644 +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -169,6 +169,12 @@ config COMMON_CLK_CDCE706 + help + This driver supports TI CDCE706 programmable 3-PLL clock synthesizer. + ++config COMMON_CLK_TPS68470 ++ tristate "Clock Driver for TI TPS68470 PMIC" ++ depends on I2C && REGMAP_I2C && INTEL_SKL_INT3472 ++ help ++ This driver supports the clocks provided by TPS68470 ++ + config COMMON_CLK_CDCE925 + tristate "Clock driver for TI CDCE913/925/937/949 devices" + depends on I2C +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index 2b91d34c582b..1f7dad3461f2 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -63,6 +63,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o + obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o + obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o + obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o ++obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o + obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o + obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o + obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o +diff --git a/drivers/clk/clk-tps68470.c b/drivers/clk/clk-tps68470.c +new file mode 100644 +index 000000000000..27e8cbd0f60e +--- /dev/null ++++ b/drivers/clk/clk-tps68470.c +@@ -0,0 +1,256 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Clock driver for TPS68470 PMIC ++ * ++ * Copyright (C) 2018 Intel Corporation ++ * ++ * Authors: ++ * Zaikuo Wang ++ * Tianshu Qiu ++ * Jian Xu Zheng ++ * Yuning Pu ++ * Antti Laakso ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TPS68470_CLK_NAME "tps68470-clk" ++ ++#define to_tps68470_clkdata(clkd) \ ++ container_of(clkd, struct tps68470_clkdata, clkout_hw) ++ ++struct tps68470_clkout_freqs { ++ unsigned long freq; ++ unsigned int xtaldiv; ++ unsigned int plldiv; ++ unsigned int postdiv; ++ unsigned int buckdiv; ++ unsigned int boostdiv; ++} clk_freqs[] = { ++/* ++ * The PLL is used to multiply the crystal oscillator ++ * frequency range of 3 MHz to 27 MHz by a programmable ++ * factor of F = (M/N)*(1/P) such that the output ++ * available at the HCLK_A or HCLK_B pins are in the range ++ * of 4 MHz to 64 MHz in increments of 0.1 MHz ++ * ++ * hclk_# = osc_in * (((plldiv*2)+320) / (xtaldiv+30)) * (1 / 2^postdiv) ++ * ++ * PLL_REF_CLK should be as close as possible to 100kHz ++ * PLL_REF_CLK = input clk / XTALDIV[7:0] + 30) ++ * ++ * PLL_VCO_CLK = (PLL_REF_CLK * (plldiv*2 + 320)) ++ * ++ * BOOST should be as close as possible to 2Mhz ++ * BOOST = PLL_VCO_CLK / (BOOSTDIV[4:0] + 16) * ++ * ++ * BUCK should be as close as possible to 5.2Mhz ++ * BUCK = PLL_VCO_CLK / (BUCKDIV[3:0] + 5) ++ * ++ * osc_in xtaldiv plldiv postdiv hclk_# ++ * 20Mhz 170 32 1 19.2Mhz ++ * 20Mhz 170 40 1 20Mhz ++ * 20Mhz 170 80 1 24Mhz ++ * ++ */ ++ { 19200000, 170, 32, 1, 2, 3 }, ++ { 20000000, 170, 40, 1, 3, 4 }, ++ { 24000000, 170, 80, 1, 4, 8 }, ++}; ++ ++struct tps68470_clkdata { ++ struct clk_hw clkout_hw; ++ struct regmap *regmap; ++ struct clk *clk; ++ int clk_cfg_idx; ++}; ++ ++static int tps68470_clk_is_prepared(struct clk_hw *hw) ++{ ++ struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); ++ int val; ++ ++ if (regmap_read(clkdata->regmap, TPS68470_REG_PLLCTL, &val)) ++ return 0; ++ ++ return val & TPS68470_PLL_EN_MASK; ++} ++ ++static int tps68470_clk_prepare(struct clk_hw *hw) ++{ ++ struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); ++ int idx = clkdata->clk_cfg_idx; ++ ++ regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, clk_freqs[idx].boostdiv); ++ regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, clk_freqs[idx].buckdiv); ++ regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, TPS68470_PLLSWR_DEFAULT); ++ regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, clk_freqs[idx].xtaldiv); ++ regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, clk_freqs[idx].plldiv); ++ regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, clk_freqs[idx].postdiv); ++ regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV2, clk_freqs[idx].postdiv); ++ regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, TPS68470_CLKCFG2_DRV_STR_2MA); ++ ++ regmap_write(clkdata->regmap, TPS68470_REG_PLLCTL, ++ TPS68470_OSC_EXT_CAP_DEFAULT << TPS68470_OSC_EXT_CAP_SHIFT | ++ TPS68470_CLK_SRC_XTAL << TPS68470_CLK_SRC_SHIFT); ++ ++ regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, ++ (TPS68470_PLL_OUTPUT_ENABLE << ++ TPS68470_OUTPUT_A_SHIFT) | ++ (TPS68470_PLL_OUTPUT_ENABLE << ++ TPS68470_OUTPUT_B_SHIFT)); ++ ++ regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, ++ TPS68470_PLL_EN_MASK, TPS68470_PLL_EN_MASK); ++ ++ return 0; ++} ++ ++static void tps68470_clk_unprepare(struct clk_hw *hw) ++{ ++ struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); ++ ++ /* disable clock first*/ ++ regmap_update_bits(clkdata->regmap, TPS68470_REG_PLLCTL, TPS68470_PLL_EN_MASK, 0); ++ ++ /* write hw defaults */ ++ regmap_write(clkdata->regmap, TPS68470_REG_BOOSTDIV, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_BUCKDIV, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_PLLSWR, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_XTALDIV, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_PLLDIV, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_POSTDIV, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG2, 0); ++ regmap_write(clkdata->regmap, TPS68470_REG_CLKCFG1, 0); ++} ++ ++static unsigned long tps68470_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); ++ ++ return clk_freqs[clkdata->clk_cfg_idx].freq; ++} ++ ++static int tps68470_clk_cfg_lookup(unsigned long rate) ++{ ++ long diff, best_diff = LONG_MAX; ++ int i, best_idx = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(clk_freqs); i++) { ++ diff = clk_freqs[i].freq - rate; ++ if (diff == 0) ++ return i; ++ ++ diff = abs(diff); ++ if (diff < best_diff) { ++ best_diff = diff; ++ best_idx = i; ++ } ++ } ++ ++ return best_idx; ++} ++ ++static long tps68470_clk_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ int idx = tps68470_clk_cfg_lookup(rate); ++ ++ return clk_freqs[idx].freq; ++} ++ ++static int tps68470_clk_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct tps68470_clkdata *clkdata = to_tps68470_clkdata(hw); ++ int idx = tps68470_clk_cfg_lookup(rate); ++ ++ if (rate != clk_freqs[idx].freq) ++ return -EINVAL; ++ ++ clkdata->clk_cfg_idx = idx; ++ return 0; ++} ++ ++static const struct clk_ops tps68470_clk_ops = { ++ .is_prepared = tps68470_clk_is_prepared, ++ .prepare = tps68470_clk_prepare, ++ .unprepare = tps68470_clk_unprepare, ++ .recalc_rate = tps68470_clk_recalc_rate, ++ .round_rate = tps68470_clk_round_rate, ++ .set_rate = tps68470_clk_set_rate, ++}; ++ ++static struct clk_init_data tps68470_clk_initdata = { ++ .name = TPS68470_CLK_NAME, ++ .ops = &tps68470_clk_ops, ++}; ++ ++static int tps68470_clk_probe(struct platform_device *pdev) ++{ ++ struct tps68470_clk_platform_data *pdata = pdev->dev.platform_data; ++ struct tps68470_clkdata *tps68470_clkdata; ++ int ret; ++ ++ tps68470_clkdata = devm_kzalloc(&pdev->dev, sizeof(*tps68470_clkdata), ++ GFP_KERNEL); ++ if (!tps68470_clkdata) ++ return -ENOMEM; ++ ++ tps68470_clkdata->regmap = dev_get_drvdata(pdev->dev.parent); ++ tps68470_clkdata->clkout_hw.init = &tps68470_clk_initdata; ++ tps68470_clkdata->clk = devm_clk_register(&pdev->dev, &tps68470_clkdata->clkout_hw); ++ if (IS_ERR(tps68470_clkdata->clk)) ++ return PTR_ERR(tps68470_clkdata->clk); ++ ++ ret = devm_clk_hw_register_clkdev(&pdev->dev, &tps68470_clkdata->clkout_hw, ++ TPS68470_CLK_NAME, NULL); ++ if (ret) ++ return ret; ++ ++ if (pdata) { ++ ret = devm_clk_hw_register_clkdev(&pdev->dev, ++ &tps68470_clkdata->clkout_hw, ++ pdata->consumer_con_id, ++ pdata->consumer_dev_name); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver tps68470_clk_driver = { ++ .driver = { ++ .name = TPS68470_CLK_NAME, ++ }, ++ .probe = tps68470_clk_probe, ++}; ++ ++/* ++ * The ACPI tps68470 probe-ordering depends on the clk/gpio/regulator drivers ++ * registering before the drivers for the camera-sensors which use them bind. ++ * subsys_initcall() ensures this when the drivers are builtin. ++ */ ++static int __init tps68470_clk_init(void) ++{ ++ return platform_driver_register(&tps68470_clk_driver); ++} ++subsys_initcall(tps68470_clk_init); ++ ++static void __exit tps68470_clk_exit(void) ++{ ++ platform_driver_unregister(&tps68470_clk_driver); ++} ++module_exit(tps68470_clk_exit); ++ ++MODULE_ALIAS("platform:tps68470-clk"); ++MODULE_DESCRIPTION("clock driver for TPS68470 pmic"); ++MODULE_LICENSE("GPL"); +diff --git a/include/linux/mfd/tps68470.h b/include/linux/mfd/tps68470.h +index ffe81127d91c..7807fa329db0 100644 +--- a/include/linux/mfd/tps68470.h ++++ b/include/linux/mfd/tps68470.h +@@ -75,6 +75,17 @@ + #define TPS68470_CLKCFG1_MODE_A_MASK GENMASK(1, 0) + #define TPS68470_CLKCFG1_MODE_B_MASK GENMASK(3, 2) + ++#define TPS68470_CLKCFG2_DRV_STR_2MA 0x05 ++#define TPS68470_PLL_OUTPUT_ENABLE 0x02 ++#define TPS68470_CLK_SRC_XTAL BIT(0) ++#define TPS68470_PLLSWR_DEFAULT GENMASK(1, 0) ++#define TPS68470_OSC_EXT_CAP_DEFAULT 0x05 ++ ++#define TPS68470_OUTPUT_A_SHIFT 0x00 ++#define TPS68470_OUTPUT_B_SHIFT 0x02 ++#define TPS68470_CLK_SRC_SHIFT GENMASK(2, 0) ++#define TPS68470_OSC_EXT_CAP_SHIFT BIT(2) ++ + #define TPS68470_GPIO_CTL_REG_A(x) (TPS68470_REG_GPCTL0A + (x) * 2) + #define TPS68470_GPIO_CTL_REG_B(x) (TPS68470_REG_GPCTL0B + (x) * 2) + #define TPS68470_GPIO_MODE_MASK GENMASK(1, 0) +-- +2.33.1 + +From ec50764e4b37f60008115a72663d2363cd983d0b Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Sun, 10 Oct 2021 20:57:02 +0200 +Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain + +The TPS68470 PMIC has an I2C passthrough mode through which I2C traffic +can be forwarded to a device connected to the PMIC as though it were +connected directly to the system bus. Enable this mode when the chip +is initialised. + +Signed-off-by: Daniel Scally +Patchset: cameras +--- + .../x86/intel/int3472/intel_skl_int3472_tps68470.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c b/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c +index c05b4cf502fe..42e688f4cad4 100644 +--- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c ++++ b/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c +@@ -45,6 +45,13 @@ static int tps68470_chip_init(struct device *dev, struct regmap *regmap) + return ret; + } + ++ /* Enable I2C daisy chain */ ++ ret = regmap_write(regmap, TPS68470_REG_S_I2C_CTL, 0x03); ++ if (ret) { ++ dev_err(dev, "Failed to enable i2c daisy chain\n"); ++ return ret; ++ } ++ + dev_info(dev, "TPS68470 REVID: 0x%02x\n", version); + + return 0; +-- +2.33.1 + +From eb388fbf65f46e896f04075b223c6a07a1cd00b7 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:03 +0200 +Subject: [PATCH] platform/x86: int3472: Split into 2 drivers + +The intel_skl_int3472.ko module contains 2 separate drivers, +the int3472_discrete platform driver and the int3472_tps68470 +I2C-driver. + +These 2 drivers contain very little shared code, only +skl_int3472_get_acpi_buffer() and skl_int3472_fill_cldb() are +shared. + +Split the module into 2 drivers, linking the little shared code +directly into both. + +This will allow us to add soft-module dependencies for the +tps68470 clk, gpio and regulator drivers to the new +intel_skl_int3472_tps68470.ko to help with probe ordering issues +without causing these modules to get loaded on boards which only +use the int3472_discrete platform driver. + +While at it also rename the .c and .h files to remove the +cumbersome intel_skl_int3472_ prefix. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/platform/x86/intel/int3472/Makefile | 9 ++-- + ...lk_and_regulator.c => clk_and_regulator.c} | 2 +- + drivers/platform/x86/intel/int3472/common.c | 54 +++++++++++++++++++ + .../{intel_skl_int3472_common.h => common.h} | 3 -- + ...ntel_skl_int3472_discrete.c => discrete.c} | 28 ++++++++-- + ...ntel_skl_int3472_tps68470.c => tps68470.c} | 23 +++++++- + 6 files changed, 105 insertions(+), 14 deletions(-) + rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_clk_and_regulator.c => clk_and_regulator.c} (99%) + create mode 100644 drivers/platform/x86/intel/int3472/common.c + rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_common.h => common.h} (94%) + rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_discrete.c => discrete.c} (93%) + rename drivers/platform/x86/intel/int3472/{intel_skl_int3472_tps68470.c => tps68470.c} (85%) + +diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile +index 48bd97f0a04e..4a4b2518ea16 100644 +--- a/drivers/platform/x86/intel/int3472/Makefile ++++ b/drivers/platform/x86/intel/int3472/Makefile +@@ -1,5 +1,4 @@ +-obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472.o +-intel_skl_int3472-objs := intel_skl_int3472_common.o \ +- intel_skl_int3472_discrete.o \ +- intel_skl_int3472_tps68470.o \ +- intel_skl_int3472_clk_and_regulator.o ++obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \ ++ intel_skl_int3472_tps68470.o ++intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o ++intel_skl_int3472_tps68470-y := tps68470.o common.o +diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c +similarity index 99% +rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c +rename to drivers/platform/x86/intel/int3472/clk_and_regulator.c +index 1700e7557a82..1cf958983e86 100644 +--- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_clk_and_regulator.c ++++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c +@@ -9,7 +9,7 @@ + #include + #include + +-#include "intel_skl_int3472_common.h" ++#include "common.h" + + /* + * The regulators have to have .ops to be valid, but the only ops we actually +diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c +new file mode 100644 +index 000000000000..350655a9515b +--- /dev/null ++++ b/drivers/platform/x86/intel/int3472/common.c +@@ -0,0 +1,54 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Author: Dan Scally */ ++ ++#include ++#include ++ ++#include "common.h" ++ ++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; ++ ++ status = acpi_evaluate_object(handle, id, NULL, &buffer); ++ if (ACPI_FAILURE(status)) ++ return ERR_PTR(-ENODEV); ++ ++ obj = buffer.pointer; ++ if (!obj) ++ return ERR_PTR(-ENODEV); ++ ++ if (obj->type != ACPI_TYPE_BUFFER) { ++ acpi_handle_err(handle, "%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; ++ ++ obj = skl_int3472_get_acpi_buffer(adev, "CLDB"); ++ if (IS_ERR(obj)) ++ return PTR_ERR(obj); ++ ++ if (obj->buffer.length > sizeof(*cldb)) { ++ acpi_handle_err(adev->handle, "The CLDB buffer is too large\n"); ++ ret = -EINVAL; ++ goto out_free_obj; ++ } ++ ++ memcpy(cldb, obj->buffer.pointer, obj->buffer.length); ++ ret = 0; ++ ++out_free_obj: ++ kfree(obj); ++ return ret; ++} +diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h b/drivers/platform/x86/intel/int3472/common.h +similarity index 94% +rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h +rename to drivers/platform/x86/intel/int3472/common.h +index 714fde73b524..d14944ee8586 100644 +--- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_common.h ++++ b/drivers/platform/x86/intel/int3472/common.h +@@ -105,9 +105,6 @@ struct int3472_discrete_device { + struct gpiod_lookup_table gpios; + }; + +-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); + 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/int3472/intel_skl_int3472_discrete.c b/drivers/platform/x86/intel/int3472/discrete.c +similarity index 93% +rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c +rename to drivers/platform/x86/intel/int3472/discrete.c +index 9fe0a2527e1c..856602a2f6bb 100644 +--- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_discrete.c ++++ b/drivers/platform/x86/intel/int3472/discrete.c +@@ -14,7 +14,7 @@ + #include + #include + +-#include "intel_skl_int3472_common.h" ++#include "common.h" + + /* + * 79234640-9e10-4fea-a5c1-b5aa8b19756f +@@ -332,7 +332,9 @@ static int skl_int3472_parse_crs(struct int3472_discrete_device *int3472) + return 0; + } + +-int skl_int3472_discrete_probe(struct platform_device *pdev) ++static int skl_int3472_discrete_remove(struct platform_device *pdev); ++ ++static int skl_int3472_discrete_probe(struct platform_device *pdev) + { + struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); + struct int3472_discrete_device *int3472; +@@ -395,7 +397,7 @@ int skl_int3472_discrete_probe(struct platform_device *pdev) + return ret; + } + +-int skl_int3472_discrete_remove(struct platform_device *pdev) ++static int skl_int3472_discrete_remove(struct platform_device *pdev) + { + struct int3472_discrete_device *int3472 = platform_get_drvdata(pdev); + +@@ -411,3 +413,23 @@ int skl_int3472_discrete_remove(struct platform_device *pdev) + + return 0; + } ++ ++static const struct acpi_device_id int3472_device_id[] = { ++ { "INT3472", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(acpi, int3472_device_id); ++ ++static struct platform_driver int3472_discrete = { ++ .driver = { ++ .name = "int3472-discrete", ++ .acpi_match_table = int3472_device_id, ++ }, ++ .probe = skl_int3472_discrete_probe, ++ .remove = skl_int3472_discrete_remove, ++}; ++module_platform_driver(int3472_discrete); ++ ++MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI Discrete Device Driver"); ++MODULE_AUTHOR("Daniel Scally "); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c +similarity index 85% +rename from drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c +rename to drivers/platform/x86/intel/int3472/tps68470.c +index 42e688f4cad4..b94cf66ab61f 100644 +--- a/drivers/platform/x86/intel/int3472/intel_skl_int3472_tps68470.c ++++ b/drivers/platform/x86/intel/int3472/tps68470.c +@@ -7,7 +7,7 @@ + #include + #include + +-#include "intel_skl_int3472_common.h" ++#include "common.h" + + #define DESIGNED_FOR_CHROMEOS 1 + #define DESIGNED_FOR_WINDOWS 2 +@@ -102,7 +102,7 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) + return DESIGNED_FOR_WINDOWS; + } + +-int skl_int3472_tps68470_probe(struct i2c_client *client) ++static int skl_int3472_tps68470_probe(struct i2c_client *client) + { + struct acpi_device *adev = ACPI_COMPANION(&client->dev); + struct regmap *regmap; +@@ -142,3 +142,22 @@ int skl_int3472_tps68470_probe(struct i2c_client *client) + + return ret; + } ++ ++static const struct acpi_device_id int3472_device_id[] = { ++ { "INT3472", 0 }, ++ { } ++}; ++MODULE_DEVICE_TABLE(acpi, int3472_device_id); ++ ++static struct i2c_driver int3472_tps68470 = { ++ .driver = { ++ .name = "int3472-tps68470", ++ .acpi_match_table = int3472_device_id, ++ }, ++ .probe_new = skl_int3472_tps68470_probe, ++}; ++module_i2c_driver(int3472_tps68470); ++ ++MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver"); ++MODULE_AUTHOR("Daniel Scally "); ++MODULE_LICENSE("GPL v2"); +-- +2.33.1 + +From d821fc0e552317e1adc05035a95b2c7ad646f1b6 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:04 +0200 +Subject: [PATCH] platform/x86: int3472: Add get_sensor_adev_and_name() helper + +The discrete.c code is not the only code which needs to lookup the +acpi_device and device-name for the sensor for which the INT3472 +ACPI-device is a GPIO/clk/regulator provider. + +The tps68470.c code also needs this functionality, so factor this +out into a new get_sensor_adev_and_name() helper. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/platform/x86/intel/int3472/common.c | 28 +++++++++++++++++++ + drivers/platform/x86/intel/int3472/common.h | 3 ++ + drivers/platform/x86/intel/int3472/discrete.c | 22 +++------------ + 3 files changed, 35 insertions(+), 18 deletions(-) + +diff --git a/drivers/platform/x86/intel/int3472/common.c b/drivers/platform/x86/intel/int3472/common.c +index 350655a9515b..77cf058e4168 100644 +--- a/drivers/platform/x86/intel/int3472/common.c ++++ b/drivers/platform/x86/intel/int3472/common.c +@@ -52,3 +52,31 @@ int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb) + kfree(obj); + return ret; + } ++ ++/* sensor_adev_ret may be NULL, name_ret must not be NULL */ ++int skl_int3472_get_sensor_adev_and_name(struct device *dev, ++ struct acpi_device **sensor_adev_ret, ++ const char **name_ret) ++{ ++ struct acpi_device *adev = ACPI_COMPANION(dev); ++ struct acpi_device *sensor; ++ int ret = 0; ++ ++ sensor = acpi_dev_get_first_consumer_dev(adev); ++ if (!sensor) { ++ dev_err(dev, "INT3472 seems to have no dependents.\n"); ++ return -ENODEV; ++ } ++ ++ *name_ret = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT, ++ acpi_dev_name(sensor)); ++ if (!*name_ret) ++ ret = -ENOMEM; ++ ++ if (ret == 0 && sensor_adev_ret) ++ *sensor_adev_ret = sensor; ++ else ++ acpi_dev_put(sensor); ++ ++ return ret; ++} +diff --git a/drivers/platform/x86/intel/int3472/common.h b/drivers/platform/x86/intel/int3472/common.h +index d14944ee8586..53270d19c73a 100644 +--- a/drivers/platform/x86/intel/int3472/common.h ++++ b/drivers/platform/x86/intel/int3472/common.h +@@ -108,6 +108,9 @@ struct int3472_discrete_device { + 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); ++int skl_int3472_get_sensor_adev_and_name(struct device *dev, ++ struct acpi_device **sensor_adev_ret, ++ const char **name_ret); + + int skl_int3472_register_clock(struct int3472_discrete_device *int3472); + void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472); +diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c +index 856602a2f6bb..22a4894f1cc7 100644 +--- a/drivers/platform/x86/intel/int3472/discrete.c ++++ b/drivers/platform/x86/intel/int3472/discrete.c +@@ -363,19 +363,10 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) + int3472->dev = &pdev->dev; + platform_set_drvdata(pdev, int3472); + +- int3472->sensor = acpi_dev_get_first_consumer_dev(adev); +- if (!int3472->sensor) { +- dev_err(&pdev->dev, "INT3472 seems to have no dependents.\n"); +- return -ENODEV; +- } +- +- int3472->sensor_name = devm_kasprintf(int3472->dev, GFP_KERNEL, +- I2C_DEV_NAME_FORMAT, +- acpi_dev_name(int3472->sensor)); +- if (!int3472->sensor_name) { +- ret = -ENOMEM; +- goto err_put_sensor; +- } ++ ret = skl_int3472_get_sensor_adev_and_name(&pdev->dev, &int3472->sensor, ++ &int3472->sensor_name); ++ if (ret) ++ return ret; + + /* + * Initialising this list means we can call gpiod_remove_lookup_table() +@@ -390,11 +381,6 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) + } + + return 0; +- +-err_put_sensor: +- acpi_dev_put(int3472->sensor); +- +- return ret; + } + + static int skl_int3472_discrete_remove(struct platform_device *pdev) +-- +2.33.1 + +From 918b0938a49bc4bbda3908f71025aa7864dda093 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:05 +0200 +Subject: [PATCH] platform/x86: int3472: Pass tps68470_clk_platform_data to the + tps68470-regulator MFD-cell + +Pass tps68470_clk_platform_data to the tps68470-clk MFD-cell, +so that sensors which use the TPS68470 can find their clock. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/platform/x86/intel/int3472/tps68470.c | 33 ++++++++++++++----- + 1 file changed, 25 insertions(+), 8 deletions(-) + +diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c +index b94cf66ab61f..78e34e7b6969 100644 +--- a/drivers/platform/x86/intel/int3472/tps68470.c ++++ b/drivers/platform/x86/intel/int3472/tps68470.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + + #include "common.h" +@@ -17,12 +18,6 @@ static const struct mfd_cell tps68470_cros[] = { + { .name = "tps68470_pmic_opregion" }, + }; + +-static const struct mfd_cell tps68470_win[] = { +- { .name = "tps68470-gpio" }, +- { .name = "tps68470-clk" }, +- { .name = "tps68470-regulator" }, +-}; +- + static const struct regmap_config tps68470_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -105,10 +100,17 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) + static int skl_int3472_tps68470_probe(struct i2c_client *client) + { + struct acpi_device *adev = ACPI_COMPANION(&client->dev); ++ struct tps68470_clk_platform_data clk_pdata = {}; ++ struct mfd_cell *cells; + struct regmap *regmap; + int device_type; + int ret; + ++ ret = skl_int3472_get_sensor_adev_and_name(&client->dev, NULL, ++ &clk_pdata.consumer_dev_name); ++ if (ret) ++ return ret; ++ + regmap = devm_regmap_init_i2c(client, &tps68470_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Failed to create regmap: %ld\n", PTR_ERR(regmap)); +@@ -126,9 +128,24 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) + device_type = skl_int3472_tps68470_calc_type(adev); + switch (device_type) { + case DESIGNED_FOR_WINDOWS: +- ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, +- tps68470_win, ARRAY_SIZE(tps68470_win), ++ cells = kcalloc(3, sizeof(*cells), GFP_KERNEL); ++ if (!cells) ++ return -ENOMEM; ++ ++ cells[0].name = "tps68470-clk"; ++ cells[0].platform_data = &clk_pdata; ++ cells[0].pdata_size = sizeof(clk_pdata); ++ cells[1].name = "tps68470-regulator"; ++ /* ++ * The GPIO cell must be last because acpi_gpiochip_add() calls ++ * acpi_dev_clear_dependencies() and the clk + regulators must ++ * be ready when this happens. ++ */ ++ cells[2].name = "tps68470-gpio"; ++ ++ ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, cells, 3, + NULL, 0, NULL); ++ kfree(cells); + break; + case DESIGNED_FOR_CHROMEOS: + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, +-- +2.33.1 + +From fbb8fa4c4878ecf198146c36461105c0ab408edf Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:06 +0200 +Subject: [PATCH] platform/x86: int3472: Pass tps68470_regulator_platform_data + to the tps68470-regulator MFD-cell + +Pass tps68470_regulator_platform_data to the tps68470-regulator +MFD-cell, specifying the voltages of the various regulators and +tying the regulators to the sensor supplies so that sensors which use +the TPS68470 can find their regulators. + +Since the voltages and supply connections are board-specific, this +introduces a DMI matches int3472_tps68470_board_data struct which +contains the necessary per-board info. + +This per-board info also includes GPIO lookup information for the +sensor GPIOs which may be connected to the tps68470 gpios. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/platform/x86/intel/int3472/Makefile | 2 +- + drivers/platform/x86/intel/int3472/tps68470.c | 43 +++++-- + drivers/platform/x86/intel/int3472/tps68470.h | 25 ++++ + .../x86/intel/int3472/tps68470_board_data.c | 118 ++++++++++++++++++ + 4 files changed, 180 insertions(+), 8 deletions(-) + create mode 100644 drivers/platform/x86/intel/int3472/tps68470.h + create mode 100644 drivers/platform/x86/intel/int3472/tps68470_board_data.c + +diff --git a/drivers/platform/x86/intel/int3472/Makefile b/drivers/platform/x86/intel/int3472/Makefile +index 4a4b2518ea16..ca56e7eea781 100644 +--- a/drivers/platform/x86/intel/int3472/Makefile ++++ b/drivers/platform/x86/intel/int3472/Makefile +@@ -1,4 +1,4 @@ + obj-$(CONFIG_INTEL_SKL_INT3472) += intel_skl_int3472_discrete.o \ + intel_skl_int3472_tps68470.o + intel_skl_int3472_discrete-y := discrete.o clk_and_regulator.o common.o +-intel_skl_int3472_tps68470-y := tps68470.o common.o ++intel_skl_int3472_tps68470-y := tps68470.o tps68470_board_data.o common.o +diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c +index 78e34e7b6969..aae24d228770 100644 +--- a/drivers/platform/x86/intel/int3472/tps68470.c ++++ b/drivers/platform/x86/intel/int3472/tps68470.c +@@ -9,6 +9,7 @@ + #include + + #include "common.h" ++#include "tps68470.h" + + #define DESIGNED_FOR_CHROMEOS 1 + #define DESIGNED_FOR_WINDOWS 2 +@@ -100,6 +101,7 @@ static int skl_int3472_tps68470_calc_type(struct acpi_device *adev) + static int skl_int3472_tps68470_probe(struct i2c_client *client) + { + struct acpi_device *adev = ACPI_COMPANION(&client->dev); ++ const struct int3472_tps68470_board_data *board_data; + struct tps68470_clk_platform_data clk_pdata = {}; + struct mfd_cell *cells; + struct regmap *regmap; +@@ -128,6 +130,12 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) + device_type = skl_int3472_tps68470_calc_type(adev); + switch (device_type) { + case DESIGNED_FOR_WINDOWS: ++ board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); ++ if (!board_data) { ++ dev_err(&client->dev, "No board-data found for this laptop/tablet model\n"); ++ return -ENODEV; ++ } ++ + cells = kcalloc(3, sizeof(*cells), GFP_KERNEL); + if (!cells) + return -ENOMEM; +@@ -136,6 +144,8 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) + cells[0].platform_data = &clk_pdata; + cells[0].pdata_size = sizeof(clk_pdata); + cells[1].name = "tps68470-regulator"; ++ cells[1].platform_data = (void *)board_data->tps68470_regulator_pdata; ++ cells[1].pdata_size = sizeof(struct tps68470_regulator_platform_data); + /* + * The GPIO cell must be last because acpi_gpiochip_add() calls + * acpi_dev_clear_dependencies() and the clk + regulators must +@@ -143,9 +153,15 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) + */ + cells[2].name = "tps68470-gpio"; + ++ gpiod_add_lookup_table(board_data->tps68470_gpio_lookup_table); ++ + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, cells, 3, + NULL, 0, NULL); + kfree(cells); ++ ++ if (ret) ++ gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); ++ + break; + case DESIGNED_FOR_CHROMEOS: + ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, +@@ -160,18 +176,31 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) + return ret; + } + ++static int skl_int3472_tps68470_remove(struct i2c_client *client) ++{ ++ const struct int3472_tps68470_board_data *board_data; ++ ++ board_data = int3472_tps68470_get_board_data(dev_name(&client->dev)); ++ if (board_data) ++ gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_table); ++ ++ return 0; ++} ++ ++ + static const struct acpi_device_id int3472_device_id[] = { +- { "INT3472", 0 }, +- { } ++ { "INT3472", 0 }, ++ { } + }; + MODULE_DEVICE_TABLE(acpi, int3472_device_id); + + static struct i2c_driver int3472_tps68470 = { +- .driver = { +- .name = "int3472-tps68470", +- .acpi_match_table = int3472_device_id, +- }, +- .probe_new = skl_int3472_tps68470_probe, ++ .driver = { ++ .name = "int3472-tps68470", ++ .acpi_match_table = int3472_device_id, ++ }, ++ .probe_new = skl_int3472_tps68470_probe, ++ .remove = skl_int3472_tps68470_remove, + }; + module_i2c_driver(int3472_tps68470); + +diff --git a/drivers/platform/x86/intel/int3472/tps68470.h b/drivers/platform/x86/intel/int3472/tps68470.h +new file mode 100644 +index 000000000000..cfd33eb62740 +--- /dev/null ++++ b/drivers/platform/x86/intel/int3472/tps68470.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * TI TPS68470 PMIC platform data definition. ++ * ++ * Copyright (c) 2021 Red Hat Inc. ++ * ++ * Red Hat authors: ++ * Hans de Goede ++ */ ++ ++#ifndef _INTEL_SKL_INT3472_TPS68470_H ++#define _INTEL_SKL_INT3472_TPS68470_H ++ ++struct gpiod_lookup_table; ++struct tps68470_regulator_platform_data; ++ ++struct int3472_tps68470_board_data { ++ const char *dev_name; ++ struct gpiod_lookup_table *tps68470_gpio_lookup_table; ++ const struct tps68470_regulator_platform_data *tps68470_regulator_pdata; ++}; ++ ++const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name); ++ ++#endif +diff --git a/drivers/platform/x86/intel/int3472/tps68470_board_data.c b/drivers/platform/x86/intel/int3472/tps68470_board_data.c +new file mode 100644 +index 000000000000..96954a789bb8 +--- /dev/null ++++ b/drivers/platform/x86/intel/int3472/tps68470_board_data.c +@@ -0,0 +1,118 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * TI TPS68470 PMIC platform data definition. ++ * ++ * Copyright (c) 2021 Dan Scally ++ * Copyright (c) 2021 Red Hat Inc. ++ * ++ * Red Hat authors: ++ * Hans de Goede ++ */ ++ ++#include ++#include ++#include ++#include ++#include "tps68470.h" ++ ++static struct regulator_consumer_supply int347a_core_consumer_supplies[] = { ++ REGULATOR_SUPPLY("dvdd", "i2c-INT347A:00"), ++}; ++ ++static struct regulator_consumer_supply int347a_ana_consumer_supplies[] = { ++ REGULATOR_SUPPLY("avdd", "i2c-INT347A:00"), ++}; ++ ++static struct regulator_consumer_supply int347a_vsio_consumer_supplies[] = { ++ REGULATOR_SUPPLY("dovdd", "i2c-INT347A:00"), ++}; ++ ++static const struct regulator_init_data surface_go_tps68470_core_reg_init_data = { ++ .constraints = { ++ .min_uV = 1200000, ++ .max_uV = 1200000, ++ .apply_uV = 1, ++ .valid_ops_mask = REGULATOR_CHANGE_STATUS, ++ }, ++ .num_consumer_supplies = ARRAY_SIZE(int347a_core_consumer_supplies), ++ .consumer_supplies = int347a_core_consumer_supplies, ++}; ++ ++static const struct regulator_init_data surface_go_tps68470_ana_reg_init_data = { ++ .constraints = { ++ .min_uV = 2815200, ++ .max_uV = 2815200, ++ .apply_uV = 1, ++ .valid_ops_mask = REGULATOR_CHANGE_STATUS, ++ }, ++ .num_consumer_supplies = ARRAY_SIZE(int347a_ana_consumer_supplies), ++ .consumer_supplies = int347a_ana_consumer_supplies, ++}; ++ ++static const struct regulator_init_data surface_go_tps68470_vsio_reg_init_data = { ++ .constraints = { ++ .min_uV = 1800600, ++ .max_uV = 1800600, ++ .apply_uV = 1, ++ .valid_ops_mask = REGULATOR_CHANGE_STATUS, ++ }, ++ .num_consumer_supplies = ARRAY_SIZE(int347a_vsio_consumer_supplies), ++ .consumer_supplies = int347a_vsio_consumer_supplies, ++}; ++ ++static const struct tps68470_regulator_platform_data surface_go_tps68470_pdata = { ++ .reg_init_data = { ++ [TPS68470_CORE] = &surface_go_tps68470_core_reg_init_data, ++ [TPS68470_ANA] = &surface_go_tps68470_ana_reg_init_data, ++ [TPS68470_VSIO] = &surface_go_tps68470_vsio_reg_init_data, ++ }, ++}; ++ ++static struct gpiod_lookup_table surface_go_tps68470_gpios = { ++ .dev_id = "i2c-INT347A:00", ++ .table = { ++ GPIO_LOOKUP("tps68470-gpio", 9, "reset", GPIO_ACTIVE_LOW), ++ GPIO_LOOKUP("tps68470-gpio", 7, "powerdown", GPIO_ACTIVE_LOW) ++ } ++}; ++ ++static const struct int3472_tps68470_board_data surface_go_tps68470_board_data = { ++ .dev_name = "i2c-INT3472:05", ++ .tps68470_gpio_lookup_table = &surface_go_tps68470_gpios, ++ .tps68470_regulator_pdata = &surface_go_tps68470_pdata, ++}; ++ ++static const struct dmi_system_id int3472_tps68470_board_data_table[] = { ++ { ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go"), ++ }, ++ .driver_data = (void *)&surface_go_tps68470_board_data, ++ }, ++ { ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Go 2"), ++ }, ++ .driver_data = (void *)&surface_go_tps68470_board_data, ++ }, ++ { } ++}; ++ ++const struct int3472_tps68470_board_data *int3472_tps68470_get_board_data(const char *dev_name) ++{ ++ const struct int3472_tps68470_board_data *board_data; ++ const struct dmi_system_id *match; ++ ++ match = dmi_first_match(int3472_tps68470_board_data_table); ++ while (match) { ++ board_data = match->driver_data; ++ if (strcmp(board_data->dev_name, dev_name) == 0) ++ return board_data; ++ ++ dmi_first_match(++match); ++ } ++ ++ return NULL; ++} +-- +2.33.1 + +From 9bc7fde514ecc4713e35e2538db6a85abe699442 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 10 Oct 2021 20:57:07 +0200 +Subject: [PATCH] platform/x86: int3472: Deal with probe ordering issues + +The clk and regulator frameworks expect clk/regulator consumer-devices +to have info about the consumed clks/regulators described in the device's +fw_node. + +To work around this info missing from the ACPI tables on devices where +the int3472 driver is used, the int3472 MFD-cell drivers attach info about +consumers to the clks/regulators when registering these. + +This causes problems with the probe ordering wrt drivers for consumers +of these clks/regulators. Since the lookups are only registered when the +provider-driver binds, trying to get these clks/regulators before then +results in a -ENOENT error for clks and a dummy regulator for regulators. + +All the sensor ACPI fw-nodes have a _DEP dependency on the INT3472 ACPI +fw-node, so to work around these probe ordering issues the ACPI core / +i2c-code does not instantiate the I2C-clients for any ACPI devices +which have a _DEP dependency on an INT3472 ACPI device until all +_DEP-s are met. + +This relies on acpi_dev_clear_dependencies() getting called by the driver +for the _DEP-s when they are ready, add a acpi_dev_clear_dependencies() +call to the discrete.c probe code. + +In the tps68470 case calling acpi_dev_clear_dependencies() is already done +by the acpi_gpiochip_add() call done by the driver for the GPIO MFD cell +(The GPIO cell is deliberately the last cell created to make sure the +clk + regulator cells are already instantiated when this happens). + +However for proper probe ordering, the clk/regulator cells must not just +be instantiated the must be fully ready (the clks + regulators must be +registered with their subsystems). + +Add MODULE_SOFTDEP dependencies for the clk and regulator drivers for +the instantiated MFD-cells so that these are loaded before us and so +that they bind immediately when the platform-devs are instantiated. + +Signed-off-by: Hans de Goede +Patchset: cameras +--- + drivers/platform/x86/intel/int3472/discrete.c | 1 + + drivers/platform/x86/intel/int3472/tps68470.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c +index 22a4894f1cc7..3e1d755b3f83 100644 +--- a/drivers/platform/x86/intel/int3472/discrete.c ++++ b/drivers/platform/x86/intel/int3472/discrete.c +@@ -380,6 +380,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) + return ret; + } + ++ acpi_dev_clear_dependencies(adev); + return 0; + } + +diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c +index aae24d228770..21c6c1a6edfc 100644 +--- a/drivers/platform/x86/intel/int3472/tps68470.c ++++ b/drivers/platform/x86/intel/int3472/tps68470.c +@@ -173,6 +173,11 @@ static int skl_int3472_tps68470_probe(struct i2c_client *client) + return device_type; + } + ++ /* ++ * No acpi_dev_clear_dependencies() here, since the acpi_gpiochip_add() ++ * for the GPIO cell already does this. ++ */ ++ + return ret; + } + +@@ -207,3 +212,4 @@ module_i2c_driver(int3472_tps68470); + MODULE_DESCRIPTION("Intel SkyLake INT3472 ACPI TPS68470 Device Driver"); + MODULE_AUTHOR("Daniel Scally "); + MODULE_LICENSE("GPL v2"); ++MODULE_SOFTDEP("pre: clk-tps68470 tps68470-regulator"); +-- +2.33.1 + +From b67efc1ae2f98b5876a2e34764de631a8092ddf8 Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Thu, 22 Jul 2021 00:20:46 +0100 +Subject: [PATCH] Revert "media: device property: Call + fwnode_graph_get_endpoint_by_id() for fwnode->secondary" + +This reverts commit acd418bfcfc415cf5e6414b6d1c6acfec850f290. Checking for +endpoints against fwnode->secondary in fwnode_graph_get_next_endpoint() is +a better way to do this since that function is also used in a bunch of +other places, for instance sensor drivers checking that they do have an +endpoint connected during probe. + +Reviewed-by: Andy Shevchenko +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/base/property.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/base/property.c b/drivers/base/property.c +index d0874f6c29bb..4d7ff55df95d 100644 +--- a/drivers/base/property.c ++++ b/drivers/base/property.c +@@ -1212,14 +1212,7 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode, + best_ep_id = fwnode_ep.id; + } + +- if (best_ep) +- return best_ep; +- +- if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) +- return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port, +- endpoint, flags); +- +- return NULL; ++ return best_ep; + } + EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id); + +-- +2.33.1 + +From 60ea601e05c037321c99cbbeb06a4afb8d3cd76a Mon Sep 17 00:00:00 2001 +From: Daniel Scally +Date: Sun, 18 Jul 2021 23:52:42 +0100 +Subject: [PATCH] device property: Check fwnode->secondary in + fwnode_graph_get_next_endpoint() + +Sensor drivers often check for an endpoint to make sure that they're +connected to a consuming device like a CIO2 during .probe(). Some of +those endpoints might be in the form of software_nodes assigned as +a secondary to the device's fwnode_handle. Account for this possibility +in fwnode_graph_get_next_endpoint() to avoid having to do it in the +sensor drivers themselves. + +Reviewed-by: Andy Shevchenko +Signed-off-by: Daniel Scally +Patchset: cameras +--- + drivers/base/property.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/property.c b/drivers/base/property.c +index 4d7ff55df95d..453918eb7390 100644 +--- a/drivers/base/property.c ++++ b/drivers/base/property.c +@@ -1033,7 +1033,26 @@ struct fwnode_handle * + fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode, + struct fwnode_handle *prev) + { +- return fwnode_call_ptr_op(fwnode, graph_get_next_endpoint, prev); ++ const struct fwnode_handle *parent; ++ struct fwnode_handle *ep; ++ ++ /* ++ * If this function is in a loop and the previous iteration returned ++ * an endpoint from fwnode->secondary, then we need to use the secondary ++ * as parent rather than @fwnode. ++ */ ++ if (prev) ++ parent = fwnode_graph_get_port_parent(prev); ++ else ++ parent = fwnode; ++ ++ ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev); ++ ++ if (IS_ERR_OR_NULL(ep) && ++ !IS_ERR_OR_NULL(parent) && !IS_ERR_OR_NULL(parent->secondary)) ++ ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL); ++ ++ return ep; + } + EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint); + -- 2.33.1 diff --git a/patches/5.14/0011-amd-gpio.patch b/patches/5.14/0011-amd-gpio.patch index c1b5c58dd..960e10e24 100644 --- a/patches/5.14/0011-amd-gpio.patch +++ b/patches/5.14/0011-amd-gpio.patch @@ -1,4 +1,4 @@ -From 9177a637b985740a74a326a64cc728ba5c7b23d0 Mon Sep 17 00:00:00 2001 +From 154f225730fa656f3c9a8b730daa794dda0e4f1c Mon Sep 17 00:00:00 2001 From: Sachi King Date: Sat, 29 May 2021 17:47:38 +1000 Subject: [PATCH] ACPI: Add quirk for Surface Laptop 4 AMD missing irq 7 @@ -65,7 +65,7 @@ index e55e0c1fad8c..46dfad41b401 100644 -- 2.33.1 -From 27c7ec7a39deea18a708e26f436c7819b422070c Mon Sep 17 00:00:00 2001 +From 9f98d74f40145b77432ecb5d60d71543e76fdf95 Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Thu, 3 Jun 2021 14:04:26 +0200 Subject: [PATCH] ACPI: Add AMD 13" Surface Laptop 4 model to irq 7 override @@ -107,7 +107,7 @@ index 46dfad41b401..78bf6a097dc5 100644 -- 2.33.1 -From 9e404375b63d371c13a10e3e7e6f71ba09d87293 Mon Sep 17 00:00:00 2001 +From 21d29f6145b07abe2349c21743e86224c9b02f6a Mon Sep 17 00:00:00 2001 From: Basavaraj Natikar Date: Tue, 31 Aug 2021 17:36:12 +0530 Subject: [PATCH] pinctrl: amd: Add irq field data @@ -173,7 +173,7 @@ index 95e763424042..1d4317073654 100644 -- 2.33.1 -From fae801e2ab3a2ba06251435d7a9dd587dae55e86 Mon Sep 17 00:00:00 2001 +From bf963c61e066577dcc919412213d567dbefc0ce6 Mon Sep 17 00:00:00 2001 From: Basavaraj Natikar Date: Tue, 31 Aug 2021 17:36:13 +0530 Subject: [PATCH] pinctrl: amd: Handle wake-up interrupt @@ -220,7 +220,7 @@ index 79b8b7f91996..d19974aceb2e 100644 -- 2.33.1 -From 7ec5c5e757046542c594805453642469b5f118f7 Mon Sep 17 00:00:00 2001 +From 008e9417adc0d715401c8c070a7904a169d908d9 Mon Sep 17 00:00:00 2001 From: Sachi King Date: Fri, 1 Oct 2021 21:19:09 +1000 Subject: [PATCH] pinctrl: amd: disable and mask interrupts on probe diff --git a/pkg/arch/kernel/PKGBUILD b/pkg/arch/kernel/PKGBUILD index 2e9fd963f..8fd3e7f02 100644 --- a/pkg/arch/kernel/PKGBUILD +++ b/pkg/arch/kernel/PKGBUILD @@ -54,11 +54,11 @@ sha256sums=('SKIP' 'c14028323060e022ec262c3578c14d6befdfd9a7150f0c8fc913f95f88424a2e' 'ff59e1b9702989070def6b668a9c84d5243c48c0a2694be7cf3be865546577ec' 'ae538e9bdc19179b42c581ed97bab2066bb0934c25da67cd5ec370d3a1e140c2' - '992a51ccf58d2f09d4d0c48914233ec5aa40684f98a7626e56b1dd3ad694dd9b' - 'c7c785f53eb79d6c4304c1f6d2a441ac4bb03df7e8ef3ff05b44641cd992ced1' - '669b7bcdc30b1655ad10dac5262fe1b6cfbeb5fb37fdee568e73a5aee7945c64' - 'bd6470505a1c1a74e3c7026831af622dac00c0127139b821eff3888fd4878e2f' - '9f3d7928a7d35b12b9eced9b10cae61583f926de8cae7f207be3f691e3877450') + '9ea20c45e0b3674160b497dd005595eb4d2c49add087cceca9bf2047a535d0c4' + 'fd89e81b1eef50e0cea4429f0e943c426c77376b3c7e72f21794f1b39b5c8bbc' + 'c8a01e8942ed5041bb9c188e26e7ea53aad0f08944ef427574be89aa23e23593' + '65bbf6d95979784cb7b43953f178ddeea91accb0f0b458f75348b55df89eba88' + '30e796de836f6fac7a87806ece5808f72e3b7d56ecefa58541e30e0537c7741c') export KBUILD_BUILD_HOST=archlinux