diff options
author | Florian Klink <flokli@flokli.de> | 2024-12-04T19·04+0200 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2024-12-04T20·02+0000 |
commit | e743e2439cd3c5b430e615c0021b47927b2dc98e (patch) | |
tree | 265fc5749208e0d729a7d5dcec4d513a8115b033 /users/flokli | |
parent | 962df219f76014816404e2ee4c82db01c899877b (diff) |
chore(users/flokli/ipu6-softisp): remove r/8981
This didn't work properly for a while, at least expose too many cameras for browsers to get confused. It also doesn't apply cleanly to the 6.12.1 kernel. Change-Id: I8a23cc0ae0547bfde5756ee84953b60f4b0a2df2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12866 Reviewed-by: flokli <flokli@flokli.de> Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org> Autosubmit: flokli <flokli@flokli.de>
Diffstat (limited to 'users/flokli')
9 files changed, 0 insertions, 1986 deletions
diff --git a/users/flokli/ipu6-softisp/README.md b/users/flokli/ipu6-softisp/README.md deleted file mode 100644 index 2ab727ace44f..000000000000 --- a/users/flokli/ipu6-softisp/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# ipu6-softisp - -This code adds support for the ipu6 webcams via libcamera, based on the work in -https://copr.fedorainfracloud.org/coprs/jwrdegoede/ipu6-softisp/. - -It's supposed to be included in your NixOS configuration imports, and will: - - - Add some patches to your kernel, which should apply on 6.8.x - - Add the `ipu6-camera-bins` firmware (still needed) - - Enable some kernel config options - - Add an udev rule so libcamera can do DMABUF things - - Override `services.pipewire.package` and - `services.pipewire.wireplumber.package` to use a pipewire built with a libcamera - with support for this webcam. - -Please make sure you don't have any of the `hardware.ipu6` options still -enabled, as they use the closed-source userspace stack and will conflict. - -Also make sure to track nixos-unstable for this. This code will get periodically -updated to be compatible with nixos-unstable! - -The testing instructions from -https://copr.fedorainfracloud.org/coprs/jwrdegoede/ipu6-softisp/ still apply. - -`qcam` can be found in `libcamera-qcam` (pending on -https://github.com/NixOS/nixpkgs/pull/284964 to trickle into master). - -Thanks to Hans de Goede for helping me bringing this up, as well as to -puckipedia for sorting out some pipewire-related confusion. diff --git a/users/flokli/ipu6-softisp/config.nix b/users/flokli/ipu6-softisp/config.nix deleted file mode 100644 index 0e47c88fbbad..000000000000 --- a/users/flokli/ipu6-softisp/config.nix +++ /dev/null @@ -1,56 +0,0 @@ -{ pkgs, lib, ... }: - -let - libcamera = pkgs.libcamera.overrideAttrs (old: { - mesonFlags = old.mesonFlags or [ ] ++ [ - "-Dpipelines=simple,ipu3,uvcvideo" - "-Dipas=simple,ipu3" - ]; - - # This is - # https://copr-dist-git.fedorainfracloud.org/cgit/jwrdegoede/ipu6-softisp/libcamera.git/plain/libcamera-0.2.0-softisp.patch?h=f39&id=60e6b3d5e366a360a75942073dc0d642e4900982, - # but manually piped to git and back, as some renames were not processed properly. - # It was later refreshed with https://patchwork.libcamera.org/cover/19663/ - patches = old.patches or [ ] ++ [ - ./libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch - ./libcamera/0002-ov01a1s-HACK.patch - ./libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch - ]; - }); - - # use patched libcamera - pipewire' = (pkgs.pipewire.override { - inherit libcamera; - }); - - wireplumber' = (pkgs.wireplumber.override { - pipewire = pipewire'; - }); -in -{ - boot.kernelPatches = [{ - name = "linux-kernel-test.patch"; - patch = ./kernel/softisp.patch; - extraStructuredConfig = { - # needed for /dev/dma_heap - DMABUF_HEAPS_CMA = lib.kernel.yes; - DMABUF_HEAPS_SYSTEM = lib.kernel.yes; - DMABUF_HEAPS = lib.kernel.yes; - }; - }]; - - - services.udev.extraRules = '' - KERNEL=="system", SUBSYSTEM=="dma_heap", TAG+="uaccess" - ''; - - # provide qcam in $PATH. - environment.systemPackages = [ - (libcamera.override { - withQcam = true; - }) - ]; - - services.pipewire.package = pipewire'; - services.pipewire.wireplumber.package = wireplumber'; -} diff --git a/users/flokli/ipu6-softisp/default.nix b/users/flokli/ipu6-softisp/default.nix deleted file mode 100644 index ab129d1bc85e..000000000000 --- a/users/flokli/ipu6-softisp/default.nix +++ /dev/null @@ -1,60 +0,0 @@ -# This file ensures the fixes from ./config.nix build with the version of -# nixpkgs from depot. -# If you're an outside user of this, import config.nix as a NixOS module (and -# check the README.md file). - -{ depot -, pkgs -, ... -}: - -let - systemFor = sys: (depot.ops.nixos.nixosFor sys).system; -in -(depot.nix.readTree.drvTargets rec { - testSystem = (systemFor ({ modulesPath, pkgs, ... }: { - imports = [ - # Import the module, this is something a user would do in their config. - ./config.nix - ]; - - # Make sure we use the linuxPackages_latest. - boot.kernelPackages = pkgs.linuxPackages_latest; - - # Enable firmware. - hardware.enableAllFirmware = true; - - # Set some options necessary to evaluate. - boot.loader.systemd-boot.enable = true; - fileSystems."/" = { - device = "/dev/disk/by-partlabel/root"; - fsType = "xfs"; - }; - - # Enable pipewire and wireplumber. - services.pipewire = { - enable = true; - wireplumber.enable = true; - }; - - # Shut off the warning. - system.stateVersion = "24.05"; - })) // { - # 2024-07-28 aspen: The patches no longer cleanly apply on upstream - meta.broken = true; - }; - - # Make sure the firmware requested by the driver is present in our firmware. - # We do have a .zst suffix here, but that's fine, since request_firmware does - # check ${name}.zst too in case CONFIG_FW_LOADER_COMPRESS is set. - # The path needs to be kept in sync with the ones used in the kernel patch. - checkFirmware = pkgs.runCommand "check-firmware" { } '' - stat ${testSystem}/firmware/intel/ipu/ipu6se_fw.bin.zst - stat ${testSystem}/firmware/intel/ipu/ipu6ep_fw.bin.zst - stat ${testSystem}/firmware/intel/ipu/ipu6_fw.bin.zst - stat ${testSystem}/firmware/intel/ipu/ipu6epmtl_fw.bin.zst - - # all good, succeed build - touch $out - ''; -}) diff --git a/users/flokli/ipu6-softisp/kernel/.skip-tree b/users/flokli/ipu6-softisp/kernel/.skip-tree deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/users/flokli/ipu6-softisp/kernel/.skip-tree +++ /dev/null diff --git a/users/flokli/ipu6-softisp/kernel/softisp.patch b/users/flokli/ipu6-softisp/kernel/softisp.patch deleted file mode 100644 index e1395bbb135f..000000000000 --- a/users/flokli/ipu6-softisp/kernel/softisp.patch +++ /dev/null @@ -1,1463 +0,0 @@ -From b5a82464677815dcbe6a06b0ee92ed065b1ec275 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 6 Nov 2023 12:13:42 +0100 -Subject: [PATCH 1/3] media: Add ov01a1s driver - -Add ov01a1s driver from: -https://github.com/intel/ipu6-drivers/ - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/i2c/Kconfig | 9 + - drivers/media/i2c/Makefile | 1 + - drivers/media/i2c/ov01a1s.c | 1191 +++++++++++++++++++++++++++++++++++ - 3 files changed, 1201 insertions(+) - create mode 100644 drivers/media/i2c/ov01a1s.c - -diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig -index c6d3ee472d81..59e0d304bef2 100644 ---- a/drivers/media/i2c/Kconfig -+++ b/drivers/media/i2c/Kconfig -@@ -315,6 +315,15 @@ config VIDEO_OV01A10 - To compile this driver as a module, choose M here: the - module will be called ov01a10. - -+config VIDEO_OV01A1S -+ tristate "OmniVision OV01A1S sensor support" -+ help -+ This is a Video4Linux2 sensor driver for the OmniVision -+ OV01A1S camera. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called ov01a1s. -+ - config VIDEO_OV02A10 - tristate "OmniVision OV02A10 sensor support" - help -diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile -index dfbe6448b549..53ea54c2cf01 100644 ---- a/drivers/media/i2c/Makefile -+++ b/drivers/media/i2c/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o - obj-$(CONFIG_VIDEO_MT9V111) += mt9v111.o - obj-$(CONFIG_VIDEO_OG01A1B) += og01a1b.o - obj-$(CONFIG_VIDEO_OV01A10) += ov01a10.o -+obj-$(CONFIG_VIDEO_OV01A1S) += ov01a1s.o - obj-$(CONFIG_VIDEO_OV02A10) += ov02a10.o - obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o - obj-$(CONFIG_VIDEO_OV08X40) += ov08x40.o -diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c -new file mode 100644 -index 000000000000..0dcce8b492b4 ---- /dev/null -+++ b/drivers/media/i2c/ov01a1s.c -@@ -0,0 +1,1191 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2020-2022 Intel Corporation. -+ -+#include <asm/unaligned.h> -+#include <linux/acpi.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+#include <linux/module.h> -+#include <linux/pm_runtime.h> -+#include <linux/version.h> -+#include <media/v4l2-ctrls.h> -+#include <media/v4l2-device.h> -+#include <media/v4l2-fwnode.h> -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+#include <linux/clk.h> -+#include <linux/gpio/consumer.h> -+#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -+#include "power_ctrl_logic.h" -+#endif -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+#include <linux/vsc.h> -+#endif -+ -+#define OV01A1S_LINK_FREQ_400MHZ 400000000ULL -+#define OV01A1S_SCLK 40000000LL -+#define OV01A1S_MCLK 19200000 -+#define OV01A1S_DATA_LANES 1 -+#define OV01A1S_RGB_DEPTH 10 -+ -+#define OV01A1S_REG_CHIP_ID 0x300a -+#define OV01A1S_CHIP_ID 0x560141 -+ -+#define OV01A1S_REG_MODE_SELECT 0x0100 -+#define OV01A1S_MODE_STANDBY 0x00 -+#define OV01A1S_MODE_STREAMING 0x01 -+ -+/* vertical-timings from sensor */ -+#define OV01A1S_REG_VTS 0x380e -+#define OV01A1S_VTS_DEF 0x0380 -+#define OV01A1S_VTS_MIN 0x0380 -+#define OV01A1S_VTS_MAX 0xffff -+ -+/* Exposure controls from sensor */ -+#define OV01A1S_REG_EXPOSURE 0x3501 -+#define OV01A1S_EXPOSURE_MIN 4 -+#define OV01A1S_EXPOSURE_MAX_MARGIN 8 -+#define OV01A1S_EXPOSURE_STEP 1 -+ -+/* Analog gain controls from sensor */ -+#define OV01A1S_REG_ANALOG_GAIN 0x3508 -+#define OV01A1S_ANAL_GAIN_MIN 0x100 -+#define OV01A1S_ANAL_GAIN_MAX 0xffff -+#define OV01A1S_ANAL_GAIN_STEP 1 -+ -+/* Digital gain controls from sensor */ -+#define OV01A1S_REG_DIGILAL_GAIN_B 0x350A -+#define OV01A1S_REG_DIGITAL_GAIN_GB 0x3510 -+#define OV01A1S_REG_DIGITAL_GAIN_GR 0x3513 -+#define OV01A1S_REG_DIGITAL_GAIN_R 0x3516 -+#define OV01A1S_DGTL_GAIN_MIN 0 -+#define OV01A1S_DGTL_GAIN_MAX 0x3ffff -+#define OV01A1S_DGTL_GAIN_STEP 1 -+#define OV01A1S_DGTL_GAIN_DEFAULT 1024 -+ -+/* Test Pattern Control */ -+#define OV01A1S_REG_TEST_PATTERN 0x4503 -+#define OV01A1S_TEST_PATTERN_ENABLE BIT(7) -+#define OV01A1S_TEST_PATTERN_BAR_SHIFT 0 -+ -+enum { -+ OV01A1S_LINK_FREQ_400MHZ_INDEX, -+}; -+ -+struct ov01a1s_reg { -+ u16 address; -+ u8 val; -+}; -+ -+struct ov01a1s_reg_list { -+ u32 num_of_regs; -+ const struct ov01a1s_reg *regs; -+}; -+ -+struct ov01a1s_link_freq_config { -+ const struct ov01a1s_reg_list reg_list; -+}; -+ -+struct ov01a1s_mode { -+ /* Frame width in pixels */ -+ u32 width; -+ -+ /* Frame height in pixels */ -+ u32 height; -+ -+ /* Horizontal timining size */ -+ u32 hts; -+ -+ /* Default vertical timining size */ -+ u32 vts_def; -+ -+ /* Min vertical timining size */ -+ u32 vts_min; -+ -+ /* Link frequency needed for this resolution */ -+ u32 link_freq_index; -+ -+ /* Sensor register settings for this resolution */ -+ const struct ov01a1s_reg_list reg_list; -+}; -+ -+static const struct ov01a1s_reg mipi_data_rate_720mbps[] = { -+}; -+ -+static const struct ov01a1s_reg sensor_1296x800_setting[] = { -+ {0x0103, 0x01}, -+ {0x0302, 0x00}, -+ {0x0303, 0x06}, -+ {0x0304, 0x01}, -+ {0x0305, 0x90}, -+ {0x0306, 0x00}, -+ {0x0308, 0x01}, -+ {0x0309, 0x00}, -+ {0x030c, 0x01}, -+ {0x0322, 0x01}, -+ {0x0323, 0x06}, -+ {0x0324, 0x01}, -+ {0x0325, 0x68}, -+ {0x3002, 0xa1}, -+ {0x301e, 0xf0}, -+ {0x3022, 0x01}, -+ {0x3501, 0x03}, -+ {0x3502, 0x78}, -+ {0x3504, 0x0c}, -+ {0x3508, 0x01}, -+ {0x3509, 0x00}, -+ {0x3601, 0xc0}, -+ {0x3603, 0x71}, -+ {0x3610, 0x68}, -+ {0x3611, 0x86}, -+ {0x3640, 0x10}, -+ {0x3641, 0x80}, -+ {0x3642, 0xdc}, -+ {0x3646, 0x55}, -+ {0x3647, 0x57}, -+ {0x364b, 0x00}, -+ {0x3653, 0x10}, -+ {0x3655, 0x00}, -+ {0x3656, 0x00}, -+ {0x365f, 0x0f}, -+ {0x3661, 0x45}, -+ {0x3662, 0x24}, -+ {0x3663, 0x11}, -+ {0x3664, 0x07}, -+ {0x3709, 0x34}, -+ {0x370b, 0x6f}, -+ {0x3714, 0x22}, -+ {0x371b, 0x27}, -+ {0x371c, 0x67}, -+ {0x371d, 0xa7}, -+ {0x371e, 0xe7}, -+ {0x3730, 0x81}, -+ {0x3733, 0x10}, -+ {0x3734, 0x40}, -+ {0x3737, 0x04}, -+ {0x3739, 0x1c}, -+ {0x3767, 0x00}, -+ {0x376c, 0x81}, -+ {0x3772, 0x14}, -+ {0x37c2, 0x04}, -+ {0x37d8, 0x03}, -+ {0x37d9, 0x0c}, -+ {0x37e0, 0x00}, -+ {0x37e1, 0x08}, -+ {0x37e2, 0x10}, -+ {0x37e3, 0x04}, -+ {0x37e4, 0x04}, -+ {0x37e5, 0x03}, -+ {0x37e6, 0x04}, -+ {0x3800, 0x00}, -+ {0x3801, 0x00}, -+ {0x3802, 0x00}, -+ {0x3803, 0x00}, -+ {0x3804, 0x05}, -+ {0x3805, 0x0f}, -+ {0x3806, 0x03}, -+ {0x3807, 0x2f}, -+ {0x3808, 0x05}, -+ {0x3809, 0x00}, -+ {0x380a, 0x03}, -+ {0x380b, 0x1e}, -+ {0x380c, 0x05}, -+ {0x380d, 0xd0}, -+ {0x380e, 0x03}, -+ {0x380f, 0x80}, -+ {0x3810, 0x00}, -+ {0x3811, 0x09}, -+ {0x3812, 0x00}, -+ {0x3813, 0x08}, -+ {0x3814, 0x01}, -+ {0x3815, 0x01}, -+ {0x3816, 0x01}, -+ {0x3817, 0x01}, -+ {0x3820, 0xa8}, -+ {0x3822, 0x03}, -+ {0x3832, 0x28}, -+ {0x3833, 0x10}, -+ {0x3b00, 0x00}, -+ {0x3c80, 0x00}, -+ {0x3c88, 0x02}, -+ {0x3c8c, 0x07}, -+ {0x3c8d, 0x40}, -+ {0x3cc7, 0x80}, -+ {0x4000, 0xc3}, -+ {0x4001, 0xe0}, -+ {0x4003, 0x40}, -+ {0x4008, 0x02}, -+ {0x4009, 0x19}, -+ {0x400a, 0x01}, -+ {0x400b, 0x6c}, -+ {0x4011, 0x00}, -+ {0x4041, 0x00}, -+ {0x4300, 0xff}, -+ {0x4301, 0x00}, -+ {0x4302, 0x0f}, -+ {0x4503, 0x00}, -+ {0x4601, 0x50}, -+ {0x481f, 0x34}, -+ {0x4825, 0x33}, -+ {0x4837, 0x14}, -+ {0x4881, 0x40}, -+ {0x4883, 0x01}, -+ {0x4890, 0x00}, -+ {0x4901, 0x00}, -+ {0x4902, 0x00}, -+ {0x4b00, 0x2a}, -+ {0x4b0d, 0x00}, -+ {0x450a, 0x04}, -+ {0x450b, 0x00}, -+ {0x5000, 0x65}, -+ {0x5004, 0x00}, -+ {0x5080, 0x40}, -+ {0x5200, 0x18}, -+ {0x4837, 0x14}, -+ {0x0305, 0xf4}, -+ {0x0325, 0xc2}, -+ {0x3808, 0x05}, -+ {0x3809, 0x10}, -+ {0x380a, 0x03}, -+ {0x380b, 0x1e}, -+ {0x3810, 0x00}, -+ {0x3811, 0x00}, -+ {0x3812, 0x00}, -+ {0x3813, 0x09}, -+ {0x3820, 0x88}, -+ {0x373d, 0x24}, -+}; -+ -+static const char * const ov01a1s_test_pattern_menu[] = { -+ "Disabled", -+ "Color Bar", -+ "Top-Bottom Darker Color Bar", -+ "Right-Left Darker Color Bar", -+ "Color Bar type 4", -+}; -+ -+static const s64 link_freq_menu_items[] = { -+ OV01A1S_LINK_FREQ_400MHZ, -+}; -+ -+static const struct ov01a1s_link_freq_config link_freq_configs[] = { -+ [OV01A1S_LINK_FREQ_400MHZ_INDEX] = { -+ .reg_list = { -+ .num_of_regs = ARRAY_SIZE(mipi_data_rate_720mbps), -+ .regs = mipi_data_rate_720mbps, -+ } -+ }, -+}; -+ -+static const struct ov01a1s_mode supported_modes[] = { -+ { -+ .width = 1296, -+ .height = 798, -+ .hts = 1488, -+ .vts_def = OV01A1S_VTS_DEF, -+ .vts_min = OV01A1S_VTS_MIN, -+ .reg_list = { -+ .num_of_regs = ARRAY_SIZE(sensor_1296x800_setting), -+ .regs = sensor_1296x800_setting, -+ }, -+ .link_freq_index = OV01A1S_LINK_FREQ_400MHZ_INDEX, -+ }, -+}; -+ -+struct ov01a1s { -+ struct v4l2_subdev sd; -+ struct media_pad pad; -+ struct v4l2_ctrl_handler ctrl_handler; -+ -+ /* V4L2 Controls */ -+ struct v4l2_ctrl *link_freq; -+ struct v4l2_ctrl *pixel_rate; -+ struct v4l2_ctrl *vblank; -+ struct v4l2_ctrl *hblank; -+ struct v4l2_ctrl *exposure; -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ struct v4l2_ctrl *privacy_status; -+ -+ /* VSC settings */ -+ struct vsc_mipi_config conf; -+ struct vsc_camera_status status; -+#endif -+ -+ /* Current mode */ -+ const struct ov01a1s_mode *cur_mode; -+ -+ /* To serialize asynchronus callbacks */ -+ struct mutex mutex; -+ -+ /* i2c client */ -+ struct i2c_client *client; -+ -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+ /* GPIO for reset */ -+ struct gpio_desc *reset_gpio; -+ /* GPIO for powerdown */ -+ struct gpio_desc *powerdown_gpio; -+ /* Power enable */ -+ struct regulator *avdd; -+ /* Clock provider */ -+ struct clk *clk; -+#endif -+ -+ enum { -+ OV01A1S_USE_DEFAULT = 0, -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) || IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -+ OV01A1S_USE_INT3472 = 1, -+#endif -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ OV01A1S_USE_INTEL_VSC = 2, -+#endif -+ } power_type; -+ -+ /* Streaming on/off */ -+ bool streaming; -+}; -+ -+static inline struct ov01a1s *to_ov01a1s(struct v4l2_subdev *subdev) -+{ -+ return container_of(subdev, struct ov01a1s, sd); -+} -+ -+static int ov01a1s_read_reg(struct ov01a1s *ov01a1s, u16 reg, u16 len, u32 *val) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ struct i2c_msg msgs[2]; -+ u8 addr_buf[2]; -+ u8 data_buf[4] = {0}; -+ int ret = 0; -+ -+ if (len > sizeof(data_buf)) -+ return -EINVAL; -+ -+ put_unaligned_be16(reg, addr_buf); -+ msgs[0].addr = client->addr; -+ msgs[0].flags = 0; -+ msgs[0].len = sizeof(addr_buf); -+ msgs[0].buf = addr_buf; -+ msgs[1].addr = client->addr; -+ msgs[1].flags = I2C_M_RD; -+ msgs[1].len = len; -+ msgs[1].buf = &data_buf[sizeof(data_buf) - len]; -+ -+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); -+ if (ret != ARRAY_SIZE(msgs)) -+ return ret < 0 ? ret : -EIO; -+ -+ *val = get_unaligned_be32(data_buf); -+ -+ return 0; -+} -+ -+static int ov01a1s_write_reg(struct ov01a1s *ov01a1s, u16 reg, u16 len, u32 val) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ u8 buf[6]; -+ int ret = 0; -+ -+ if (len > 4) -+ return -EINVAL; -+ -+ put_unaligned_be16(reg, buf); -+ put_unaligned_be32(val << 8 * (4 - len), buf + 2); -+ -+ ret = i2c_master_send(client, buf, len + 2); -+ if (ret != len + 2) -+ return ret < 0 ? ret : -EIO; -+ -+ return 0; -+} -+ -+static int ov01a1s_write_reg_list(struct ov01a1s *ov01a1s, -+ const struct ov01a1s_reg_list *r_list) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ unsigned int i; -+ int ret = 0; -+ -+ for (i = 0; i < r_list->num_of_regs; i++) { -+ ret = ov01a1s_write_reg(ov01a1s, r_list->regs[i].address, 1, -+ r_list->regs[i].val); -+ if (ret) { -+ dev_err_ratelimited(&client->dev, -+ "write reg 0x%4.4x return err = %d", -+ r_list->regs[i].address, ret); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int ov01a1s_update_digital_gain(struct ov01a1s *ov01a1s, u32 d_gain) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ u32 real = d_gain << 6; -+ int ret = 0; -+ -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_DIGILAL_GAIN_B, 3, real); -+ if (ret) { -+ dev_err(&client->dev, "failed to set OV01A1S_REG_DIGITAL_GAIN_B"); -+ return ret; -+ } -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_DIGITAL_GAIN_GB, 3, real); -+ if (ret) { -+ dev_err(&client->dev, "failed to set OV01A1S_REG_DIGITAL_GAIN_GB"); -+ return ret; -+ } -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_DIGITAL_GAIN_GR, 3, real); -+ if (ret) { -+ dev_err(&client->dev, "failed to set OV01A1S_REG_DIGITAL_GAIN_GR"); -+ return ret; -+ } -+ -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_DIGITAL_GAIN_R, 3, real); -+ if (ret) { -+ dev_err(&client->dev, "failed to set OV01A1S_REG_DIGITAL_GAIN_R"); -+ return ret; -+ } -+ return ret; -+} -+ -+static int ov01a1s_test_pattern(struct ov01a1s *ov01a1s, u32 pattern) -+{ -+ if (pattern) -+ pattern = (pattern - 1) << OV01A1S_TEST_PATTERN_BAR_SHIFT | -+ OV01A1S_TEST_PATTERN_ENABLE; -+ -+ return ov01a1s_write_reg(ov01a1s, OV01A1S_REG_TEST_PATTERN, 1, pattern); -+} -+ -+static int ov01a1s_set_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct ov01a1s *ov01a1s = container_of(ctrl->handler, -+ struct ov01a1s, ctrl_handler); -+ struct i2c_client *client = ov01a1s->client; -+ s64 exposure_max; -+ int ret = 0; -+ -+ /* Propagate change of current control to all related controls */ -+ if (ctrl->id == V4L2_CID_VBLANK) { -+ /* Update max exposure while meeting expected vblanking */ -+ exposure_max = ov01a1s->cur_mode->height + ctrl->val - -+ OV01A1S_EXPOSURE_MAX_MARGIN; -+ __v4l2_ctrl_modify_range(ov01a1s->exposure, -+ ov01a1s->exposure->minimum, -+ exposure_max, ov01a1s->exposure->step, -+ exposure_max); -+ } -+ -+ /* V4L2 controls values will be applied only when power is already up */ -+ if (!pm_runtime_get_if_in_use(&client->dev)) -+ return 0; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_ANALOGUE_GAIN: -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_ANALOG_GAIN, 2, -+ ctrl->val); -+ break; -+ -+ case V4L2_CID_DIGITAL_GAIN: -+ ret = ov01a1s_update_digital_gain(ov01a1s, ctrl->val); -+ break; -+ -+ case V4L2_CID_EXPOSURE: -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_EXPOSURE, 2, -+ ctrl->val); -+ break; -+ -+ case V4L2_CID_VBLANK: -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_VTS, 2, -+ ov01a1s->cur_mode->height + ctrl->val); -+ break; -+ -+ case V4L2_CID_TEST_PATTERN: -+ ret = ov01a1s_test_pattern(ov01a1s, ctrl->val); -+ break; -+ -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ case V4L2_CID_PRIVACY: -+ dev_dbg(&client->dev, "set privacy to %d", ctrl->val); -+ break; -+ -+#endif -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ -+ pm_runtime_put(&client->dev); -+ -+ return ret; -+} -+ -+static const struct v4l2_ctrl_ops ov01a1s_ctrl_ops = { -+ .s_ctrl = ov01a1s_set_ctrl, -+}; -+ -+static int ov01a1s_init_controls(struct ov01a1s *ov01a1s) -+{ -+ struct v4l2_ctrl_handler *ctrl_hdlr; -+ const struct ov01a1s_mode *cur_mode; -+ s64 exposure_max, h_blank; -+ u32 vblank_min, vblank_max, vblank_default; -+ int size; -+ int ret = 0; -+ -+ ctrl_hdlr = &ov01a1s->ctrl_handler; -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9); -+#else -+ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); -+#endif -+ if (ret) -+ return ret; -+ -+ ctrl_hdlr->lock = &ov01a1s->mutex; -+ cur_mode = ov01a1s->cur_mode; -+ size = ARRAY_SIZE(link_freq_menu_items); -+ -+ ov01a1s->link_freq = v4l2_ctrl_new_int_menu(ctrl_hdlr, -+ &ov01a1s_ctrl_ops, -+ V4L2_CID_LINK_FREQ, -+ size - 1, 0, -+ link_freq_menu_items); -+ if (ov01a1s->link_freq) -+ ov01a1s->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; -+ -+ ov01a1s->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, -+ V4L2_CID_PIXEL_RATE, 0, -+ OV01A1S_SCLK, 1, OV01A1S_SCLK); -+ -+ vblank_min = cur_mode->vts_min - cur_mode->height; -+ vblank_max = OV01A1S_VTS_MAX - cur_mode->height; -+ vblank_default = cur_mode->vts_def - cur_mode->height; -+ ov01a1s->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, -+ V4L2_CID_VBLANK, vblank_min, -+ vblank_max, 1, vblank_default); -+ -+ h_blank = cur_mode->hts - cur_mode->width; -+ ov01a1s->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, -+ V4L2_CID_HBLANK, h_blank, h_blank, -+ 1, h_blank); -+ if (ov01a1s->hblank) -+ ov01a1s->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ ov01a1s->privacy_status = v4l2_ctrl_new_std(ctrl_hdlr, -+ &ov01a1s_ctrl_ops, -+ V4L2_CID_PRIVACY, -+ 0, 1, 1, 0); -+#endif -+ -+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, -+ OV01A1S_ANAL_GAIN_MIN, OV01A1S_ANAL_GAIN_MAX, -+ OV01A1S_ANAL_GAIN_STEP, OV01A1S_ANAL_GAIN_MIN); -+ v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, V4L2_CID_DIGITAL_GAIN, -+ OV01A1S_DGTL_GAIN_MIN, OV01A1S_DGTL_GAIN_MAX, -+ OV01A1S_DGTL_GAIN_STEP, OV01A1S_DGTL_GAIN_DEFAULT); -+ exposure_max = cur_mode->vts_def - OV01A1S_EXPOSURE_MAX_MARGIN; -+ ov01a1s->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, -+ V4L2_CID_EXPOSURE, -+ OV01A1S_EXPOSURE_MIN, -+ exposure_max, -+ OV01A1S_EXPOSURE_STEP, -+ exposure_max); -+ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &ov01a1s_ctrl_ops, -+ V4L2_CID_TEST_PATTERN, -+ ARRAY_SIZE(ov01a1s_test_pattern_menu) - 1, -+ 0, 0, ov01a1s_test_pattern_menu); -+ if (ctrl_hdlr->error) -+ return ctrl_hdlr->error; -+ -+ ov01a1s->sd.ctrl_handler = ctrl_hdlr; -+ -+ return 0; -+} -+ -+static void ov01a1s_update_pad_format(const struct ov01a1s_mode *mode, -+ struct v4l2_mbus_framefmt *fmt) -+{ -+ fmt->width = mode->width; -+ fmt->height = mode->height; -+ fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; -+ fmt->field = V4L2_FIELD_NONE; -+} -+ -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+static void ov01a1s_vsc_privacy_callback(void *handle, -+ enum vsc_privacy_status status) -+{ -+ struct ov01a1s *ov01a1s = handle; -+ -+ v4l2_ctrl_s_ctrl(ov01a1s->privacy_status, !status); -+} -+ -+#endif -+static int ov01a1s_start_streaming(struct ov01a1s *ov01a1s) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ const struct ov01a1s_reg_list *reg_list; -+ int link_freq_index; -+ int ret = 0; -+ -+ link_freq_index = ov01a1s->cur_mode->link_freq_index; -+ reg_list = &link_freq_configs[link_freq_index].reg_list; -+ ret = ov01a1s_write_reg_list(ov01a1s, reg_list); -+ if (ret) { -+ dev_err(&client->dev, "failed to set plls"); -+ return ret; -+ } -+ -+ reg_list = &ov01a1s->cur_mode->reg_list; -+ ret = ov01a1s_write_reg_list(ov01a1s, reg_list); -+ if (ret) { -+ dev_err(&client->dev, "failed to set mode"); -+ return ret; -+ } -+ -+ ret = __v4l2_ctrl_handler_setup(ov01a1s->sd.ctrl_handler); -+ if (ret) -+ return ret; -+ -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_MODE_SELECT, 1, -+ OV01A1S_MODE_STREAMING); -+ if (ret) -+ dev_err(&client->dev, "failed to start streaming"); -+ -+ return ret; -+} -+ -+static void ov01a1s_stop_streaming(struct ov01a1s *ov01a1s) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ int ret = 0; -+ -+ ret = ov01a1s_write_reg(ov01a1s, OV01A1S_REG_MODE_SELECT, 1, -+ OV01A1S_MODE_STANDBY); -+ if (ret) -+ dev_err(&client->dev, "failed to stop streaming"); -+} -+ -+static int ov01a1s_set_stream(struct v4l2_subdev *sd, int enable) -+{ -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ struct i2c_client *client = ov01a1s->client; -+ int ret = 0; -+ -+ if (ov01a1s->streaming == enable) -+ return 0; -+ -+ mutex_lock(&ov01a1s->mutex); -+ if (enable) { -+ ret = pm_runtime_get_sync(&client->dev); -+ if (ret < 0) { -+ pm_runtime_put_noidle(&client->dev); -+ mutex_unlock(&ov01a1s->mutex); -+ return ret; -+ } -+ -+ ret = ov01a1s_start_streaming(ov01a1s); -+ if (ret) { -+ enable = 0; -+ ov01a1s_stop_streaming(ov01a1s); -+ pm_runtime_put(&client->dev); -+ } -+ } else { -+ ov01a1s_stop_streaming(ov01a1s); -+ pm_runtime_put(&client->dev); -+ } -+ -+ ov01a1s->streaming = enable; -+ mutex_unlock(&ov01a1s->mutex); -+ -+ return ret; -+} -+ -+static int ov01a1s_power_off(struct device *dev) -+{ -+ struct v4l2_subdev *sd = dev_get_drvdata(dev); -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ int ret = 0; -+ -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+ if (ov01a1s->power_type == OV01A1S_USE_INT3472) { -+ gpiod_set_value_cansleep(ov01a1s->reset_gpio, 1); -+ gpiod_set_value_cansleep(ov01a1s->powerdown_gpio, 1); -+ if (ov01a1s->avdd) -+ ret = regulator_disable(ov01a1s->avdd); -+ clk_disable_unprepare(ov01a1s->clk); -+ msleep(20); -+ } -+#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -+ if (ov01a1s->power_type == OV01A1S_USE_INT3472) -+ ret = power_ctrl_logic_set_power(0); -+#endif -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ if (ov01a1s->power_type == OV01A1S_USE_INTEL_VSC) { -+ ret = vsc_release_camera_sensor(&ov01a1s->status); -+ if (ret && ret != -EAGAIN) -+ dev_err(dev, "Release VSC failed"); -+ } -+#endif -+ -+ return ret; -+} -+ -+static int ov01a1s_power_on(struct device *dev) -+{ -+ struct v4l2_subdev *sd = dev_get_drvdata(dev); -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ int ret = 0; -+ -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+ if (ov01a1s->power_type == OV01A1S_USE_INT3472) { -+ ret = clk_prepare_enable(ov01a1s->clk); -+ if (ret) -+ return ret; -+ if (ov01a1s->avdd) -+ ret = regulator_enable(ov01a1s->avdd); -+ if (ret) -+ return ret; -+ gpiod_set_value_cansleep(ov01a1s->powerdown_gpio, 0); -+ gpiod_set_value_cansleep(ov01a1s->reset_gpio, 0); -+ msleep(20); -+ } -+#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -+ if (ov01a1s->power_type == OV01A1S_USE_INT3472) -+ ret = power_ctrl_logic_set_power(1); -+#endif -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ if (ov01a1s->power_type == OV01A1S_USE_INTEL_VSC) { -+ ret = vsc_acquire_camera_sensor(&ov01a1s->conf, -+ ov01a1s_vsc_privacy_callback, -+ ov01a1s, &ov01a1s->status); -+ if (ret && ret != -EAGAIN) { -+ dev_err(dev, "Acquire VSC failed"); -+ return ret; -+ } -+ __v4l2_ctrl_s_ctrl(ov01a1s->privacy_status, -+ !(ov01a1s->status.status)); -+ } -+#endif -+ -+ return ret; -+} -+ -+static int __maybe_unused ov01a1s_suspend(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct v4l2_subdev *sd = i2c_get_clientdata(client); -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ -+ mutex_lock(&ov01a1s->mutex); -+ if (ov01a1s->streaming) -+ ov01a1s_stop_streaming(ov01a1s); -+ -+ mutex_unlock(&ov01a1s->mutex); -+ -+ return 0; -+} -+ -+static int __maybe_unused ov01a1s_resume(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct v4l2_subdev *sd = i2c_get_clientdata(client); -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ int ret = 0; -+ -+ mutex_lock(&ov01a1s->mutex); -+ if (!ov01a1s->streaming) -+ goto exit; -+ -+ ret = ov01a1s_start_streaming(ov01a1s); -+ if (ret) { -+ ov01a1s->streaming = false; -+ ov01a1s_stop_streaming(ov01a1s); -+ } -+ -+exit: -+ mutex_unlock(&ov01a1s->mutex); -+ return ret; -+} -+ -+static int ov01a1s_set_format(struct v4l2_subdev *sd, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ struct v4l2_subdev_pad_config *cfg, -+#else -+ struct v4l2_subdev_state *sd_state, -+#endif -+ struct v4l2_subdev_format *fmt) -+{ -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ const struct ov01a1s_mode *mode; -+ s32 vblank_def, h_blank; -+ -+ mode = v4l2_find_nearest_size(supported_modes, -+ ARRAY_SIZE(supported_modes), width, -+ height, fmt->format.width, -+ fmt->format.height); -+ -+ mutex_lock(&ov01a1s->mutex); -+ ov01a1s_update_pad_format(mode, &fmt->format); -+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; -+#else -+ *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; -+#endif -+ } else { -+ ov01a1s->cur_mode = mode; -+ __v4l2_ctrl_s_ctrl(ov01a1s->link_freq, mode->link_freq_index); -+ __v4l2_ctrl_s_ctrl_int64(ov01a1s->pixel_rate, OV01A1S_SCLK); -+ -+ /* Update limits and set FPS to default */ -+ vblank_def = mode->vts_def - mode->height; -+ __v4l2_ctrl_modify_range(ov01a1s->vblank, -+ mode->vts_min - mode->height, -+ OV01A1S_VTS_MAX - mode->height, 1, -+ vblank_def); -+ __v4l2_ctrl_s_ctrl(ov01a1s->vblank, vblank_def); -+ h_blank = mode->hts - mode->width; -+ __v4l2_ctrl_modify_range(ov01a1s->hblank, h_blank, h_blank, 1, -+ h_blank); -+ } -+ mutex_unlock(&ov01a1s->mutex); -+ -+ return 0; -+} -+ -+static int ov01a1s_get_format(struct v4l2_subdev *sd, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ struct v4l2_subdev_pad_config *cfg, -+#else -+ struct v4l2_subdev_state *sd_state, -+#endif -+ struct v4l2_subdev_format *fmt) -+{ -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ -+ mutex_lock(&ov01a1s->mutex); -+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, cfg, -+ fmt->pad); -+#else -+ fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, -+ sd_state, fmt->pad); -+#endif -+ else -+ ov01a1s_update_pad_format(ov01a1s->cur_mode, &fmt->format); -+ -+ mutex_unlock(&ov01a1s->mutex); -+ -+ return 0; -+} -+ -+static int ov01a1s_enum_mbus_code(struct v4l2_subdev *sd, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ struct v4l2_subdev_pad_config *cfg, -+#else -+ struct v4l2_subdev_state *sd_state, -+#endif -+ struct v4l2_subdev_mbus_code_enum *code) -+{ -+ if (code->index > 0) -+ return -EINVAL; -+ -+ code->code = MEDIA_BUS_FMT_SGRBG10_1X10; -+ -+ return 0; -+} -+ -+static int ov01a1s_enum_frame_size(struct v4l2_subdev *sd, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ struct v4l2_subdev_pad_config *cfg, -+#else -+ struct v4l2_subdev_state *sd_state, -+#endif -+ struct v4l2_subdev_frame_size_enum *fse) -+{ -+ if (fse->index >= ARRAY_SIZE(supported_modes)) -+ return -EINVAL; -+ -+ if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) -+ return -EINVAL; -+ -+ fse->min_width = supported_modes[fse->index].width; -+ fse->max_width = fse->min_width; -+ fse->min_height = supported_modes[fse->index].height; -+ fse->max_height = fse->min_height; -+ -+ return 0; -+} -+ -+static int ov01a1s_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) -+{ -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ -+ mutex_lock(&ov01a1s->mutex); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) -+ ov01a1s_update_pad_format(&supported_modes[0], -+ v4l2_subdev_get_try_format(sd, fh->pad, 0)); -+#else -+ ov01a1s_update_pad_format(&supported_modes[0], -+ v4l2_subdev_get_try_format(sd, fh->state, 0)); -+#endif -+ mutex_unlock(&ov01a1s->mutex); -+ -+ return 0; -+} -+ -+static const struct v4l2_subdev_video_ops ov01a1s_video_ops = { -+ .s_stream = ov01a1s_set_stream, -+}; -+ -+static const struct v4l2_subdev_pad_ops ov01a1s_pad_ops = { -+ .set_fmt = ov01a1s_set_format, -+ .get_fmt = ov01a1s_get_format, -+ .enum_mbus_code = ov01a1s_enum_mbus_code, -+ .enum_frame_size = ov01a1s_enum_frame_size, -+}; -+ -+static const struct v4l2_subdev_ops ov01a1s_subdev_ops = { -+ .video = &ov01a1s_video_ops, -+ .pad = &ov01a1s_pad_ops, -+}; -+ -+static const struct media_entity_operations ov01a1s_subdev_entity_ops = { -+ .link_validate = v4l2_subdev_link_validate, -+}; -+ -+static const struct v4l2_subdev_internal_ops ov01a1s_internal_ops = { -+ .open = ov01a1s_open, -+}; -+ -+static int ov01a1s_identify_module(struct ov01a1s *ov01a1s) -+{ -+ struct i2c_client *client = ov01a1s->client; -+ int ret; -+ u32 val; -+ -+ ret = ov01a1s_read_reg(ov01a1s, OV01A1S_REG_CHIP_ID, 3, &val); -+ if (ret) -+ return ret; -+ -+ if (val != OV01A1S_CHIP_ID) { -+ dev_err(&client->dev, "chip id mismatch: %x!=%x", -+ OV01A1S_CHIP_ID, val); -+ return -ENXIO; -+ } -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0) -+static int ov01a1s_remove(struct i2c_client *client) -+#else -+static void ov01a1s_remove(struct i2c_client *client) -+#endif -+{ -+ struct v4l2_subdev *sd = i2c_get_clientdata(client); -+ struct ov01a1s *ov01a1s = to_ov01a1s(sd); -+ -+ v4l2_async_unregister_subdev(sd); -+ media_entity_cleanup(&sd->entity); -+ v4l2_ctrl_handler_free(sd->ctrl_handler); -+ pm_runtime_disable(&client->dev); -+ mutex_destroy(&ov01a1s->mutex); -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0) -+ return 0; -+#endif -+} -+ -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+static int ov01a1s_parse_gpio(struct ov01a1s *ov01a1s) -+{ -+ struct device *dev = &ov01a1s->client->dev; -+ -+ ov01a1s->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); -+ if (IS_ERR(ov01a1s->reset_gpio)) { -+ dev_warn(dev, "error while getting reset gpio: %ld\n", -+ PTR_ERR(ov01a1s->reset_gpio)); -+ ov01a1s->reset_gpio = NULL; -+ return -EPROBE_DEFER; -+ } -+ -+ /* For optional, don't return or print warn if can't get it */ -+ ov01a1s->powerdown_gpio = -+ devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW); -+ if (IS_ERR(ov01a1s->powerdown_gpio)) { -+ dev_dbg(dev, "no powerdown gpio: %ld\n", -+ PTR_ERR(ov01a1s->powerdown_gpio)); -+ ov01a1s->powerdown_gpio = NULL; -+ } -+ -+ ov01a1s->avdd = devm_regulator_get_optional(dev, "avdd"); -+ if (IS_ERR(ov01a1s->avdd)) { -+ dev_dbg(dev, "no regulator avdd: %ld\n", -+ PTR_ERR(ov01a1s->avdd)); -+ ov01a1s->avdd = NULL; -+ } -+ -+ ov01a1s->clk = devm_clk_get_optional(dev, "clk"); -+ if (IS_ERR(ov01a1s->clk)) { -+ dev_dbg(dev, "no clk: %ld\n", PTR_ERR(ov01a1s->clk)); -+ ov01a1s->clk = NULL; -+ } -+ -+ return 0; -+} -+#endif -+ -+static int ov01a1s_parse_power(struct ov01a1s *ov01a1s) -+{ -+ int ret = 0; -+ -+#if IS_ENABLED(CONFIG_INTEL_VSC) -+ ov01a1s->conf.lane_num = OV01A1S_DATA_LANES; -+ /* frequency unit 100k */ -+ ov01a1s->conf.freq = OV01A1S_LINK_FREQ_400MHZ / 100000; -+ ret = vsc_acquire_camera_sensor(&ov01a1s->conf, NULL, NULL, &ov01a1s->status); -+ if (!ret) { -+ ov01a1s->power_type = OV01A1S_USE_INTEL_VSC; -+ return 0; -+ } else if (ret != -EAGAIN) { -+ return ret; -+ } -+#endif -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+ ret = ov01a1s_parse_gpio(ov01a1s); -+#elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -+ ret = power_ctrl_logic_set_power(1); -+#endif -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) || IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) -+ if (!ret) { -+ ov01a1s->power_type = OV01A1S_USE_INT3472; -+ return 0; -+ } -+#endif -+ if (ret == -EAGAIN) -+ return -EPROBE_DEFER; -+ -+ return ret; -+} -+ -+static int ov01a1s_probe(struct i2c_client *client) -+{ -+ struct ov01a1s *ov01a1s; -+ int ret = 0; -+ -+ ov01a1s = devm_kzalloc(&client->dev, sizeof(*ov01a1s), GFP_KERNEL); -+ if (!ov01a1s) -+ return -ENOMEM; -+ -+ ov01a1s->client = client; -+ ret = ov01a1s_parse_power(ov01a1s); -+ if (ret) -+ return ret; -+ -+ v4l2_i2c_subdev_init(&ov01a1s->sd, client, &ov01a1s_subdev_ops); -+#if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) -+ /* In other cases, power is up in ov01a1s_parse_power */ -+ if (ov01a1s->power_type == OV01A1S_USE_INT3472) -+ ov01a1s_power_on(&client->dev); -+#endif -+ ret = ov01a1s_identify_module(ov01a1s); -+ if (ret) { -+ dev_err(&client->dev, "failed to find sensor: %d", ret); -+ goto probe_error_power_off; -+ } -+ -+ mutex_init(&ov01a1s->mutex); -+ ov01a1s->cur_mode = &supported_modes[0]; -+ ret = ov01a1s_init_controls(ov01a1s); -+ if (ret) { -+ dev_err(&client->dev, "failed to init controls: %d", ret); -+ goto probe_error_v4l2_ctrl_handler_free; -+ } -+ -+ ov01a1s->sd.internal_ops = &ov01a1s_internal_ops; -+ ov01a1s->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; -+ ov01a1s->sd.entity.ops = &ov01a1s_subdev_entity_ops; -+ ov01a1s->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; -+ ov01a1s->pad.flags = MEDIA_PAD_FL_SOURCE; -+ ret = media_entity_pads_init(&ov01a1s->sd.entity, 1, &ov01a1s->pad); -+ if (ret) { -+ dev_err(&client->dev, "failed to init entity pads: %d", ret); -+ goto probe_error_v4l2_ctrl_handler_free; -+ } -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) -+ ret = v4l2_async_register_subdev_sensor_common(&ov01a1s->sd); -+#else -+ ret = v4l2_async_register_subdev_sensor(&ov01a1s->sd); -+#endif -+ if (ret < 0) { -+ dev_err(&client->dev, "failed to register V4L2 subdev: %d", -+ ret); -+ goto probe_error_media_entity_cleanup; -+ } -+ -+ /* -+ * Device is already turned on by i2c-core with ACPI domain PM. -+ * Enable runtime PM and turn off the device. -+ */ -+ pm_runtime_set_active(&client->dev); -+ pm_runtime_enable(&client->dev); -+ pm_runtime_idle(&client->dev); -+ -+ return 0; -+ -+probe_error_media_entity_cleanup: -+ media_entity_cleanup(&ov01a1s->sd.entity); -+ -+probe_error_v4l2_ctrl_handler_free: -+ v4l2_ctrl_handler_free(ov01a1s->sd.ctrl_handler); -+ mutex_destroy(&ov01a1s->mutex); -+ -+probe_error_power_off: -+ ov01a1s_power_off(&client->dev); -+ -+ return ret; -+} -+ -+static const struct dev_pm_ops ov01a1s_pm_ops = { -+ SET_SYSTEM_SLEEP_PM_OPS(ov01a1s_suspend, ov01a1s_resume) -+ SET_RUNTIME_PM_OPS(ov01a1s_power_off, ov01a1s_power_on, NULL) -+}; -+ -+#ifdef CONFIG_ACPI -+static const struct acpi_device_id ov01a1s_acpi_ids[] = { -+ { "OVTI01AS" }, -+ {} -+}; -+ -+MODULE_DEVICE_TABLE(acpi, ov01a1s_acpi_ids); -+#endif -+ -+static struct i2c_driver ov01a1s_i2c_driver = { -+ .driver = { -+ .name = "ov01a1s", -+ .pm = &ov01a1s_pm_ops, -+ .acpi_match_table = ACPI_PTR(ov01a1s_acpi_ids), -+ }, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) -+ .probe_new = ov01a1s_probe, -+#else -+ .probe = ov01a1s_probe, -+#endif -+ .remove = ov01a1s_remove, -+}; -+ -+module_i2c_driver(ov01a1s_i2c_driver); -+ -+MODULE_AUTHOR("Xu, Chongyang <chongyang.xu@intel.com>"); -+MODULE_AUTHOR("Lai, Jim <jim.lai@intel.com>"); -+MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>"); -+MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>"); -+MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>"); -+MODULE_DESCRIPTION("OmniVision OV01A1S sensor driver"); -+MODULE_LICENSE("GPL v2"); --- -2.45.2 - -From 5cdf8b2b159a7cfef03b67b7fd51da967345090c Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Mon, 6 Nov 2023 12:33:56 +0100 -Subject: [PATCH 2/3] media: ov01a1s: Remove non upstream iVSC support - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - drivers/media/i2c/ov01a1s.c | 71 ------------------------------------- - 1 file changed, 71 deletions(-) - -diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c -index 0dcce8b492b4..c97c1a661022 100644 ---- a/drivers/media/i2c/ov01a1s.c -+++ b/drivers/media/i2c/ov01a1s.c -@@ -17,9 +17,6 @@ - #elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) - #include "power_ctrl_logic.h" - #endif --#if IS_ENABLED(CONFIG_INTEL_VSC) --#include <linux/vsc.h> --#endif - - #define OV01A1S_LINK_FREQ_400MHZ 400000000ULL - #define OV01A1S_SCLK 40000000LL -@@ -302,13 +299,6 @@ struct ov01a1s { - struct v4l2_ctrl *vblank; - struct v4l2_ctrl *hblank; - struct v4l2_ctrl *exposure; --#if IS_ENABLED(CONFIG_INTEL_VSC) -- struct v4l2_ctrl *privacy_status; -- -- /* VSC settings */ -- struct vsc_mipi_config conf; -- struct vsc_camera_status status; --#endif - - /* Current mode */ - const struct ov01a1s_mode *cur_mode; -@@ -334,9 +324,6 @@ struct ov01a1s { - OV01A1S_USE_DEFAULT = 0, - #if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) || IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) - OV01A1S_USE_INT3472 = 1, --#endif --#if IS_ENABLED(CONFIG_INTEL_VSC) -- OV01A1S_USE_INTEL_VSC = 2, - #endif - } power_type; - -@@ -505,12 +492,6 @@ static int ov01a1s_set_ctrl(struct v4l2_ctrl *ctrl) - ret = ov01a1s_test_pattern(ov01a1s, ctrl->val); - break; - --#if IS_ENABLED(CONFIG_INTEL_VSC) -- case V4L2_CID_PRIVACY: -- dev_dbg(&client->dev, "set privacy to %d", ctrl->val); -- break; -- --#endif - default: - ret = -EINVAL; - break; -@@ -535,11 +516,7 @@ static int ov01a1s_init_controls(struct ov01a1s *ov01a1s) - int ret = 0; - - ctrl_hdlr = &ov01a1s->ctrl_handler; --#if IS_ENABLED(CONFIG_INTEL_VSC) -- ret = v4l2_ctrl_handler_init(ctrl_hdlr, 9); --#else - ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); --#endif - if (ret) - return ret; - -@@ -572,12 +549,6 @@ static int ov01a1s_init_controls(struct ov01a1s *ov01a1s) - 1, h_blank); - if (ov01a1s->hblank) - ov01a1s->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; --#if IS_ENABLED(CONFIG_INTEL_VSC) -- ov01a1s->privacy_status = v4l2_ctrl_new_std(ctrl_hdlr, -- &ov01a1s_ctrl_ops, -- V4L2_CID_PRIVACY, -- 0, 1, 1, 0); --#endif - - v4l2_ctrl_new_std(ctrl_hdlr, &ov01a1s_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, - OV01A1S_ANAL_GAIN_MIN, OV01A1S_ANAL_GAIN_MAX, -@@ -613,16 +584,6 @@ static void ov01a1s_update_pad_format(const struct ov01a1s_mode *mode, - fmt->field = V4L2_FIELD_NONE; - } - --#if IS_ENABLED(CONFIG_INTEL_VSC) --static void ov01a1s_vsc_privacy_callback(void *handle, -- enum vsc_privacy_status status) --{ -- struct ov01a1s *ov01a1s = handle; -- -- v4l2_ctrl_s_ctrl(ov01a1s->privacy_status, !status); --} -- --#endif - static int ov01a1s_start_streaming(struct ov01a1s *ov01a1s) - { - struct i2c_client *client = ov01a1s->client; -@@ -722,13 +683,6 @@ static int ov01a1s_power_off(struct device *dev) - if (ov01a1s->power_type == OV01A1S_USE_INT3472) - ret = power_ctrl_logic_set_power(0); - #endif --#if IS_ENABLED(CONFIG_INTEL_VSC) -- if (ov01a1s->power_type == OV01A1S_USE_INTEL_VSC) { -- ret = vsc_release_camera_sensor(&ov01a1s->status); -- if (ret && ret != -EAGAIN) -- dev_err(dev, "Release VSC failed"); -- } --#endif - - return ret; - } -@@ -756,19 +710,6 @@ static int ov01a1s_power_on(struct device *dev) - if (ov01a1s->power_type == OV01A1S_USE_INT3472) - ret = power_ctrl_logic_set_power(1); - #endif --#if IS_ENABLED(CONFIG_INTEL_VSC) -- if (ov01a1s->power_type == OV01A1S_USE_INTEL_VSC) { -- ret = vsc_acquire_camera_sensor(&ov01a1s->conf, -- ov01a1s_vsc_privacy_callback, -- ov01a1s, &ov01a1s->status); -- if (ret && ret != -EAGAIN) { -- dev_err(dev, "Acquire VSC failed"); -- return ret; -- } -- __v4l2_ctrl_s_ctrl(ov01a1s->privacy_status, -- !(ov01a1s->status.status)); -- } --#endif - - return ret; - } -@@ -1044,18 +985,6 @@ static int ov01a1s_parse_power(struct ov01a1s *ov01a1s) - { - int ret = 0; - --#if IS_ENABLED(CONFIG_INTEL_VSC) -- ov01a1s->conf.lane_num = OV01A1S_DATA_LANES; -- /* frequency unit 100k */ -- ov01a1s->conf.freq = OV01A1S_LINK_FREQ_400MHZ / 100000; -- ret = vsc_acquire_camera_sensor(&ov01a1s->conf, NULL, NULL, &ov01a1s->status); -- if (!ret) { -- ov01a1s->power_type = OV01A1S_USE_INTEL_VSC; -- return 0; -- } else if (ret != -EAGAIN) { -- return ret; -- } --#endif - #if IS_ENABLED(CONFIG_INTEL_SKL_INT3472) - ret = ov01a1s_parse_gpio(ov01a1s); - #elif IS_ENABLED(CONFIG_POWER_CTRL_LOGIC) --- -2.45.2 - -From 5ccd06ac4351f3eb8146c1109446fc80aeaa873f Mon Sep 17 00:00:00 2001 -From: Florian Klink <flokli@flokli.de> -Date: Sun, 17 Mar 2024 14:24:05 +0200 -Subject: [PATCH 3/3] ov01a1s.c: support Linux 6.8.0 - -Used https://github.com/intel/ipu6-drivers/pull/213 as an inspiration. ---- - drivers/media/i2c/ov01a1s.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c -index c97c1a661022..22b406bdeae9 100644 ---- a/drivers/media/i2c/ov01a1s.c -+++ b/drivers/media/i2c/ov01a1s.c -@@ -773,8 +773,10 @@ static int ov01a1s_set_format(struct v4l2_subdev *sd, - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) - *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; --#else -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) - *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; -+#else -+ *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; - #endif - } else { - ov01a1s->cur_mode = mode; -@@ -812,9 +814,11 @@ static int ov01a1s_get_format(struct v4l2_subdev *sd, - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) - fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, cfg, - fmt->pad); --#else -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) - fmt->format = *v4l2_subdev_get_try_format(&ov01a1s->sd, - sd_state, fmt->pad); -+#else -+ fmt->format = *v4l2_subdev_state_get_format(sd_state, fmt->pad); - #endif - else - ov01a1s_update_pad_format(ov01a1s->cur_mode, &fmt->format); -@@ -870,9 +874,12 @@ static int ov01a1s_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) - #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) - ov01a1s_update_pad_format(&supported_modes[0], - v4l2_subdev_get_try_format(sd, fh->pad, 0)); --#else -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0) - ov01a1s_update_pad_format(&supported_modes[0], - v4l2_subdev_get_try_format(sd, fh->state, 0)); -+#else -+ ov01a1s_update_pad_format(&supported_modes[0], -+ v4l2_subdev_state_get_format(fh->state, 0)); - #endif - mutex_unlock(&ov01a1s->mutex); - --- -2.45.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/.skip-tree b/users/flokli/ipu6-softisp/libcamera/.skip-tree deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/.skip-tree +++ /dev/null diff --git a/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch b/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch deleted file mode 100644 index 5340901edb94..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0001-libcamera-Add-support-for-IGIG_GBGR_IGIG_GRGB-bayer-.patch +++ /dev/null @@ -1,243 +0,0 @@ -From 0e94883c2f4f6164d40d4ea355449ba0864dc4f9 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 19 Dec 2023 11:16:26 +0100 -Subject: [PATCH 1/3] libcamera: Add support for IGIG_GBGR_IGIG_GRGB bayer - order DNU - -The ov01a1s sensor has the following bayer pattern (4x4 tile repeating): - -IGIG -GBGR -IGIG -GRGB - -Add support for this PixelFormat to libcamera. - -Do Not Upstream, first the include/linux/media-bus-format.h and -include/linux/videodev2.h changes need to land in the upstream kernel. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - include/libcamera/internal/bayer_format.h | 3 ++- - include/linux/drm_fourcc.h | 2 ++ - include/linux/media-bus-format.h | 4 +++- - include/linux/videodev2.h | 3 +++ - src/libcamera/bayer_format.cpp | 5 +++++ - src/libcamera/formats.cpp | 20 ++++++++++++++++++++ - src/libcamera/formats.yaml | 5 +++++ - src/libcamera/sensor/camera_sensor.cpp | 3 +++ - src/libcamera/v4l2_pixelformat.cpp | 4 ++++ - src/libcamera/v4l2_subdevice.cpp | 7 +++++++ - 10 files changed, 54 insertions(+), 2 deletions(-) - -diff --git a/include/libcamera/internal/bayer_format.h b/include/libcamera/internal/bayer_format.h -index 5c14bb5f..49b7f417 100644 ---- a/include/libcamera/internal/bayer_format.h -+++ b/include/libcamera/internal/bayer_format.h -@@ -27,7 +27,8 @@ public: - GBRG = 1, - GRBG = 2, - RGGB = 3, -- MONO = 4 -+ MONO = 4, -+ IGIG_GBGR_IGIG_GRGB = 5, - }; - - enum class Packing : uint16_t { -diff --git a/include/linux/drm_fourcc.h b/include/linux/drm_fourcc.h -index b4e1a092..070696bc 100644 ---- a/include/linux/drm_fourcc.h -+++ b/include/linux/drm_fourcc.h -@@ -447,6 +447,8 @@ extern "C" { - #define DRM_FORMAT_SGRBG10 fourcc_code('B', 'A', '1', '0') - #define DRM_FORMAT_SGBRG10 fourcc_code('G', 'B', '1', '0') - #define DRM_FORMAT_SBGGR10 fourcc_code('B', 'G', '1', '0') -+/* Mixed 10 bit bayer + ir pixel pattern found on Omnivision ov01a1s */ -+#define DRM_FORMAT_SIGIG_GBGR_IGIG_GRGB10 fourcc_code('O', 'V', '1', 'S') - - /* 12-bit Bayer formats */ - #define DRM_FORMAT_SRGGB12 fourcc_code('R', 'G', '1', '2') -diff --git a/include/linux/media-bus-format.h b/include/linux/media-bus-format.h -index f05f747e..1b4a65db 100644 ---- a/include/linux/media-bus-format.h -+++ b/include/linux/media-bus-format.h -@@ -121,7 +121,7 @@ - #define MEDIA_BUS_FMT_YUV16_1X48 0x202a - #define MEDIA_BUS_FMT_UYYVYY16_0_5X48 0x202b - --/* Bayer - next is 0x3021 */ -+/* Bayer - next is 0x3022 */ - #define MEDIA_BUS_FMT_SBGGR8_1X8 0x3001 - #define MEDIA_BUS_FMT_SGBRG8_1X8 0x3013 - #define MEDIA_BUS_FMT_SGRBG8_1X8 0x3002 -@@ -154,6 +154,8 @@ - #define MEDIA_BUS_FMT_SGBRG16_1X16 0x301e - #define MEDIA_BUS_FMT_SGRBG16_1X16 0x301f - #define MEDIA_BUS_FMT_SRGGB16_1X16 0x3020 -+/* Mixed bayer + ir pixel pattern found on ov01a1s */ -+#define MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10 0x3021 - - /* JPEG compressed formats - next is 0x4002 */ - #define MEDIA_BUS_FMT_JPEG_1X8 0x4001 -diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h -index 0b5482a0..a51d6755 100644 ---- a/include/linux/videodev2.h -+++ b/include/linux/videodev2.h -@@ -704,6 +704,9 @@ struct v4l2_pix_format { - #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16 GBGB.. RGRG.. */ - #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16 GRGR.. BGBG.. */ - #define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16 RGRG.. GBGB.. */ -+ /* 10bit mixed bayer + ir pixel pattern found on ov01a1s */ -+#define V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10 v4l2_fourcc('O', 'V', '1', 'S') /* unpacked */ -+#define V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10P v4l2_fourcc('O', 'V', '1', 'P') /* packed */ - - /* HSV formats */ - #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3') -diff --git a/src/libcamera/bayer_format.cpp b/src/libcamera/bayer_format.cpp -index 014f716d..325887a2 100644 ---- a/src/libcamera/bayer_format.cpp -+++ b/src/libcamera/bayer_format.cpp -@@ -112,6 +112,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{ - { formats::SGRBG10, V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10) } }, - { { BayerFormat::RGGB, 10, BayerFormat::Packing::None }, - { formats::SRGGB10, V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10) } }, -+ { { BayerFormat::IGIG_GBGR_IGIG_GRGB, 10, BayerFormat::Packing::None }, -+ { formats::SIGIG_GBGR_IGIG_GRGB10, V4L2PixelFormat(V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10) } }, - { { BayerFormat::BGGR, 10, BayerFormat::Packing::CSI2 }, - { formats::SBGGR10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P) } }, - { { BayerFormat::GBRG, 10, BayerFormat::Packing::CSI2 }, -@@ -120,6 +122,8 @@ const std::map<BayerFormat, Formats, BayerFormatComparator> bayerToFormat{ - { formats::SGRBG10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SGRBG10P) } }, - { { BayerFormat::RGGB, 10, BayerFormat::Packing::CSI2 }, - { formats::SRGGB10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P) } }, -+ { { BayerFormat::IGIG_GBGR_IGIG_GRGB, 10, BayerFormat::Packing::CSI2 }, -+ { formats::SIGIG_GBGR_IGIG_GRGB10_CSI2P, V4L2PixelFormat(V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10P) } }, - { { BayerFormat::BGGR, 10, BayerFormat::Packing::IPU3 }, - { formats::SBGGR10_IPU3, V4L2PixelFormat(V4L2_PIX_FMT_IPU3_SBGGR10) } }, - { { BayerFormat::GBRG, 10, BayerFormat::Packing::IPU3 }, -@@ -211,6 +215,7 @@ const std::unordered_map<unsigned int, BayerFormat> mbusCodeToBayer{ - { MEDIA_BUS_FMT_SGBRG10_1X10, { BayerFormat::GBRG, 10, BayerFormat::Packing::None } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, { BayerFormat::GRBG, 10, BayerFormat::Packing::None } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, { BayerFormat::RGGB, 10, BayerFormat::Packing::None } }, -+ { MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, { BayerFormat::IGIG_GBGR_IGIG_GRGB, 10, BayerFormat::Packing::None } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, { BayerFormat::BGGR, 12, BayerFormat::Packing::None } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, { BayerFormat::GBRG, 12, BayerFormat::Packing::None } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, { BayerFormat::GRBG, 12, BayerFormat::Packing::None } }, -diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp -index cf41f2c2..13ac3253 100644 ---- a/src/libcamera/formats.cpp -+++ b/src/libcamera/formats.cpp -@@ -639,6 +639,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ - .pixelsPerGroup = 2, - .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, - } }, -+ { formats::SIGIG_GBGR_IGIG_GRGB10, { -+ .name = "SIGIG_GBGR_IGIG_GRGB10", -+ .format = formats::SIGIG_GBGR_IGIG_GRGB10, -+ .v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10), }, -+ .bitsPerPixel = 10, -+ .colourEncoding = PixelFormatInfo::ColourEncodingRAW, -+ .packed = false, -+ .pixelsPerGroup = 4, -+ .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, -+ } }, - { formats::SBGGR10_CSI2P, { - .name = "SBGGR10_CSI2P", - .format = formats::SBGGR10_CSI2P, -@@ -679,6 +689,16 @@ const std::map<PixelFormat, PixelFormatInfo> pixelFormatInfo{ - .pixelsPerGroup = 4, - .planes = {{ { 5, 1 }, { 0, 0 }, { 0, 0 } }}, - } }, -+ { formats::SIGIG_GBGR_IGIG_GRGB10_CSI2P, { -+ .name = "SIGIG_GBGR_IGIG_GRGB10_CSI2P", -+ .format = formats::SIGIG_GBGR_IGIG_GRGB10_CSI2P, -+ .v4l2Formats = { V4L2PixelFormat(V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10P), }, -+ .bitsPerPixel = 10, -+ .colourEncoding = PixelFormatInfo::ColourEncodingRAW, -+ .packed = true, -+ .pixelsPerGroup = 4, -+ .planes = {{ { 4, 1 }, { 0, 0 }, { 0, 0 } }}, -+ } }, - { formats::SBGGR12, { - .name = "SBGGR12", - .format = formats::SBGGR12, -diff --git a/src/libcamera/formats.yaml b/src/libcamera/formats.yaml -index fe027a7c..394f980c 100644 ---- a/src/libcamera/formats.yaml -+++ b/src/libcamera/formats.yaml -@@ -107,6 +107,8 @@ formats: - fourcc: DRM_FORMAT_SGBRG10 - - SBGGR10: - fourcc: DRM_FORMAT_SBGGR10 -+ - SIGIG_GBGR_IGIG_GRGB10: -+ fourcc: DRM_FORMAT_SIGIG_GBGR_IGIG_GRGB10 - - - SRGGB12: - fourcc: DRM_FORMAT_SRGGB12 -@@ -151,6 +153,9 @@ formats: - - SBGGR10_CSI2P: - fourcc: DRM_FORMAT_SBGGR10 - mod: MIPI_FORMAT_MOD_CSI2_PACKED -+ - SIGIG_GBGR_IGIG_GRGB10_CSI2P: -+ fourcc: DRM_FORMAT_SIGIG_GBGR_IGIG_GRGB10 -+ mod: MIPI_FORMAT_MOD_CSI2_PACKED - - - SRGGB12_CSI2P: - fourcc: DRM_FORMAT_SRGGB12 -diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp -index c6d7f801..77c396b9 100644 ---- a/src/libcamera/sensor/camera_sensor.cpp -+++ b/src/libcamera/sensor/camera_sensor.cpp -@@ -526,6 +526,9 @@ int CameraSensor::initProperties() - case BayerFormat::MONO: - cfa = properties::draft::MONO; - break; -+ case BayerFormat::IGIG_GBGR_IGIG_GRGB: -+ cfa = properties::draft::RGB; -+ break; - } - - properties_.set(properties::draft::ColorFilterArrangement, cfa); -diff --git a/src/libcamera/v4l2_pixelformat.cpp b/src/libcamera/v4l2_pixelformat.cpp -index 70568335..a2fbd644 100644 ---- a/src/libcamera/v4l2_pixelformat.cpp -+++ b/src/libcamera/v4l2_pixelformat.cpp -@@ -159,6 +159,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{ - { formats::SGRBG10, "10-bit Bayer GRGR/BGBG" } }, - { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10), - { formats::SRGGB10, "10-bit Bayer RGRG/GBGB" } }, -+ { V4L2PixelFormat(V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10), -+ { formats::SIGIG_GBGR_IGIG_GRGB10, "10-bit Bayer GRGB/IGIG/GBGR/IGIG" } }, - { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR10P), - { formats::SBGGR10_CSI2P, "10-bit Bayer BGBG/GRGR Packed" } }, - { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG10P), -@@ -167,6 +169,8 @@ const std::map<V4L2PixelFormat, V4L2PixelFormat::Info> vpf2pf{ - { formats::SGRBG10_CSI2P, "10-bit Bayer GRGR/BGBG Packed" } }, - { V4L2PixelFormat(V4L2_PIX_FMT_SRGGB10P), - { formats::SRGGB10_CSI2P, "10-bit Bayer RGRG/GBGB Packed" } }, -+ { V4L2PixelFormat(V4L2_PIX_FMT_SIGIG_GBGR_IGIG_GRGB10P), -+ { formats::SIGIG_GBGR_IGIG_GRGB10_CSI2P, "10-bit Bayer GRGB/IGIG/GBGR/IGIG Packed" } }, - { V4L2PixelFormat(V4L2_PIX_FMT_SBGGR12), - { formats::SBGGR12, "12-bit Bayer BGBG/GRGR" } }, - { V4L2PixelFormat(V4L2_PIX_FMT_SGBRG12), -diff --git a/src/libcamera/v4l2_subdevice.cpp b/src/libcamera/v4l2_subdevice.cpp -index 6da77775..0ba8c0de 100644 ---- a/src/libcamera/v4l2_subdevice.cpp -+++ b/src/libcamera/v4l2_subdevice.cpp -@@ -595,6 +595,13 @@ const std::map<uint32_t, MediaBusFormatInfo> mediaBusFormatInfo{ - .bitsPerPixel = 10, - .colourEncoding = PixelFormatInfo::ColourEncodingRAW, - } }, -+ { MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, { -+ .name = "SIGIG_GBGR_IGIG_GRGB10_1X10", -+ .code = MEDIA_BUS_FMT_SIGIG_GBGR_IGIG_GRGB10_1X10, -+ .type = MediaBusFormatInfo::Type::Image, -+ .bitsPerPixel = 10, -+ .colourEncoding = PixelFormatInfo::ColourEncodingRAW, -+ } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, { - .name = "SBGGR12_1X12", - .code = MEDIA_BUS_FMT_SBGGR12_1X12, --- -2.45.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch b/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch deleted file mode 100644 index 61316d10427f..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0002-ov01a1s-HACK.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 5895f4ed8163780446665b99b8d5dc31d6f2b791 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Tue, 19 Dec 2023 15:45:51 +0100 -Subject: [PATCH 2/3] ov01a1s HACK - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/sensor/camera_sensor.cpp | 6 ++++++ - src/libcamera/software_isp/debayer_cpu.cpp | 7 +++++++ - src/libcamera/software_isp/swstats_cpu.cpp | 4 ++++ - 3 files changed, 17 insertions(+) - -diff --git a/src/libcamera/sensor/camera_sensor.cpp b/src/libcamera/sensor/camera_sensor.cpp -index 77c396b9..628b12f4 100644 ---- a/src/libcamera/sensor/camera_sensor.cpp -+++ b/src/libcamera/sensor/camera_sensor.cpp -@@ -33,6 +33,9 @@ - */ - - namespace libcamera { -+ -+// HACK HACK -+bool is_ov01a1s = false; - - LOG_DEFINE_CATEGORY(CameraSensor) - -@@ -442,6 +445,9 @@ int CameraSensor::initProperties() - model_ = subdev_->model(); - properties_.set(properties::Model, utils::toAscii(model_)); - -+ if (model_ == "ov01a1s") -+ is_ov01a1s = true; -+ - /* Generate a unique ID for the sensor. */ - int ret = generateId(); - if (ret) -diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index 8254bbe9..10ea29b1 100644 ---- a/src/libcamera/software_isp/debayer_cpu.cpp -+++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -23,6 +23,7 @@ - - namespace libcamera { - -+extern bool is_ov01a1s; - /** - * \class DebayerCpu - * \brief Class for debayering on the CPU -@@ -275,6 +276,9 @@ int DebayerCpu::getInputConfig(PixelFormat inputFormat, DebayerInputConfig &conf - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputFormat); - -+ if (is_ov01a1s) -+ bayerFormat.order = BayerFormat::IGIG_GBGR_IGIG_GRGB; -+ - if ((bayerFormat.bitDepth == 8 || bayerFormat.bitDepth == 10 || bayerFormat.bitDepth == 12) && - bayerFormat.packing == BayerFormat::Packing::None && - isStandardBayerOrder(bayerFormat.order)) { -@@ -343,6 +347,9 @@ int DebayerCpu::setDebayerFunctions(PixelFormat inputFormat, PixelFormat outputF - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputFormat); - -+ if (is_ov01a1s) -+ bayerFormat.order = BayerFormat::IGIG_GBGR_IGIG_GRGB; -+ - xShift_ = 0; - swapRedBlueGains_ = false; - -diff --git a/src/libcamera/software_isp/swstats_cpu.cpp b/src/libcamera/software_isp/swstats_cpu.cpp -index 815c4d4f..0b310f80 100644 ---- a/src/libcamera/software_isp/swstats_cpu.cpp -+++ b/src/libcamera/software_isp/swstats_cpu.cpp -@@ -19,6 +19,7 @@ - - namespace libcamera { - -+extern bool is_ov01a1s; - /** - * \class SwStatsCpu - * \brief Class for gathering statistics on the CPU -@@ -367,6 +368,9 @@ int SwStatsCpu::configure(const StreamConfiguration &inputCfg) - BayerFormat bayerFormat = - BayerFormat::fromPixelFormat(inputCfg.pixelFormat); - -+ if (is_ov01a1s) -+ bayerFormat.order = BayerFormat::IGIG_GBGR_IGIG_GRGB; -+ - if (bayerFormat.packing == BayerFormat::Packing::None && - setupStandardBayerOrder(bayerFormat.order) == 0) { - switch (bayerFormat.bitDepth) { --- -2.45.2 - diff --git a/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch b/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch deleted file mode 100644 index f250617bd3ad..000000000000 --- a/users/flokli/ipu6-softisp/libcamera/0003-libcamera-debayer_cpu-Make-the-minimum-size-1280x720.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 06add438e4fc53faca6e016bd582df0e7ac5a271 Mon Sep 17 00:00:00 2001 -From: Hans de Goede <hdegoede@redhat.com> -Date: Wed, 24 Jan 2024 20:44:29 +0100 -Subject: [PATCH 3/3] libcamera: debayer_cpu: Make the minimum size 1280x720 - -pipewire + firefox default to what looks like 640x480 if we export -the entire supported cropping range. Hardcode 720p as minsize for now. - -Signed-off-by: Hans de Goede <hdegoede@redhat.com> ---- - src/libcamera/software_isp/debayer_cpu.cpp | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp -index 10ea29b1..a354138b 100644 ---- a/src/libcamera/software_isp/debayer_cpu.cpp -+++ b/src/libcamera/software_isp/debayer_cpu.cpp -@@ -805,10 +805,17 @@ SizeRange DebayerCpu::sizes(PixelFormat inputFormat, const Size &inputSize) - return {}; - } - -- return SizeRange(Size(patternSize.width, patternSize.height), -- Size((inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1), -- (inputSize.height - 2 * borderHeight) & ~(patternSize.height - 1)), -- patternSize.width, patternSize.height); -+ /* -+ * pipewire + firefox default to what looks like 640x480 -+ * if we export the entire supported cropping range. -+ * Hardcode 720p as minsize for now. Minsize should be -+ * Size(patternSize.width, patternSize.height) -+ */ -+ unsigned int w = (inputSize.width - 2 * patternSize.width) & ~(patternSize.width - 1); -+ unsigned int h = (inputSize.height - 2 * patternSize.height) & ~(patternSize.height - 1); -+ return SizeRange(Size(std::min(w, 1280u), std::min(h, 720u)), -+ Size(w, h), -+ patternSize.width, patternSize.height); - } - - } /* namespace libcamera */ --- -2.45.2 - |