0011-cameras.patch 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247
  1. From 5271cb0a99d23130806f0a4bd2b5440023163a62 Mon Sep 17 00:00:00 2001
  2. From: Hans de Goede <hdegoede@redhat.com>
  3. Date: Sun, 10 Oct 2021 20:56:57 +0200
  4. Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an
  5. INT3472 device
  6. The clk and regulator frameworks expect clk/regulator consumer-devices
  7. to have info about the consumed clks/regulators described in the device's
  8. fw_node.
  9. To work around cases where this info is not present in the firmware tables,
  10. which is often the case on x86/ACPI devices, both frameworks allow the
  11. provider-driver to attach info about consumers to the clks/regulators
  12. when registering these.
  13. This causes problems with the probe ordering wrt drivers for consumers
  14. of these clks/regulators. Since the lookups are only registered when the
  15. provider-driver binds, trying to get these clks/regulators before then
  16. results in a -ENOENT error for clks and a dummy regulator for regulators.
  17. One case where we hit this issue is camera sensors such as e.g. the OV8865
  18. sensor found on the Microsoft Surface Go. The sensor uses clks, regulators
  19. and GPIOs provided by a TPS68470 PMIC which is described in an INT3472
  20. ACPI device. There is special platform code handling this and setting
  21. platform_data with the necessary consumer info on the MFD cells
  22. instantiated for the PMIC under: drivers/platform/x86/intel/int3472.
  23. For this to work properly the ov8865 driver must not bind to the I2C-client
  24. for the OV8865 sensor until after the TPS68470 PMIC gpio, regulator and
  25. clk MFD cells have all been fully setup.
  26. The OV8865 on the Microsoft Surface Go is just one example, all X86
  27. devices using the Intel IPU3 camera block found on recent Intel SoCs
  28. have similar issues where there is an INT3472 HID ACPI-device, which
  29. describes the clks and regulators, and the driver for this INT3472 device
  30. must be fully initialized before the sensor driver (any sensor driver)
  31. binds for things to work properly.
  32. On these devices the ACPI nodes describing the sensors all have a _DEP
  33. dependency on the matching INT3472 ACPI device (there is one per sensor).
  34. This allows solving the probe-ordering problem by delaying the enumeration
  35. (instantiation of the I2C-client in the ov8865 example) of ACPI-devices
  36. which have a _DEP dependency on an INT3472 device.
  37. The new acpi_dev_ready_for_enumeration() helper used for this is also
  38. exported because for devices, which have the enumeration_by_parent flag
  39. set, the parent-driver will do its own scan of child ACPI devices and
  40. it will try to enumerate those during its probe(). Code doing this such
  41. as e.g. the i2c-core-acpi.c code must call this new helper to ensure
  42. that it too delays the enumeration until all the _DEP dependencies are
  43. met on devices which have the new honor_deps flag set.
  44. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  45. Patchset: cameras
  46. ---
  47. drivers/acpi/scan.c | 3 +++
  48. 1 file changed, 3 insertions(+)
  49. diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
  50. index 762b61f67e6c..2c0f39a7f2a1 100644
  51. --- a/drivers/acpi/scan.c
  52. +++ b/drivers/acpi/scan.c
  53. @@ -2122,6 +2122,9 @@ static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used,
  54. static void acpi_default_enumeration(struct acpi_device *device)
  55. {
  56. + if (!acpi_dev_ready_for_enumeration(device))
  57. + return;
  58. +
  59. /*
  60. * Do not enumerate devices with enumeration_by_parent flag set as
  61. * they will be enumerated by their respective parents.
  62. --
  63. 2.37.2
  64. From 6596a99eddeeaa1167b7c3363036701cb5b0427c Mon Sep 17 00:00:00 2001
  65. From: zouxiaoh <xiaohong.zou@intel.com>
  66. Date: Fri, 25 Jun 2021 08:52:59 +0800
  67. Subject: [PATCH] iommu: intel-ipu: use IOMMU passthrough mode for Intel IPUs
  68. Intel IPU(Image Processing Unit) has its own (IO)MMU hardware,
  69. The IPU driver allocates its own page table that is not mapped
  70. via the DMA, and thus the Intel IOMMU driver blocks access giving
  71. this error: DMAR: DRHD: handling fault status reg 3 DMAR:
  72. [DMA Read] Request device [00:05.0] PASID ffffffff
  73. fault addr 76406000 [fault reason 06] PTE Read access is not set
  74. As IPU is not an external facing device which is not risky, so use
  75. IOMMU passthrough mode for Intel IPUs.
  76. Change-Id: I6dcccdadac308cf42e20a18e1b593381391e3e6b
  77. Depends-On: Iacd67578e8c6a9b9ac73285f52b4081b72fb68a6
  78. Tracked-On: #JIITL8-411
  79. Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
  80. Signed-off-by: zouxiaoh <xiaohong.zou@intel.com>
  81. Signed-off-by: Xu Chongyang <chongyang.xu@intel.com>
  82. Patchset: cameras
  83. ---
  84. drivers/iommu/intel/iommu.c | 30 ++++++++++++++++++++++++++++++
  85. 1 file changed, 30 insertions(+)
  86. diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
  87. index 7f3699e19270..0ee615daadeb 100644
  88. --- a/drivers/iommu/intel/iommu.c
  89. +++ b/drivers/iommu/intel/iommu.c
  90. @@ -37,6 +37,12 @@
  91. #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
  92. #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
  93. #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
  94. +#define IS_INTEL_IPU(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \
  95. + ((pdev)->device == 0x9a19 || \
  96. + (pdev)->device == 0x9a39 || \
  97. + (pdev)->device == 0x4e19 || \
  98. + (pdev)->device == 0x465d || \
  99. + (pdev)->device == 0x1919))
  100. #define IS_IPTS(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \
  101. ((pdev)->device == 0x9d3e))
  102. #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
  103. @@ -310,12 +316,14 @@ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
  104. static int dmar_map_gfx = 1;
  105. static int dmar_map_ipts = 1;
  106. +static int dmar_map_ipu = 1;
  107. static int intel_iommu_superpage = 1;
  108. static int iommu_identity_mapping;
  109. static int iommu_skip_te_disable;
  110. #define IDENTMAP_GFX 2
  111. #define IDENTMAP_AZALIA 4
  112. +#define IDENTMAP_IPU 8
  113. #define IDENTMAP_IPTS 16
  114. int intel_iommu_gfx_mapped;
  115. @@ -2705,6 +2713,9 @@ static int device_def_domain_type(struct device *dev)
  116. if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
  117. return IOMMU_DOMAIN_IDENTITY;
  118. + if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev))
  119. + return IOMMU_DOMAIN_IDENTITY;
  120. +
  121. if ((iommu_identity_mapping & IDENTMAP_IPTS) && IS_IPTS(pdev))
  122. return IOMMU_DOMAIN_IDENTITY;
  123. }
  124. @@ -3143,6 +3154,9 @@ static int __init init_dmars(void)
  125. if (!dmar_map_gfx)
  126. iommu_identity_mapping |= IDENTMAP_GFX;
  127. + if (!dmar_map_ipu)
  128. + iommu_identity_mapping |= IDENTMAP_IPU;
  129. +
  130. if (!dmar_map_ipts)
  131. iommu_identity_mapping |= IDENTMAP_IPTS;
  132. @@ -4917,6 +4931,18 @@ static void quirk_iommu_igfx(struct pci_dev *dev)
  133. dmar_map_gfx = 0;
  134. }
  135. +static void quirk_iommu_ipu(struct pci_dev *dev)
  136. +{
  137. + if (!IS_INTEL_IPU(dev))
  138. + return;
  139. +
  140. + if (risky_device(dev))
  141. + return;
  142. +
  143. + pci_info(dev, "Passthrough IOMMU for integrated Intel IPU\n");
  144. + dmar_map_ipu = 0;
  145. +}
  146. +
  147. static void quirk_iommu_ipts(struct pci_dev *dev)
  148. {
  149. if (!IS_IPTS(dev))
  150. @@ -4928,6 +4954,7 @@ static void quirk_iommu_ipts(struct pci_dev *dev)
  151. pci_info(dev, "Passthrough IOMMU for IPTS\n");
  152. dmar_map_ipts = 0;
  153. }
  154. +
  155. /* G4x/GM45 integrated gfx dmar support is totally busted. */
  156. DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
  157. DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
  158. @@ -4963,6 +4990,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
  159. DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
  160. DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
  161. +/* disable IPU dmar support */
  162. +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu);
  163. +
  164. /* disable IPTS dmar support */
  165. DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9D3E, quirk_iommu_ipts);
  166. --
  167. 2.37.2
  168. From c6e12368fc3a4610a28f66c3f6b6ba896df7bda4 Mon Sep 17 00:00:00 2001
  169. From: Daniel Scally <djrscally@gmail.com>
  170. Date: Sun, 10 Oct 2021 20:57:02 +0200
  171. Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain
  172. The TPS68470 PMIC has an I2C passthrough mode through which I2C traffic
  173. can be forwarded to a device connected to the PMIC as though it were
  174. connected directly to the system bus. Enable this mode when the chip
  175. is initialised.
  176. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  177. Patchset: cameras
  178. ---
  179. drivers/platform/x86/intel/int3472/tps68470.c | 7 +++++++
  180. 1 file changed, 7 insertions(+)
  181. diff --git a/drivers/platform/x86/intel/int3472/tps68470.c b/drivers/platform/x86/intel/int3472/tps68470.c
  182. index 22f61b47f9e5..e1de1ff40bba 100644
  183. --- a/drivers/platform/x86/intel/int3472/tps68470.c
  184. +++ b/drivers/platform/x86/intel/int3472/tps68470.c
  185. @@ -45,6 +45,13 @@ static int tps68470_chip_init(struct device *dev, struct regmap *regmap)
  186. return ret;
  187. }
  188. + /* Enable I2C daisy chain */
  189. + ret = regmap_write(regmap, TPS68470_REG_S_I2C_CTL, 0x03);
  190. + if (ret) {
  191. + dev_err(dev, "Failed to enable i2c daisy chain\n");
  192. + return ret;
  193. + }
  194. +
  195. dev_info(dev, "TPS68470 REVID: 0x%02x\n", version);
  196. return 0;
  197. --
  198. 2.37.2
  199. From 03bc16d2ed07c397a051ee0f08058517e3c7e59a Mon Sep 17 00:00:00 2001
  200. From: Daniel Scally <djrscally@gmail.com>
  201. Date: Thu, 28 Oct 2021 21:55:16 +0100
  202. Subject: [PATCH] media: i2c: Add driver for DW9719 VCM
  203. Add a driver for the DW9719 VCM. The driver creates a v4l2 subdevice
  204. and registers a control to set the desired focus.
  205. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  206. Patchset: cameras
  207. ---
  208. MAINTAINERS | 7 +
  209. drivers/media/i2c/Kconfig | 11 +
  210. drivers/media/i2c/Makefile | 1 +
  211. drivers/media/i2c/dw9719.c | 427 +++++++++++++++++++++++++++++++++++++
  212. 4 files changed, 446 insertions(+)
  213. create mode 100644 drivers/media/i2c/dw9719.c
  214. diff --git a/MAINTAINERS b/MAINTAINERS
  215. index f96b3dba903a..03452d847a52 100644
  216. --- a/MAINTAINERS
  217. +++ b/MAINTAINERS
  218. @@ -6002,6 +6002,13 @@ T: git git://linuxtv.org/media_tree.git
  219. F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.txt
  220. F: drivers/media/i2c/dw9714.c
  221. +DONGWOON DW9719 LENS VOICE COIL DRIVER
  222. +M: Daniel Scally <djrscally@gmail.com>
  223. +L: linux-media@vger.kernel.org
  224. +S: Maintained
  225. +T: git git://linuxtv.org/media_tree.git
  226. +F: drivers/media/i2c/dw9719.c
  227. +
  228. DONGWOON DW9768 LENS VOICE COIL DRIVER
  229. M: Dongchun Zhu <dongchun.zhu@mediatek.com>
  230. L: linux-media@vger.kernel.org
  231. diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
  232. index c926e5d43820..5c245f642ae3 100644
  233. --- a/drivers/media/i2c/Kconfig
  234. +++ b/drivers/media/i2c/Kconfig
  235. @@ -806,6 +806,17 @@ config VIDEO_DW9714
  236. capability. This is designed for linear control of
  237. voice coil motors, controlled via I2C serial interface.
  238. +config VIDEO_DW9719
  239. + tristate "DW9719 lens voice coil support"
  240. + depends on I2C && VIDEO_V4L2
  241. + select MEDIA_CONTROLLER
  242. + select VIDEO_V4L2_SUBDEV_API
  243. + select V4L2_ASYNC
  244. + help
  245. + This is a driver for the DW9719 camera lens voice coil.
  246. + This is designed for linear control of voice coil motors,
  247. + controlled via I2C serial interface.
  248. +
  249. config VIDEO_DW9768
  250. tristate "DW9768 lens voice coil support"
  251. depends on I2C && VIDEO_DEV
  252. diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
  253. index 3e1696963e7f..9dfda069e006 100644
  254. --- a/drivers/media/i2c/Makefile
  255. +++ b/drivers/media/i2c/Makefile
  256. @@ -29,6 +29,7 @@ obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
  257. obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
  258. obj-$(CONFIG_VIDEO_CX25840) += cx25840/
  259. obj-$(CONFIG_VIDEO_DW9714) += dw9714.o
  260. +obj-$(CONFIG_VIDEO_DW9719) += dw9719.o
  261. obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
  262. obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
  263. obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/
  264. diff --git a/drivers/media/i2c/dw9719.c b/drivers/media/i2c/dw9719.c
  265. new file mode 100644
  266. index 000000000000..8451c75b696b
  267. --- /dev/null
  268. +++ b/drivers/media/i2c/dw9719.c
  269. @@ -0,0 +1,427 @@
  270. +// SPDX-License-Identifier: GPL-2.0
  271. +// Copyright (c) 2012 Intel Corporation
  272. +
  273. +/*
  274. + * Based on linux/modules/camera/drivers/media/i2c/imx/dw9719.c in this repo:
  275. + * https://github.com/ZenfoneArea/android_kernel_asus_zenfone5
  276. + */
  277. +
  278. +#include <asm/unaligned.h>
  279. +
  280. +#include <linux/delay.h>
  281. +#include <linux/i2c.h>
  282. +#include <linux/pm_runtime.h>
  283. +#include <linux/regulator/consumer.h>
  284. +#include <linux/types.h>
  285. +
  286. +#include <media/v4l2-common.h>
  287. +#include <media/v4l2-ctrls.h>
  288. +#include <media/v4l2-subdev.h>
  289. +
  290. +#define DW9719_MAX_FOCUS_POS 1023
  291. +#define DW9719_CTRL_STEPS 16
  292. +#define DW9719_CTRL_DELAY_US 1000
  293. +#define DELAY_MAX_PER_STEP_NS (1000000 * 1023)
  294. +
  295. +#define DW9719_INFO 0
  296. +#define DW9719_ID 0xF1
  297. +#define DW9719_CONTROL 2
  298. +#define DW9719_VCM_CURRENT 3
  299. +
  300. +#define DW9719_MODE 6
  301. +#define DW9719_VCM_FREQ 7
  302. +
  303. +#define DW9719_MODE_SAC3 0x40
  304. +#define DW9719_DEFAULT_VCM_FREQ 0x60
  305. +#define DW9719_ENABLE_RINGING 0x02
  306. +
  307. +#define NUM_REGULATORS 2
  308. +
  309. +#define to_dw9719_device(x) container_of(x, struct dw9719_device, sd)
  310. +
  311. +struct dw9719_device {
  312. + struct device *dev;
  313. + struct i2c_client *client;
  314. + struct regulator_bulk_data regulators[NUM_REGULATORS];
  315. + struct v4l2_subdev sd;
  316. +
  317. + struct dw9719_v4l2_ctrls {
  318. + struct v4l2_ctrl_handler handler;
  319. + struct v4l2_ctrl *focus;
  320. + } ctrls;
  321. +};
  322. +
  323. +static int dw9719_i2c_rd8(struct i2c_client *client, u8 reg, u8 *val)
  324. +{
  325. + struct i2c_msg msg[2];
  326. + u8 buf[2] = { reg };
  327. + int ret;
  328. +
  329. + msg[0].addr = client->addr;
  330. + msg[0].flags = 0;
  331. + msg[0].len = 1;
  332. + msg[0].buf = buf;
  333. +
  334. + msg[1].addr = client->addr;
  335. + msg[1].flags = I2C_M_RD;
  336. + msg[1].len = 1;
  337. + msg[1].buf = &buf[1];
  338. + *val = 0;
  339. +
  340. + ret = i2c_transfer(client->adapter, msg, 2);
  341. + if (ret < 0)
  342. + return ret;
  343. +
  344. + *val = buf[1];
  345. +
  346. + return 0;
  347. +}
  348. +
  349. +static int dw9719_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
  350. +{
  351. + struct i2c_msg msg;
  352. + int ret;
  353. +
  354. + u8 buf[2] = { reg, val };
  355. +
  356. + msg.addr = client->addr;
  357. + msg.flags = 0;
  358. + msg.len = sizeof(buf);
  359. + msg.buf = buf;
  360. +
  361. + ret = i2c_transfer(client->adapter, &msg, 1);
  362. +
  363. + return ret < 0 ? ret : 0;
  364. +}
  365. +
  366. +static int dw9719_i2c_wr16(struct i2c_client *client, u8 reg, u16 val)
  367. +{
  368. + struct i2c_msg msg;
  369. + u8 buf[3] = { reg };
  370. + int ret;
  371. +
  372. + put_unaligned_be16(val, buf + 1);
  373. +
  374. + msg.addr = client->addr;
  375. + msg.flags = 0;
  376. + msg.len = sizeof(buf);
  377. + msg.buf = buf;
  378. +
  379. + ret = i2c_transfer(client->adapter, &msg, 1);
  380. +
  381. + return ret < 0 ? ret : 0;
  382. +}
  383. +
  384. +static int dw9719_detect(struct dw9719_device *dw9719)
  385. +{
  386. + int ret;
  387. + u8 val;
  388. +
  389. + ret = dw9719_i2c_rd8(dw9719->client, DW9719_INFO, &val);
  390. + if (ret < 0)
  391. + return ret;
  392. +
  393. + if (val != DW9719_ID) {
  394. + dev_err(dw9719->dev, "Failed to detect correct id\n");
  395. + ret = -ENXIO;
  396. + }
  397. +
  398. + return 0;
  399. +}
  400. +
  401. +static int dw9719_power_down(struct dw9719_device *dw9719)
  402. +{
  403. + return regulator_bulk_disable(NUM_REGULATORS, dw9719->regulators);
  404. +}
  405. +
  406. +static int dw9719_power_up(struct dw9719_device *dw9719)
  407. +{
  408. + int ret;
  409. +
  410. + ret = regulator_bulk_enable(NUM_REGULATORS, dw9719->regulators);
  411. + if (ret)
  412. + return ret;
  413. +
  414. + /* Jiggle SCL pin to wake up device */
  415. + ret = dw9719_i2c_wr8(dw9719->client, DW9719_CONTROL, 1);
  416. +
  417. + /* Need 100us to transit from SHUTDOWN to STANDBY*/
  418. + usleep_range(100, 1000);
  419. +
  420. + ret = dw9719_i2c_wr8(dw9719->client, DW9719_CONTROL,
  421. + DW9719_ENABLE_RINGING);
  422. + if (ret < 0)
  423. + goto fail_powerdown;
  424. +
  425. + ret = dw9719_i2c_wr8(dw9719->client, DW9719_MODE, DW9719_MODE_SAC3);
  426. + if (ret < 0)
  427. + goto fail_powerdown;
  428. +
  429. + ret = dw9719_i2c_wr8(dw9719->client, DW9719_VCM_FREQ,
  430. + DW9719_DEFAULT_VCM_FREQ);
  431. + if (ret < 0)
  432. + goto fail_powerdown;
  433. +
  434. + return 0;
  435. +
  436. +fail_powerdown:
  437. + dw9719_power_down(dw9719);
  438. + return ret;
  439. +}
  440. +
  441. +static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value)
  442. +{
  443. + int ret;
  444. +
  445. + value = clamp(value, 0, DW9719_MAX_FOCUS_POS);
  446. + ret = dw9719_i2c_wr16(dw9719->client, DW9719_VCM_CURRENT, value);
  447. + if (ret < 0)
  448. + return ret;
  449. +
  450. + return 0;
  451. +}
  452. +
  453. +static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl)
  454. +{
  455. + struct dw9719_device *dw9719 = container_of(ctrl->handler,
  456. + struct dw9719_device,
  457. + ctrls.handler);
  458. + int ret;
  459. +
  460. + /* Only apply changes to the controls if the device is powered up */
  461. + if (!pm_runtime_get_if_in_use(dw9719->dev))
  462. + return 0;
  463. +
  464. + switch (ctrl->id) {
  465. + case V4L2_CID_FOCUS_ABSOLUTE:
  466. + ret = dw9719_t_focus_abs(dw9719, ctrl->val);
  467. + break;
  468. + default:
  469. + ret = -EINVAL;
  470. + }
  471. +
  472. + pm_runtime_put(dw9719->dev);
  473. +
  474. + return ret;
  475. +}
  476. +
  477. +static const struct v4l2_ctrl_ops dw9719_ctrl_ops = {
  478. + .s_ctrl = dw9719_set_ctrl,
  479. +};
  480. +
  481. +static int __maybe_unused dw9719_suspend(struct device *dev)
  482. +{
  483. + struct v4l2_subdev *sd = dev_get_drvdata(dev);
  484. + struct dw9719_device *dw9719 = to_dw9719_device(sd);
  485. + int ret;
  486. + int val;
  487. +
  488. + for (val = dw9719->ctrls.focus->val; val >= 0;
  489. + val -= DW9719_CTRL_STEPS) {
  490. + ret = dw9719_t_focus_abs(dw9719, val);
  491. + if (ret)
  492. + return ret;
  493. +
  494. + usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
  495. + }
  496. +
  497. + return dw9719_power_down(dw9719);
  498. +}
  499. +
  500. +static int __maybe_unused dw9719_resume(struct device *dev)
  501. +{
  502. + struct v4l2_subdev *sd = dev_get_drvdata(dev);
  503. + struct dw9719_device *dw9719 = to_dw9719_device(sd);
  504. + int current_focus = dw9719->ctrls.focus->val;
  505. + int ret;
  506. + int val;
  507. +
  508. + ret = dw9719_power_up(dw9719);
  509. + if (ret)
  510. + return ret;
  511. +
  512. + for (val = current_focus % DW9719_CTRL_STEPS; val < current_focus;
  513. + val += DW9719_CTRL_STEPS) {
  514. + ret = dw9719_t_focus_abs(dw9719, val);
  515. + if (ret)
  516. + goto err_power_down;
  517. +
  518. + usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
  519. + }
  520. +
  521. + return 0;
  522. +
  523. +err_power_down:
  524. + dw9719_power_down(dw9719);
  525. + return ret;
  526. +}
  527. +
  528. +static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
  529. +{
  530. + return pm_runtime_resume_and_get(sd->dev);
  531. +}
  532. +
  533. +static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
  534. +{
  535. + pm_runtime_put(sd->dev);
  536. +
  537. + return 0;
  538. +}
  539. +
  540. +static const struct v4l2_subdev_internal_ops dw9719_internal_ops = {
  541. + .open = dw9719_open,
  542. + .close = dw9719_close,
  543. +};
  544. +
  545. +static int dw9719_init_controls(struct dw9719_device *dw9719)
  546. +{
  547. + const struct v4l2_ctrl_ops *ops = &dw9719_ctrl_ops;
  548. + int ret;
  549. +
  550. + ret = v4l2_ctrl_handler_init(&dw9719->ctrls.handler, 1);
  551. + if (ret)
  552. + return ret;
  553. +
  554. + dw9719->ctrls.focus = v4l2_ctrl_new_std(&dw9719->ctrls.handler, ops,
  555. + V4L2_CID_FOCUS_ABSOLUTE, 0,
  556. + DW9719_MAX_FOCUS_POS, 1, 0);
  557. +
  558. + if (dw9719->ctrls.handler.error) {
  559. + dev_err(dw9719->dev, "Error initialising v4l2 ctrls\n");
  560. + ret = dw9719->ctrls.handler.error;
  561. + goto err_free_handler;
  562. + }
  563. +
  564. + dw9719->sd.ctrl_handler = &dw9719->ctrls.handler;
  565. +
  566. + return ret;
  567. +
  568. +err_free_handler:
  569. + v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
  570. + return ret;
  571. +}
  572. +
  573. +static const struct v4l2_subdev_ops dw9719_ops = { };
  574. +
  575. +static int dw9719_probe(struct i2c_client *client)
  576. +{
  577. + struct dw9719_device *dw9719;
  578. + int ret;
  579. +
  580. + dw9719 = devm_kzalloc(&client->dev, sizeof(*dw9719), GFP_KERNEL);
  581. + if (!dw9719)
  582. + return -ENOMEM;
  583. +
  584. + dw9719->client = client;
  585. + dw9719->dev = &client->dev;
  586. +
  587. + dw9719->regulators[0].supply = "vdd";
  588. + /*
  589. + * The DW9719 has only the 1 VDD voltage input, but some PMICs such as
  590. + * the TPS68470 PMIC have I2C passthrough capability, to disconnect the
  591. + * sensor's I2C pins from the I2C bus when the sensors VSIO (Sensor-IO)
  592. + * is off, because some sensors then short these pins to ground;
  593. + * and the DW9719 might sit behind this passthrough, this it needs to
  594. + * enable VSIO as that will also enable the I2C passthrough.
  595. + */
  596. + dw9719->regulators[1].supply = "vsio";
  597. +
  598. + ret = devm_regulator_bulk_get(&client->dev, NUM_REGULATORS,
  599. + dw9719->regulators);
  600. + if (ret)
  601. + return dev_err_probe(&client->dev, ret, "getting regulators\n");
  602. +
  603. + v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops);
  604. + dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
  605. + dw9719->sd.internal_ops = &dw9719_internal_ops;
  606. +
  607. + ret = dw9719_init_controls(dw9719);
  608. + if (ret)
  609. + return ret;
  610. +
  611. + ret = media_entity_pads_init(&dw9719->sd.entity, 0, NULL);
  612. + if (ret < 0)
  613. + goto err_free_ctrl_handler;
  614. +
  615. + dw9719->sd.entity.function = MEDIA_ENT_F_LENS;
  616. +
  617. + /*
  618. + * We need the driver to work in the event that pm runtime is disable in
  619. + * the kernel, so power up and verify the chip now. In the event that
  620. + * runtime pm is disabled this will leave the chip on, so that the lens
  621. + * will work.
  622. + */
  623. +
  624. + ret = dw9719_power_up(dw9719);
  625. + if (ret)
  626. + goto err_cleanup_media;
  627. +
  628. + ret = dw9719_detect(dw9719);
  629. + if (ret)
  630. + goto err_powerdown;
  631. +
  632. + pm_runtime_set_active(&client->dev);
  633. + pm_runtime_get_noresume(&client->dev);
  634. + pm_runtime_enable(&client->dev);
  635. +
  636. + ret = v4l2_async_register_subdev(&dw9719->sd);
  637. + if (ret < 0)
  638. + goto err_pm_runtime;
  639. +
  640. + pm_runtime_set_autosuspend_delay(&client->dev, 1000);
  641. + pm_runtime_use_autosuspend(&client->dev);
  642. + pm_runtime_put_autosuspend(&client->dev);
  643. +
  644. + return ret;
  645. +
  646. +err_pm_runtime:
  647. + pm_runtime_disable(&client->dev);
  648. + pm_runtime_put_noidle(&client->dev);
  649. +err_powerdown:
  650. + dw9719_power_down(dw9719);
  651. +err_cleanup_media:
  652. + media_entity_cleanup(&dw9719->sd.entity);
  653. +err_free_ctrl_handler:
  654. + v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
  655. +
  656. + return ret;
  657. +}
  658. +
  659. +static int dw9719_remove(struct i2c_client *client)
  660. +{
  661. + struct v4l2_subdev *sd = i2c_get_clientdata(client);
  662. + struct dw9719_device *dw9719 = container_of(sd, struct dw9719_device,
  663. + sd);
  664. +
  665. + pm_runtime_disable(&client->dev);
  666. + v4l2_async_unregister_subdev(sd);
  667. + v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
  668. + media_entity_cleanup(&dw9719->sd.entity);
  669. +
  670. + return 0;
  671. +}
  672. +
  673. +static const struct i2c_device_id dw9719_id_table[] = {
  674. + { "dw9719" },
  675. + { }
  676. +};
  677. +MODULE_DEVICE_TABLE(i2c, dw9719_id_table);
  678. +
  679. +static const struct dev_pm_ops dw9719_pm_ops = {
  680. + SET_RUNTIME_PM_OPS(dw9719_suspend, dw9719_resume, NULL)
  681. +};
  682. +
  683. +static struct i2c_driver dw9719_i2c_driver = {
  684. + .driver = {
  685. + .name = "dw9719",
  686. + .pm = &dw9719_pm_ops,
  687. + },
  688. + .probe_new = dw9719_probe,
  689. + .remove = dw9719_remove,
  690. + .id_table = dw9719_id_table,
  691. +};
  692. +module_i2c_driver(dw9719_i2c_driver);
  693. +
  694. +MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
  695. +MODULE_DESCRIPTION("DW9719 VCM Driver");
  696. +MODULE_LICENSE("GPL");
  697. --
  698. 2.37.2
  699. From 8792b2fe58ecf2b5a4d7195d7846dac21a740c9c Mon Sep 17 00:00:00 2001
  700. From: Maximilian Luz <luzmaximilian@gmail.com>
  701. Date: Fri, 15 Jul 2022 23:48:00 +0200
  702. Subject: [PATCH] drivers/media/i2c: Fix DW9719 dependencies
  703. It should depend on VIDEO_DEV instead of VIDEO_V4L2.
  704. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  705. Patchset: cameras
  706. ---
  707. drivers/media/i2c/Kconfig | 2 +-
  708. 1 file changed, 1 insertion(+), 1 deletion(-)
  709. diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
  710. index 5c245f642ae3..50ea62e63784 100644
  711. --- a/drivers/media/i2c/Kconfig
  712. +++ b/drivers/media/i2c/Kconfig
  713. @@ -808,7 +808,7 @@ config VIDEO_DW9714
  714. config VIDEO_DW9719
  715. tristate "DW9719 lens voice coil support"
  716. - depends on I2C && VIDEO_V4L2
  717. + depends on I2C && VIDEO_DEV
  718. select MEDIA_CONTROLLER
  719. select VIDEO_V4L2_SUBDEV_API
  720. select V4L2_ASYNC
  721. --
  722. 2.37.2
  723. From 498ae9f4a0e000ab0ee3eb140466f54d22ebbbac Mon Sep 17 00:00:00 2001
  724. From: Daniel Scally <djrscally@gmail.com>
  725. Date: Mon, 13 Dec 2021 22:38:17 +0000
  726. Subject: [PATCH] media: entity: Skip non-data links in graph iteration
  727. When iterating over the media graph, don't follow links that are not
  728. data links.
  729. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  730. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  731. Patchset: cameras
  732. ---
  733. drivers/media/mc/mc-entity.c | 6 ++++++
  734. 1 file changed, 6 insertions(+)
  735. diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
  736. index 8ab0913d8d82..a8631f74dcee 100644
  737. --- a/drivers/media/mc/mc-entity.c
  738. +++ b/drivers/media/mc/mc-entity.c
  739. @@ -295,6 +295,12 @@ static void media_graph_walk_iter(struct media_graph *graph)
  740. link = list_entry(link_top(graph), typeof(*link), list);
  741. + /* If the link is not a data link, don't follow it */
  742. + if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
  743. + link_top(graph) = link_top(graph)->next;
  744. + return;
  745. + }
  746. +
  747. /* The link is not enabled so we do not follow. */
  748. if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
  749. link_top(graph) = link_top(graph)->next;
  750. --
  751. 2.37.2
  752. From ab99732bedda2cd5e8c97c22b682fb95f3e1dc4a Mon Sep 17 00:00:00 2001
  753. From: Daniel Scally <djrscally@gmail.com>
  754. Date: Mon, 13 Dec 2021 22:53:09 +0000
  755. Subject: [PATCH] media: media.h: Add new media link type
  756. To describe in the kernel the connection between devices and their
  757. supporting peripherals (for example, a camera sensor and the vcm
  758. driving the focusing lens for it), add a new type of media link
  759. to introduce the concept of these ancillary links.
  760. Add some elements to the uAPI documentation to explain the new link
  761. type, their purpose and some aspects of their current implementation.
  762. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  763. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  764. Patchset: cameras
  765. ---
  766. .../media/mediactl/media-controller-model.rst | 6 ++++++
  767. .../media/mediactl/media-types.rst | 17 ++++++++++++-----
  768. include/uapi/linux/media.h | 1 +
  769. 3 files changed, 19 insertions(+), 5 deletions(-)
  770. diff --git a/Documentation/userspace-api/media/mediactl/media-controller-model.rst b/Documentation/userspace-api/media/mediactl/media-controller-model.rst
  771. index 222cb99debb5..78bfdfb2a322 100644
  772. --- a/Documentation/userspace-api/media/mediactl/media-controller-model.rst
  773. +++ b/Documentation/userspace-api/media/mediactl/media-controller-model.rst
  774. @@ -33,3 +33,9 @@ are:
  775. - An **interface link** is a point-to-point bidirectional control
  776. connection between a Linux Kernel interface and an entity.
  777. +
  778. +- An **ancillary link** is a point-to-point connection denoting that two
  779. + entities form a single logical unit. For example this could represent the
  780. + fact that a particular camera sensor and lens controller form a single
  781. + physical module, meaning this lens controller drives the lens for this
  782. + camera sensor.
  783. \ No newline at end of file
  784. diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst
  785. index 0a26397bd01d..60747251d409 100644
  786. --- a/Documentation/userspace-api/media/mediactl/media-types.rst
  787. +++ b/Documentation/userspace-api/media/mediactl/media-types.rst
  788. @@ -412,14 +412,21 @@ must be set for every pad.
  789. is set by drivers and is read-only for applications.
  790. * - ``MEDIA_LNK_FL_LINK_TYPE``
  791. - - This is a bitmask that defines the type of the link. Currently,
  792. - two types of links are supported:
  793. + - This is a bitmask that defines the type of the link. The following
  794. + link types are currently supported:
  795. .. _MEDIA-LNK-FL-DATA-LINK:
  796. - ``MEDIA_LNK_FL_DATA_LINK`` if the link is between two pads
  797. + ``MEDIA_LNK_FL_DATA_LINK`` for links that represent a data connection
  798. + between two pads.
  799. .. _MEDIA-LNK-FL-INTERFACE-LINK:
  800. - ``MEDIA_LNK_FL_INTERFACE_LINK`` if the link is between an
  801. - interface and an entity
  802. + ``MEDIA_LNK_FL_INTERFACE_LINK`` for links that associate an entity to its
  803. + interface.
  804. +
  805. + .. _MEDIA-LNK-FL-ANCILLARY-LINK:
  806. +
  807. + ``MEDIA_LNK_FL_ANCILLARY_LINK`` for links that represent a physical
  808. + relationship between two entities. The link may or may not be ummutable, so
  809. + applications must not assume either case.
  810. \ No newline at end of file
  811. diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
  812. index 200fa8462b90..afbae7213d35 100644
  813. --- a/include/uapi/linux/media.h
  814. +++ b/include/uapi/linux/media.h
  815. @@ -226,6 +226,7 @@ struct media_pad_desc {
  816. #define MEDIA_LNK_FL_LINK_TYPE (0xf << 28)
  817. # define MEDIA_LNK_FL_DATA_LINK (0 << 28)
  818. # define MEDIA_LNK_FL_INTERFACE_LINK (1 << 28)
  819. +# define MEDIA_LNK_FL_ANCILLARY_LINK (2 << 28)
  820. struct media_link_desc {
  821. struct media_pad_desc source;
  822. --
  823. 2.37.2
  824. From 512b2e9c2dddd2924c95d5d9548ca89db1edefd1 Mon Sep 17 00:00:00 2001
  825. From: Daniel Scally <djrscally@gmail.com>
  826. Date: Mon, 13 Dec 2021 22:36:31 +0000
  827. Subject: [PATCH] media: entity: Add link_type_name() helper
  828. Now we have three types of media link, printing the right name during
  829. debug output is slightly more complicated. Add a helper function to
  830. make it easier.
  831. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  832. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  833. Patchset: cameras
  834. ---
  835. drivers/media/mc/mc-entity.c | 18 +++++++++++++++---
  836. 1 file changed, 15 insertions(+), 3 deletions(-)
  837. diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
  838. index a8631f74dcee..4bd80ce1a33d 100644
  839. --- a/drivers/media/mc/mc-entity.c
  840. +++ b/drivers/media/mc/mc-entity.c
  841. @@ -44,6 +44,20 @@ static inline const char *intf_type(struct media_interface *intf)
  842. }
  843. };
  844. +static inline const char *link_type_name(struct media_link *link)
  845. +{
  846. + switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
  847. + case MEDIA_LNK_FL_DATA_LINK:
  848. + return "data";
  849. + case MEDIA_LNK_FL_INTERFACE_LINK:
  850. + return "interface";
  851. + case MEDIA_LNK_FL_ANCILLARY_LINK:
  852. + return "ancillary";
  853. + default:
  854. + return "unknown";
  855. + }
  856. +}
  857. +
  858. __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
  859. int idx_max)
  860. {
  861. @@ -89,9 +103,7 @@ static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj)
  862. dev_dbg(gobj->mdev->dev,
  863. "%s id %u: %s link id %u ==> id %u\n",
  864. - event_name, media_id(gobj),
  865. - media_type(link->gobj0) == MEDIA_GRAPH_PAD ?
  866. - "data" : "interface",
  867. + event_name, media_id(gobj), link_type_name(link),
  868. media_id(link->gobj0),
  869. media_id(link->gobj1));
  870. break;
  871. --
  872. 2.37.2
  873. From ab787dfcd33ab0d1d1bc9c8faaf7b3a4b9a9c2cc Mon Sep 17 00:00:00 2001
  874. From: Daniel Scally <djrscally@gmail.com>
  875. Date: Mon, 13 Dec 2021 22:54:10 +0000
  876. Subject: [PATCH] media: entity: Add support for ancillary links
  877. Add functions to create ancillary links, so that they don't need to
  878. be manually created by users.
  879. Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  880. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  881. Patchset: cameras
  882. ---
  883. drivers/media/mc/mc-entity.c | 22 ++++++++++++++++++++++
  884. include/media/media-entity.h | 19 +++++++++++++++++++
  885. 2 files changed, 41 insertions(+)
  886. diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
  887. index 4bd80ce1a33d..1ff60d411ea9 100644
  888. --- a/drivers/media/mc/mc-entity.c
  889. +++ b/drivers/media/mc/mc-entity.c
  890. @@ -1025,3 +1025,25 @@ void media_remove_intf_links(struct media_interface *intf)
  891. mutex_unlock(&mdev->graph_mutex);
  892. }
  893. EXPORT_SYMBOL_GPL(media_remove_intf_links);
  894. +
  895. +struct media_link *media_create_ancillary_link(struct media_entity *primary,
  896. + struct media_entity *ancillary)
  897. +{
  898. + struct media_link *link;
  899. +
  900. + link = media_add_link(&primary->links);
  901. + if (!link)
  902. + return ERR_PTR(-ENOMEM);
  903. +
  904. + link->gobj0 = &primary->graph_obj;
  905. + link->gobj1 = &ancillary->graph_obj;
  906. + link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
  907. + MEDIA_LNK_FL_ANCILLARY_LINK;
  908. +
  909. + /* Initialize graph object embedded in the new link */
  910. + media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
  911. + &link->graph_obj);
  912. +
  913. + return link;
  914. +}
  915. +EXPORT_SYMBOL_GPL(media_create_ancillary_link);
  916. diff --git a/include/media/media-entity.h b/include/media/media-entity.h
  917. index 742918962d46..1d13b8939a11 100644
  918. --- a/include/media/media-entity.h
  919. +++ b/include/media/media-entity.h
  920. @@ -1121,4 +1121,23 @@ void media_remove_intf_links(struct media_interface *intf);
  921. (((entity)->ops && (entity)->ops->operation) ? \
  922. (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
  923. +/**
  924. + * media_create_ancillary_link() - create an ancillary link between two
  925. + * instances of &media_entity
  926. + *
  927. + * @primary: pointer to the primary &media_entity
  928. + * @ancillary: pointer to the ancillary &media_entity
  929. + *
  930. + * Create an ancillary link between two entities, indicating that they
  931. + * represent two connected pieces of hardware that form a single logical unit.
  932. + * A typical example is a camera lens controller being linked to the sensor that
  933. + * it is supporting.
  934. + *
  935. + * The function sets both MEDIA_LNK_FL_ENABLED and MEDIA_LNK_FL_IMMUTABLE for
  936. + * the new link.
  937. + */
  938. +struct media_link *
  939. +media_create_ancillary_link(struct media_entity *primary,
  940. + struct media_entity *ancillary);
  941. +
  942. #endif
  943. --
  944. 2.37.2
  945. From ddc66e6de51574fb41902754928996c210710a0e Mon Sep 17 00:00:00 2001
  946. From: Daniel Scally <djrscally@gmail.com>
  947. Date: Fri, 26 Nov 2021 22:55:50 +0000
  948. Subject: [PATCH] media: v4l2-async: Create links during
  949. v4l2_async_match_notify()
  950. Upon an async fwnode match, there's some typical behaviour that the
  951. notifier and matching subdev will want to do. For example, a notifier
  952. representing a sensor matching to an async subdev representing its
  953. VCM will want to create an ancillary link to expose that relationship
  954. to userspace.
  955. To avoid lots of code in individual drivers, try to build these links
  956. within v4l2 core.
  957. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  958. Patchset: cameras
  959. ---
  960. drivers/media/v4l2-core/v4l2-async.c | 31 ++++++++++++++++++++++++++++
  961. 1 file changed, 31 insertions(+)
  962. diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
  963. index 0404267f1ae4..436bd6900fd8 100644
  964. --- a/drivers/media/v4l2-core/v4l2-async.c
  965. +++ b/drivers/media/v4l2-core/v4l2-async.c
  966. @@ -275,6 +275,24 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
  967. static int
  968. v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
  969. +static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n,
  970. + struct v4l2_subdev *sd)
  971. +{
  972. + struct media_link *link = NULL;
  973. +
  974. +#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
  975. +
  976. + if (sd->entity.function != MEDIA_ENT_F_LENS &&
  977. + sd->entity.function != MEDIA_ENT_F_FLASH)
  978. + return 0;
  979. +
  980. + link = media_create_ancillary_link(&n->sd->entity, &sd->entity);
  981. +
  982. +#endif
  983. +
  984. + return IS_ERR(link) ? PTR_ERR(link) : 0;
  985. +}
  986. +
  987. static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
  988. struct v4l2_device *v4l2_dev,
  989. struct v4l2_subdev *sd,
  990. @@ -293,6 +311,19 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
  991. return ret;
  992. }
  993. + /*
  994. + * Depending of the function of the entities involved, we may want to
  995. + * create links between them (for example between a sensor and its lens
  996. + * or between a sensor's source pad and the connected device's sink
  997. + * pad).
  998. + */
  999. + ret = v4l2_async_create_ancillary_links(notifier, sd);
  1000. + if (ret) {
  1001. + v4l2_async_nf_call_unbind(notifier, sd, asd);
  1002. + v4l2_device_unregister_subdev(sd);
  1003. + return ret;
  1004. + }
  1005. +
  1006. /* Remove from the waiting list */
  1007. list_del(&asd->list);
  1008. sd->asd = asd;
  1009. --
  1010. 2.37.2
  1011. From 9265a11f92a688baa1f820936e217bc8490c57c3 Mon Sep 17 00:00:00 2001
  1012. From: Daniel Scally <djrscally@gmail.com>
  1013. Date: Wed, 4 May 2022 23:21:45 +0100
  1014. Subject: [PATCH] media: ipu3-cio2: Move functionality from .complete() to
  1015. .bound()
  1016. Creating links and registering subdev nodes during the .complete()
  1017. callback has the unfortunate effect of preventing all cameras that
  1018. connect to a notifier from working if any one of their drivers fails
  1019. to probe. Moving the functionality from .complete() to .bound() allows
  1020. those camera sensor drivers that did probe correctly to work regardless.
  1021. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  1022. Patchset: cameras
  1023. ---
  1024. drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 65 +++++++------------
  1025. 1 file changed, 23 insertions(+), 42 deletions(-)
  1026. diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
  1027. index 0e9b0503b62a..50682a7b2a07 100644
  1028. --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
  1029. +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
  1030. @@ -1382,7 +1382,10 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
  1031. {
  1032. struct cio2_device *cio2 = to_cio2_device(notifier);
  1033. struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
  1034. + struct device *dev = &cio2->pci_dev->dev;
  1035. struct cio2_queue *q;
  1036. + unsigned int pad;
  1037. + int ret;
  1038. if (cio2->queue[s_asd->csi2.port].sensor)
  1039. return -EBUSY;
  1040. @@ -1393,7 +1396,26 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
  1041. q->sensor = sd;
  1042. q->csi_rx_base = cio2->base + CIO2_REG_PIPE_BASE(q->csi2.port);
  1043. - return 0;
  1044. + for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
  1045. + if (q->sensor->entity.pads[pad].flags &
  1046. + MEDIA_PAD_FL_SOURCE)
  1047. + break;
  1048. +
  1049. + if (pad == q->sensor->entity.num_pads) {
  1050. + dev_err(dev, "failed to find src pad for %s\n",
  1051. + q->sensor->name);
  1052. + return -ENXIO;
  1053. + }
  1054. +
  1055. + ret = media_create_pad_link(&q->sensor->entity, pad, &q->subdev.entity,
  1056. + CIO2_PAD_SINK, 0);
  1057. + if (ret) {
  1058. + dev_err(dev, "failed to create link for %s\n",
  1059. + q->sensor->name);
  1060. + return ret;
  1061. + }
  1062. +
  1063. + return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
  1064. }
  1065. /* The .unbind callback */
  1066. @@ -1407,50 +1429,9 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
  1067. cio2->queue[s_asd->csi2.port].sensor = NULL;
  1068. }
  1069. -/* .complete() is called after all subdevices have been located */
  1070. -static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
  1071. -{
  1072. - struct cio2_device *cio2 = to_cio2_device(notifier);
  1073. - struct device *dev = &cio2->pci_dev->dev;
  1074. - struct sensor_async_subdev *s_asd;
  1075. - struct v4l2_async_subdev *asd;
  1076. - struct cio2_queue *q;
  1077. - unsigned int pad;
  1078. - int ret;
  1079. -
  1080. - list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
  1081. - s_asd = to_sensor_asd(asd);
  1082. - q = &cio2->queue[s_asd->csi2.port];
  1083. -
  1084. - for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
  1085. - if (q->sensor->entity.pads[pad].flags &
  1086. - MEDIA_PAD_FL_SOURCE)
  1087. - break;
  1088. -
  1089. - if (pad == q->sensor->entity.num_pads) {
  1090. - dev_err(dev, "failed to find src pad for %s\n",
  1091. - q->sensor->name);
  1092. - return -ENXIO;
  1093. - }
  1094. -
  1095. - ret = media_create_pad_link(
  1096. - &q->sensor->entity, pad,
  1097. - &q->subdev.entity, CIO2_PAD_SINK,
  1098. - 0);
  1099. - if (ret) {
  1100. - dev_err(dev, "failed to create link for %s\n",
  1101. - q->sensor->name);
  1102. - return ret;
  1103. - }
  1104. - }
  1105. -
  1106. - return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
  1107. -}
  1108. -
  1109. static const struct v4l2_async_notifier_operations cio2_async_ops = {
  1110. .bound = cio2_notifier_bound,
  1111. .unbind = cio2_notifier_unbind,
  1112. - .complete = cio2_notifier_complete,
  1113. };
  1114. static int cio2_parse_firmware(struct cio2_device *cio2)
  1115. --
  1116. 2.37.2
  1117. From 54b2514cecc9cb79754586cfb1a716251f91b5e1 Mon Sep 17 00:00:00 2001
  1118. From: Daniel Scally <djrscally@gmail.com>
  1119. Date: Thu, 2 Jun 2022 22:15:56 +0100
  1120. Subject: [PATCH] media: ipu3-cio2: Re-add .complete() to ipu3-cio2
  1121. Removing the .complete() callback had some unintended consequences.
  1122. Because the VCM driver is not directly linked to the ipu3-cio2
  1123. driver .bound() never gets called for it, which means its devnode
  1124. is never created if it probes late. Because .complete() waits for
  1125. any sub-notifiers to also be complete it is captured in that call.
  1126. Signed-off-by: Daniel Scally <djrscally@gmail.com>
  1127. Patchset: cameras
  1128. ---
  1129. drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 9 +++++++++
  1130. 1 file changed, 9 insertions(+)
  1131. diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
  1132. index 50682a7b2a07..ff79582a583d 100644
  1133. --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
  1134. +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
  1135. @@ -1429,9 +1429,18 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
  1136. cio2->queue[s_asd->csi2.port].sensor = NULL;
  1137. }
  1138. +/* .complete() is called after all subdevices have been located */
  1139. +static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
  1140. +{
  1141. + struct cio2_device *cio2 = to_cio2_device(notifier);
  1142. +
  1143. + return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
  1144. +}
  1145. +
  1146. static const struct v4l2_async_notifier_operations cio2_async_ops = {
  1147. .bound = cio2_notifier_bound,
  1148. .unbind = cio2_notifier_unbind,
  1149. + .complete = cio2_notifier_complete,
  1150. };
  1151. static int cio2_parse_firmware(struct cio2_device *cio2)
  1152. --
  1153. 2.37.2