From db143a8f30e0fd80b87b37e1b50567ee22422ba5 Mon Sep 17 00:00:00 2001 From: linya14x Date: Sat, 1 Nov 2025 18:03:04 +0800 Subject: [PATCH] PTL V6.17 with staging isys Signed-off-by: linya14x linx.yang@intel.com --- Makefile | 8 +- dkms.conf | 14 +- drivers/media/pci/intel/ipu7/ipu7-isys.c | 8 +- drivers/media/pci/intel/ipu7/ipu7.c | 4 +- drivers/media/platform/intel/Kconfig | 3 +- drivers/media/platform/intel/Makefile | 13 +- .../media/platform/intel/ipu-acpi-common.c | 10 +- drivers/media/platform/intel/ipu-acpi-pdata.c | 615 +++++++++++++- drivers/media/platform/intel/ipu-acpi.c | 119 ++- include/media/ipu-acpi-pdata.h | 38 +- include/media/ipu-acpi.h | 78 +- include/media/ipu-get-acpi.h | 30 + ...001-staging-add-ipu7-isys-reset-code.patch | 803 ++++++++++++++++++ ...2-staging-add-enable-CONFIG_DEBUG_FS.patch | 270 ++++++ ...ing-add-enable-CONFIG_INTEL_IPU_ACPI.patch | 404 +++++++++ ...d-patch-for-use-DPHY-as-the-default-.patch | 32 + ...d-patch-for-increase-fw-msg-bufs-ini.patch | 29 + ...d-fixup-some-PCI-probe-and-release-i.patch | 98 +++ ...-add-pacth-for-ipu7-Kconfig-Makefile.patch | 79 ++ ...ging-add-Update-firmware-ABI-version.patch | 145 ++++ .../0009-INT3472-Support-LT6911GXD.patch | 58 ++ ...-media-i2c-add-support-for-lt6911gxd.patch | 45 + ...a-pci-enable-lt6911gxd-in-ipu-bridge.patch | 26 + .../0012-ipu-bridge-add-CPHY-support.patch | 109 +++ ...nc-at-buffer_prepare-callback-as-DMA.patch | 42 + ...max9x-add-config-in-makefile-kconfig.patch | 55 ++ ...t-v4l2_subdev_enable_streams_api-tru.patch | 27 + 27 files changed, 3032 insertions(+), 130 deletions(-) create mode 100644 include/media/ipu-get-acpi.h create mode 100644 patch/v6.17_staging/0001-staging-add-ipu7-isys-reset-code.patch create mode 100644 patch/v6.17_staging/0002-staging-add-enable-CONFIG_DEBUG_FS.patch create mode 100644 patch/v6.17_staging/0003-staging-add-enable-CONFIG_INTEL_IPU_ACPI.patch create mode 100644 patch/v6.17_staging/0004-staging-add-patch-for-use-DPHY-as-the-default-.patch create mode 100644 patch/v6.17_staging/0005-staging-add-patch-for-increase-fw-msg-bufs-ini.patch create mode 100644 patch/v6.17_staging/0006-staging-add-fixup-some-PCI-probe-and-release-i.patch create mode 100644 patch/v6.17_staging/0007-staging-add-pacth-for-ipu7-Kconfig-Makefile.patch create mode 100644 patch/v6.17_staging/0008-staging-add-Update-firmware-ABI-version.patch create mode 100644 patch/v6.17_staging/0009-INT3472-Support-LT6911GXD.patch create mode 100644 patch/v6.17_staging/0010-media-i2c-add-support-for-lt6911gxd.patch create mode 100644 patch/v6.17_staging/0011-media-pci-enable-lt6911gxd-in-ipu-bridge.patch create mode 100644 patch/v6.17_staging/0012-ipu-bridge-add-CPHY-support.patch create mode 100644 patch/v6.17_staging/0013-media-ipu-Dma-sync-at-buffer_prepare-callback-as-DMA.patch create mode 100644 patch/v6.17_staging/0014-max9x-add-config-in-makefile-kconfig.patch create mode 100644 patch/v6.17_staging/0015-drivers-media-set-v4l2_subdev_enable_streams_api-tru.patch diff --git a/Makefile b/Makefile index deb1761..3ee25b1 100644 --- a/Makefile +++ b/Makefile @@ -8,16 +8,16 @@ MODSRC := $(shell pwd) export EXTERNAL_BUILD = 1 export CONFIG_VIDEO_INTEL_IPU7 = m export CONFIG_IPU_BRIDGE = y -export CONFIG_INTEL_IPU7_ACPI = m +export CONFIG_INTEL_IPU_ACPI = m -obj-y += drivers/media/pci/intel/ipu7/ +obj-y += drivers/media/pci/intel/ipu7/psys/ obj-y += drivers/media/platform/intel/ subdir-ccflags-y += -I$(src)/include subdir-ccflags-$(CONFIG_IPU_BRIDGE) += \ -DCONFIG_IPU_BRIDGE -subdir-ccflags-$(CONFIG_INTEL_IPU7_ACPI) += \ - -DCONFIG_INTEL_IPU7_ACPI +subdir-ccflags-$(CONFIG_INTEL_IPU_ACPI) += \ + -DCONFIG_INTEL_IPU_ACPI subdir-ccflags-y += $(subdir-ccflags-m) all: diff --git a/dkms.conf b/dkms.conf index e871f5f..b436c3c 100644 --- a/dkms.conf +++ b/dkms.conf @@ -6,14 +6,10 @@ CLEAN="make KERNELRELEASE=$kernelver KERNEL_SRC=$kernel_source_dir clean" AUTOINSTALL="yes" BUILD_EXCLUSIVE_CONFIG="CONFIG_VIDEO_V4L2_I2C" -BUILT_MODULE_NAME[0]="intel-ipu7" -BUILT_MODULE_LOCATION[0]="drivers/media/pci/intel/ipu7" +BUILT_MODULE_NAME[0]="intel-ipu7-psys" +BUILT_MODULE_LOCATION[0]="drivers/media/pci/intel/ipu7/psys" DEST_MODULE_LOCATION[0]="/updates" -BUILT_MODULE_NAME[1]="intel-ipu7-isys" -BUILT_MODULE_LOCATION[1]="drivers/media/pci/intel/ipu7" -DEST_MODULE_LOCATION[1]="/updates" - -BUILT_MODULE_NAME[2]="intel-ipu7-psys" -BUILT_MODULE_LOCATION[2]="drivers/media/pci/intel/ipu7/psys" -DEST_MODULE_LOCATION[2]="/updates" \ No newline at end of file +BUILT_MODULE_NAME[1]="intel-ipu-acpi" +BUILT_MODULE_LOCATION[1]="drivers/media/platform/intel" +DEST_MODULE_LOCATION[1]="/updates" \ No newline at end of file diff --git a/drivers/media/pci/intel/ipu7/ipu7-isys.c b/drivers/media/pci/intel/ipu7/ipu7-isys.c index 2b3b49d..00edeeb 100644 --- a/drivers/media/pci/intel/ipu7/ipu7-isys.c +++ b/drivers/media/pci/intel/ipu7/ipu7-isys.c @@ -175,7 +175,7 @@ static int isys_register_ext_subdev(struct ipu7_isys *isys, client = isys_find_i2c_subdev(adapter, sd_info); if (client) { dev_warn(dev, "Device exists\n"); -#if IS_ENABLED(CONFIG_INTEL_IPU7_ACPI) +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) /* TODO: remove i2c_unregister_device() */ i2c_unregister_device(client); #else @@ -263,7 +263,7 @@ static int isys_fw_log_init(struct ipu7_isys *isys) return 0; } -#if IS_ENABLED(CONFIG_INTEL_IPU7_ACPI) +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) /* The .bound() notifier callback when a match is found */ static int isys_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, @@ -497,7 +497,7 @@ static int isys_csi2_create_media_links(struct ipu7_isys *isys) return 0; } -#if IS_ENABLED(CONFIG_INTEL_IPU7_ACPI) +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) static int isys_register_devices(struct ipu7_isys *isys) { struct device *dev = &isys->adev->auxdev.dev; @@ -771,7 +771,7 @@ static const struct dev_pm_ops isys_pm_ops = { .resume = isys_resume, }; -#if IS_ENABLED(CONFIG_INTEL_IPU7_ACPI) +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) static void isys_remove(struct auxiliary_device *auxdev) { struct ipu7_isys *isys = dev_get_drvdata(&auxdev->dev); diff --git a/drivers/media/pci/intel/ipu7/ipu7.c b/drivers/media/pci/intel/ipu7/ipu7.c index 69fe220..f52d274 100644 --- a/drivers/media/pci/intel/ipu7/ipu7.c +++ b/drivers/media/pci/intel/ipu7/ipu7.c @@ -40,7 +40,7 @@ #include "ipu7-mmu.h" #include "ipu7-platform-regs.h" -#if IS_ENABLED(CONFIG_INTEL_IPU7_ACPI) +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) #include #endif @@ -2613,7 +2613,7 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_ipu_bus_del_devices; } -#if IS_ENABLED(CONFIG_INTEL_IPU7_ACPI) +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) ipu_get_acpi_devices(&dev->platform_data); #endif isp->isys = ipu7_isys_init(pdev, dev, isys_ctrl, isys_base, diff --git a/drivers/media/platform/intel/Kconfig b/drivers/media/platform/intel/Kconfig index f8affa6..4ec9c70 100644 --- a/drivers/media/platform/intel/Kconfig +++ b/drivers/media/platform/intel/Kconfig @@ -8,9 +8,8 @@ config INTEL_IPU7_FPGA_PDATA development and mainly used for pixter or sensor enablement without ACPI support. -config INTEL_IPU7_ACPI +config INTEL_IPU_ACPI tristate "Enable IPU ACPI driver" - default VIDEO_INTEL_IPU7 depends on I2C depends on ACPI help diff --git a/drivers/media/platform/intel/Makefile b/drivers/media/platform/intel/Makefile index d0c41b7..129beee 100644 --- a/drivers/media/platform/intel/Makefile +++ b/drivers/media/platform/intel/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Copyright (c) 2010 - 2022 Intel Corporation. +# Copyright (c) 2010 - 2025 Intel Corporation. is_kernel_lt_6_10 = $(shell if [ $$(printf "6.10\n$(KERNELVERSION)" | sort -V | head -n1) != "6.10" ]; then echo 1; fi) ifeq ($(is_kernel_lt_6_10), 1) @@ -8,12 +8,13 @@ src := $(srctree)/$(src) endif endif -ccflags-y += -I$(src)/../../pci/intel/ipu7/ +ccflags-y += -I$(src)/../../../staging/media/ipu7/ -ifneq ($(filter y m, $(CONFIG_INTEL_IPU7_ACPI)),) -obj-$(CONFIG_INTEL_IPU7_ACPI) += ipu-acpi.o \ - ipu-acpi-pdata.o \ - ipu-acpi-common.o +ifneq ($(filter y m, $(CONFIG_INTEL_IPU_ACPI)),) +obj-$(CONFIG_INTEL_IPU_ACPI) += intel-ipu-acpi.o +intel-ipu-acpi-y += ipu-acpi.o \ + ipu-acpi-pdata.o \ + ipu-acpi-common.o else obj-y += ipu7-fpga-pdata.o endif diff --git a/drivers/media/platform/intel/ipu-acpi-common.c b/drivers/media/platform/intel/ipu-acpi-common.c index 936c158..4c5507b 100644 --- a/drivers/media/platform/intel/ipu-acpi-common.c +++ b/drivers/media/platform/intel/ipu-acpi-common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2016-2024 Intel Corporation. + * Copyright (c) 2016-2025 Intel Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -13,7 +13,9 @@ * */ #include -#include +#include +#include + #include #include @@ -365,8 +367,12 @@ int ipu_acpi_get_dep_data(struct device *dev, continue; /* Process device IN3472 created by acpi */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0) + if (acpi_bus_get_device(dep_devices.handles[i], &device)) { +#else device = acpi_fetch_acpi_dev(dep_devices.handles[i]); if (!device) { +#endif pr_err("IPU ACPI: Failed to get ACPI device"); return -ENODEV; } diff --git a/drivers/media/platform/intel/ipu-acpi-pdata.c b/drivers/media/platform/intel/ipu-acpi-pdata.c index 0a84dcc..65b759a 100644 --- a/drivers/media/platform/intel/ipu-acpi-pdata.c +++ b/drivers/media/platform/intel/ipu-acpi-pdata.c @@ -12,18 +12,32 @@ * GNU General Public License for more details. * */ - #include #include #define MIN_SENSOR_I2C 1 #define MIN_SERDES_I2C 3 +#define SENSOR_2X_I2C 5 #define SUFFIX_BASE 97 +#define MSG_LEN 128 -struct ipu7_isys_subdev_pdata acpi_subdev_pdata = { - .subdevs = (struct ipu7_isys_subdev_info *[]) { - NULL, - } +static struct ipu_isys_subdev_pdata *ptr_built_in_pdata; + +void set_built_in_pdata(struct ipu_isys_subdev_pdata *pdata) +{ + ptr_built_in_pdata = pdata; +}; +EXPORT_SYMBOL(set_built_in_pdata); + +static struct ipu_isys_clk_mapping clk_mapping[] = { + { CLKDEV_INIT(NULL, NULL, NULL), NULL } +}; + +struct ipu_isys_subdev_pdata acpi_subdev_pdata = { + .subdevs = (struct ipu_isys_subdev_info *[]) { + NULL, NULL, NULL, NULL, NULL, + }, + .clk_map = clk_mapping, }; struct serdes_local serdes_info; @@ -74,7 +88,8 @@ static int get_i2c_bus_id(int adapter_id, char *adapter_bdf, int bdf_len) */ static void update_i2c_bus_id(void) { - struct ipu7_isys_subdev_info **subdevs = acpi_subdev_pdata.subdevs; + struct ipu_isys_subdev_info **subdevs = acpi_subdev_pdata.subdevs; + for (int i = 0; subdevs[i] != NULL; i++) { subdevs[i]->i2c.i2c_adapter_id = get_i2c_bus_id(subdevs[i]->i2c.i2c_adapter_id, @@ -83,9 +98,9 @@ static void update_i2c_bus_id(void) } } -struct ipu7_isys_subdev_pdata *get_acpi_subdev_pdata(void) +struct ipu_isys_subdev_pdata *get_acpi_subdev_pdata(void) { - struct ipu7_isys_subdev_pdata *ptr; + struct ipu_isys_subdev_pdata *ptr; update_i2c_bus_id(); ptr = &acpi_subdev_pdata; @@ -122,7 +137,7 @@ static void print_serdes_sdinfo(struct serdes_subdev_info *sdinfo) (int)sd_mpdata->gpio_powerup_seq[i]); } -static void print_serdes_subdev(struct ipu7_isys_subdev_info *sd) +static void print_serdes_subdev(struct ipu_isys_subdev_info *sd) { struct serdes_platform_data *sd_pdata = sd->i2c.board_info.platform_data; int i; @@ -153,6 +168,7 @@ static void print_serdes_subdev(struct ipu7_isys_subdev_info *sd) pr_debug("\t\tlink_freq_mbps \t\t= %d", sd_pdata->link_freq_mbps); pr_debug("\t\tdeser_nlanes \t\t= %d", sd_pdata->deser_nlanes); pr_debug("\t\tser_nlanes \t\t= %d", sd_pdata->ser_nlanes); + pr_debug("\t\tser_name \t\t= %s", sd_pdata->ser_name); for (i = 0; i < serdes_info.rx_port; i++) { sd_sdinfo = &sd_pdata->subdev_info[i]; @@ -167,7 +183,7 @@ static void print_serdes_subdev(struct ipu7_isys_subdev_info *sd) } -static void print_subdev(struct ipu7_isys_subdev_info *sd) +static void print_subdev(struct ipu_isys_subdev_info *sd) { struct sensor_platform_data *spdata = sd->i2c.board_info.platform_data; int i; @@ -198,10 +214,380 @@ static void print_subdev(struct ipu7_isys_subdev_info *sd) pr_debug("\t\treset_pin \t\t= %d", spdata->reset_pin); pr_debug("\t\tdetect_pin \t\t= %d", spdata->detect_pin); - for (i = 0; i < IPU7_SPDATA_GPIO_NUM; i++) + for (i = 0; i < IPU_SPDATA_GPIO_NUM; i++) pr_debug("\t\tgpios[%d] \t\t= %d", i, spdata->gpios[i]); } +static void add_local_subdevs(struct ipu_isys_subdev_info *new_subdev_info) +{ + struct ipu_isys_subdev_pdata *ptr_acpi_subdev_pdata = &acpi_subdev_pdata; + int i = 0; + + while (i < MAX_ACPI_SENSOR_NUM) { + if (!ptr_acpi_subdev_pdata->subdevs[i]) { + ptr_acpi_subdev_pdata->subdevs[i] = new_subdev_info; + ptr_acpi_subdev_pdata->subdevs[i+1] = NULL; + break; + } + i++; + } +} + +static void update_short(struct device *dev, + char msg[MSG_LEN], + unsigned short *old_short, + unsigned int new_short) +{ + if (*old_short != new_short) { + dev_info(dev, "%s 0x%x -> 0x%x", msg, *old_short, new_short); + *old_short = new_short; + } +} + +static void update_hex(struct device *dev, + char msg[MSG_LEN], + unsigned int *old_hex, + unsigned int new_hex) +{ + if (*old_hex != new_hex) { + dev_info(dev, "%s 0x%x -> 0x%x", msg, *old_hex, new_hex); + *old_hex = new_hex; + } +} + +static void update_int(struct device *dev, + char msg[MSG_LEN], + unsigned int *old_int, + unsigned int new_int) +{ + if (*old_int != new_int) { + dev_info(dev, "%s %d -> %d", msg, *old_int, new_int); + *old_int = new_int; + } +} + +static void update_inta(struct device *dev, + char msg[MSG_LEN], + int old_int[MSG_LEN], + int new_int[MSG_LEN], + size_t size) +{ + int i; + + for (i = 0; i < size; i++) { + if (old_int[i] != new_int[i]) { + dev_info(dev, "%s %d -> %d", msg, old_int[i], new_int[i]); + old_int[i] = new_int[i]; + } + } +} + +static void update_str(struct device *dev, + char msg[MSG_LEN], + char old_str[MSG_LEN], + char new_str[MSG_LEN]) +{ + if (strcmp(old_str, new_str) != 0) { + dev_info(dev, "%s %s -> %s", msg, old_str, new_str); + strscpy(old_str, new_str, strlen(new_str)+1); + } +} + +static void update_subdev(struct device *dev, + struct ipu_isys_subdev_info *new_sd, + struct ipu_isys_subdev_info **old_sd) +{ + struct sensor_platform_data *old_pdata = + (*old_sd)->i2c.board_info.platform_data; + + struct sensor_platform_data *new_pdata = + new_sd->i2c.board_info.platform_data; + + /* csi2 */ + update_int(dev, "CSI2 port", &(*old_sd)->csi2->port, new_sd->csi2->port); + update_int(dev, "CSI2 nlanes", &(*old_sd)->csi2->nlanes, new_sd->csi2->nlanes); + + /* i2c */ + update_short(dev, "I2C board_info addr", &(*old_sd)->i2c.board_info.addr, + new_sd->i2c.board_info.addr); + update_str(dev, "I2C i2c_adapter_bdf", (*old_sd)->i2c.i2c_adapter_bdf, + new_sd->i2c.i2c_adapter_bdf); + + /* platform data */ + update_int(dev, "pdata port", &(old_pdata)->port, new_pdata->port); + update_int(dev, "pdata lanes", &(old_pdata)->lanes, new_pdata->lanes); + update_hex(dev, "pdata I2C slave addr", &(old_pdata)->i2c_slave_address, + new_pdata->i2c_slave_address); + update_int(dev, "pdata irq_pin", &(old_pdata)->irq_pin, new_pdata->irq_pin); + update_str(dev, "pdata irq_pin_name", old_pdata->irq_pin_name, new_pdata->irq_pin_name); + update_int(dev, "pdata reset_pin", &(old_pdata)->reset_pin, new_pdata->reset_pin); + update_int(dev, "pdata detect_pin", &(old_pdata)->detect_pin, new_pdata->detect_pin); + update_inta(dev, "pdata gpios", old_pdata->gpios, new_pdata->gpios, IPU_SPDATA_GPIO_NUM); +} + +static void update_serdes_subdev(struct device *dev, + struct ipu_isys_subdev_info *new_sd, + struct ipu_isys_subdev_info **old_sd) +{ + struct serdes_platform_data *old_pdata = + (*old_sd)->i2c.board_info.platform_data; + + struct serdes_platform_data *new_pdata = + new_sd->i2c.board_info.platform_data; + + int i; + struct serdes_subdev_info *old_sdinfo, *new_sdinfo; + struct serdes_module_pdata *old_mpdata, *new_mpdata; + + /* csi2 */ + update_int(dev, "CSI2 port", &(*old_sd)->csi2->port, new_sd->csi2->port); + update_int(dev, "CSI2 nlanes", &(*old_sd)->csi2->nlanes, new_sd->csi2->nlanes); + + /* i2c */ + update_short(dev, "I2C board_info addr", &(*old_sd)->i2c.board_info.addr, + new_sd->i2c.board_info.addr); + update_str(dev, "I2C i2c_adapter_bdf", (*old_sd)->i2c.i2c_adapter_bdf, + new_sd->i2c.i2c_adapter_bdf); + + update_int(dev, "I2C Pdata reset_gpio", &old_pdata->reset_gpio, + new_pdata->reset_gpio); + update_int(dev, "I2C Pdata FPD_gpio", &old_pdata->FPD_gpio, new_pdata->FPD_gpio); + + /* platform data */ + for (i = 0; i < SERDES_MAX_PORT; i++) { + old_sdinfo = &old_pdata->subdev_info[i]; + old_mpdata = old_sdinfo->board_info.platform_data; + + new_sdinfo = &new_pdata->subdev_info[i]; + new_mpdata = new_sdinfo->board_info.platform_data; + + if (!strcmp(old_sdinfo->board_info.type, new_sdinfo->board_info.type) && + old_sdinfo->suffix == new_sdinfo->suffix) { + update_short(dev, "SdInfo port", &old_sdinfo->rx_port, + new_sdinfo->rx_port); + update_short(dev, "SdInfo ser_alias", &old_sdinfo->ser_alias, + new_sdinfo->ser_alias); + update_short(dev, "SdInfo board_info.addr", &old_sdinfo->board_info.addr, + new_sdinfo->board_info.addr); + + if (!strcmp(old_mpdata->module_name, new_mpdata->module_name)) { + update_int(dev, "mPdata lanes", &old_mpdata->lanes, + new_mpdata->lanes); + update_int(dev, "mPdata fsin", &old_mpdata->fsin, + new_mpdata->fsin); + update_inta(dev, "mPdata gpio_powerup_seq", + (int *)old_mpdata->gpio_powerup_seq, + (int *)new_mpdata->gpio_powerup_seq, + SERDES_MAX_GPIO_POWERUP_SEQ); + } + } + } +} + +static int compare_subdev(struct device *dev, + struct ipu_isys_subdev_info *new_subdev, + struct ipu_isys_subdev_info *old_subdev, + enum connection_type connect) +{ + /* check for ACPI HID in existing pdata */ + if (old_subdev->acpi_hid) { + /* compare with HID for User Custom */ + if (!strcmp(old_subdev->acpi_hid, dev_name(dev))) { + dev_info(dev, "Found matching sensor : %s", dev_name(dev)); + return 0; + } + } + /* compare sensor type */ + if (!strcmp(old_subdev->i2c.board_info.type, + new_subdev->i2c.board_info.type)) { + + if (connect == TYPE_DIRECT) { + struct sensor_platform_data *old_pdata, *new_pdata; + + old_pdata = (struct sensor_platform_data *) + old_subdev->i2c.board_info.platform_data; + + new_pdata = (struct sensor_platform_data *) + new_subdev->i2c.board_info.platform_data; + + if (old_pdata->suffix == new_pdata->suffix) { + dev_info(dev, "Found matching sensor : %s %c", + old_subdev->i2c.board_info.type, + old_pdata->suffix); + return 0; + } + } else if (connect == TYPE_SERDES) { + struct serdes_platform_data *old_pdata, *new_pdata; + + old_pdata = (struct serdes_platform_data *) + old_subdev->i2c.board_info.platform_data; + + new_pdata = (struct serdes_platform_data *) + new_subdev->i2c.board_info.platform_data; + + if (old_pdata->suffix == new_pdata->suffix) { + dev_info(dev, "Found matching sensor : %s %c", + old_subdev->i2c.board_info.type, + old_pdata->suffix); + return 0; + } + } + } + return -1; +} + +static void update_pdata(struct device *dev, + struct ipu_isys_subdev_info *new_subdev, + enum connection_type connect) +{ + struct ipu_isys_subdev_info *acpi_subdev; + bool found = false; + + acpi_subdev = new_subdev; + + /* update local ipu_isys_subdev_pdata */ + add_local_subdevs(acpi_subdev); + + /* found existing pdata */ + if (ptr_built_in_pdata) { + struct ipu_isys_subdev_info **subdevs, *sd_info; + + for (subdevs = ptr_built_in_pdata->subdevs; *subdevs; subdevs++) { + sd_info = *subdevs; + + /* found similar subdev in existing pdata*/ + if (!compare_subdev(dev, acpi_subdev, sd_info, connect)) { + /* print and update old subdev */ + if (connect == TYPE_DIRECT) { + dev_dbg(dev, "Old sensor subdev\n"); + print_subdev(sd_info); + update_subdev(dev, acpi_subdev, &sd_info); + dev_dbg(dev, "Updated subdev\n"); + print_subdev(sd_info); + } else if (connect == TYPE_SERDES) { + dev_dbg(dev, "Old serdes subdev\n"); + print_serdes_subdev(sd_info); + update_serdes_subdev(dev, acpi_subdev, &sd_info); + dev_dbg(dev, "Updated subdev\n"); + print_serdes_subdev(sd_info); + } + + /* stop once similar subdev updated */ + found = true; + break; + } + } + + /* no similar subdev found */ + if (!found) { + if (connect == TYPE_DIRECT) { + struct sensor_platform_data *acpi_pdata; + + acpi_pdata = (struct sensor_platform_data *) + acpi_subdev->i2c.board_info.platform_data; + + dev_err(dev, "Pdata does not contain %s %c\n", + acpi_subdev->i2c.board_info.type, + acpi_pdata->suffix); + + /* print new subdev */ + print_subdev(acpi_subdev); + + } else { + struct serdes_platform_data *acpi_pdata; + + acpi_pdata = (struct serdes_platform_data *) + acpi_subdev->i2c.board_info.platform_data; + + dev_err(dev, "Pdata does not contain %s %c\n", + acpi_subdev->i2c.board_info.type, + acpi_pdata->suffix); + + print_serdes_subdev(acpi_subdev); + } + } + } + /* does not have existing pdata */ + else { + /* print new subdev */ + if (connect == TYPE_DIRECT) { + pr_debug("New sensor subdev\n"); + print_subdev(acpi_subdev); + } else { + pr_debug("New serdes subdev\n"); + print_serdes_subdev(acpi_subdev); + } + } + + /* update total num of sensor connected */ + if (connect == TYPE_SERDES) + serdes_info.deser_num++; +} + +#if IS_ENABLED(CONFIG_VIDEO_TI960) +static void set_ti960_gpio(struct control_logic_data *ctl_data, struct serdes_platform_data **pdata) +{ + int i; + + (*pdata)->reset_gpio = 0; + (*pdata)->FPD_gpio = -1; + + if (ctl_data->completed && ctl_data->gpio_num > 0) { + for (i = 0; i < ctl_data->gpio_num; i++) { + if (ctl_data->gpio[i].func != GPIO_RESET) + dev_err(ctl_data->dev, + "IPU ACPI: Invalid GPIO func: %d\n", + ctl_data->gpio[i].func); + + /* check for RESET selection in BIOS */ + if (ctl_data->gpio[i].valid && ctl_data->gpio[i].func == GPIO_RESET) + (*pdata)->FPD_gpio = ctl_data->gpio[i].pin; + } + } +} +#endif + +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) || IS_ENABLED(CONFIG_VIDEO_LT6911UXE) +static void set_lt_gpio(struct control_logic_data *ctl_data, struct sensor_platform_data **pdata, + bool is_dummy) +{ + int i; + + (*pdata)->irq_pin = -1; + (*pdata)->reset_pin = -1; + (*pdata)->detect_pin = -1; + + if (ctl_data->completed && ctl_data->gpio_num > 0 && !is_dummy) { + for (i = 0; i < ctl_data->gpio_num; i++) { + /* check for unsupported GPIO function */ + if (ctl_data->gpio[i].func != GPIO_RESET && + ctl_data->gpio[i].func != GPIO_READY_STAT && + ctl_data->gpio[i].func != GPIO_HDMI_DETECT) + dev_err(ctl_data->dev, + "IPU ACPI: Invalid GPIO func: %d\n", + ctl_data->gpio[i].func); + + /* check for RESET selection in BIOS */ + if (ctl_data->gpio[i].valid && ctl_data->gpio[i].func == GPIO_RESET) + (*pdata)->reset_pin = ctl_data->gpio[i].pin; + + /* check for READY_STAT selection in BIOS */ + if (ctl_data->gpio[i].valid && ctl_data->gpio[i].func == GPIO_READY_STAT) { + (*pdata)->irq_pin = ctl_data->gpio[i].pin; + (*pdata)->irq_pin_flags = IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | + IRQF_ONESHOT; + strscpy((*pdata)->irq_pin_name, "READY_STAT", sizeof("READY_STAT")); + } + + /* check for HDMI_DETECT selection in BIOS */ + if (ctl_data->gpio[i].valid && ctl_data->gpio[i].func == GPIO_HDMI_DETECT) + (*pdata)->detect_pin = ctl_data->gpio[i].pin; + } + } +} +#endif + static void set_common_gpio(struct control_logic_data *ctl_data, struct sensor_platform_data **pdata) { @@ -226,11 +612,11 @@ static void set_common_gpio(struct control_logic_data *ctl_data, ctl_data->gpio[i].func); } -static int set_csi2(struct ipu7_isys_subdev_info **sensor_sd, +static int set_csi2(struct ipu_isys_subdev_info **sensor_sd, unsigned int lanes, unsigned int port, unsigned int bus_type) { - struct ipu7_isys_csi2_config *csi2_config; + struct ipu_isys_csi2_config *csi2_config; csi2_config = kzalloc(sizeof(*csi2_config), GFP_KERNEL); if (!csi2_config) @@ -250,7 +636,7 @@ static int set_csi2(struct ipu7_isys_subdev_info **sensor_sd, return 0; } -static void set_i2c(struct ipu7_isys_subdev_info **sensor_sd, +static void set_i2c(struct ipu_isys_subdev_info **sensor_sd, struct device *dev, const char *sensor_name, unsigned int addr, @@ -270,11 +656,61 @@ static void set_serdes_sd_pdata(struct serdes_module_pdata **module_pdata, /* general */ (*module_pdata)->lanes = lanes; strscpy((*module_pdata)->module_name, sensor_name, I2C_NAME_SIZE); +#if IS_ENABLED(CONFIG_VIDEO_TI960) //????????????// +#if IS_ENABLED(CONFIG_VIDEO_IMX390) + /* TI960 and IMX390 specific */ + if (!strcmp(sensor_name, IMX390_NAME) && !strcmp(hid_name, "INTC10C1")) { + (*module_pdata)->gpio_powerup_seq[0] = 0; + (*module_pdata)->gpio_powerup_seq[1] = 0x9; + (*module_pdata)->gpio_powerup_seq[2] = -1; + (*module_pdata)->gpio_powerup_seq[3] = -1; + (*module_pdata)->module_flags = TI960_FL_POWERUP | + TI960_FL_INIT_SER | + TI960_FL_INIT_SER_CLK; + (*module_pdata)->fsin = 3; + } + /* TI960 and IMX390 specific */ + if (!strcmp(sensor_name, IMX390_NAME) && !strcmp(hid_name, "INTC10CM")) { + (*module_pdata)->gpio_powerup_seq[0] = 0; + (*module_pdata)->gpio_powerup_seq[1] = 0xa; + (*module_pdata)->gpio_powerup_seq[2] = -1; + (*module_pdata)->gpio_powerup_seq[3] = -1; + (*module_pdata)->module_flags = TI960_FL_POWERUP | + TI960_FL_INIT_SER | + TI960_FL_INIT_SER_CLK; + (*module_pdata)->fsin = 0; + } +#endif +#if IS_ENABLED(CONFIG_VIDEO_ISX031) + /* TI960 and ISX031 specific */ + if (!strcmp(sensor_name, ISX031_NAME) && !strcmp(hid_name, "INTC1031")) { + (*module_pdata)->gpio_powerup_seq[0] = 0x0; + (*module_pdata)->gpio_powerup_seq[1] = 0x08; + (*module_pdata)->gpio_powerup_seq[2] = 0X08; + (*module_pdata)->gpio_powerup_seq[3] = -1; + (*module_pdata)->module_flags = TI960_FL_POWERUP | + TI960_FL_INIT_SER; + (*module_pdata)->fsin = 2; + } +#endif +#if IS_ENABLED(CONFIG_VIDEO_OV2311) + /* TI960 and OV2311 specific */ + if (!strcmp(sensor_name, OV2311_NAME)) { + (*module_pdata)->gpio_powerup_seq[0] = 0x0; + (*module_pdata)->gpio_powerup_seq[1] = 0x09; + (*module_pdata)->gpio_powerup_seq[2] = -1; + (*module_pdata)->gpio_powerup_seq[3] = -1; + (*module_pdata)->module_flags = TI960_FL_POWERUP | + TI960_FL_INIT_SER; + (*module_pdata)->fsin = 2; + } +#endif +#endif } #define PORT_NR 8 -static int set_serdes_subdev(struct ipu7_isys_subdev_info **serdes_sd, +static int set_serdes_subdev(struct ipu_isys_subdev_info **serdes_sd, struct device *dev, struct serdes_platform_data **pdata, const char *sensor_name, @@ -304,12 +740,29 @@ static int set_serdes_subdev(struct ipu7_isys_subdev_info **serdes_sd, /* board info */ strscpy(serdes_sdinfo[i].board_info.type, sensor_name, I2C_NAME_SIZE); - serdes_sdinfo[i].board_info.addr = serdes_info.sensor_map_addr + i; +#if IS_ENABLED(CONFIG_VIDEO_D4XX) + if (!strcmp(sensor_name, D457_NAME)) { + if (i == 0) + serdes_sdinfo[i].board_info.addr = serdes_info.sensor_map_addr; + else + serdes_sdinfo[i].board_info.addr = serdes_info.sensor_map_addr_2; + } else +#endif + serdes_sdinfo[i].board_info.addr = serdes_info.sensor_map_addr + i; + serdes_sdinfo[i].board_info.platform_data = module_pdata[i]; /* serdes_subdev_info */ serdes_sdinfo[i].rx_port = i; - serdes_sdinfo[i].ser_alias = serdes_info.ser_map_addr + i; +#if IS_ENABLED(CONFIG_VIDEO_D4XX) + if (!strcmp(sensor_name, D457_NAME)) { + if (i == 0) + serdes_sdinfo[i].ser_alias = serdes_info.ser_map_addr; + else + serdes_sdinfo[i].ser_alias = serdes_info.ser_map_addr_2; + } else +#endif + serdes_sdinfo[i].ser_alias = serdes_info.ser_map_addr + i; serdes_sdinfo[i].phy_i2c_addr = serdes_info.phy_i2c_addr; snprintf(serdes_sdinfo[i].suffix, sizeof(serdes_sdinfo[i].suffix), "%c-%d", @@ -326,7 +779,7 @@ static int set_serdes_subdev(struct ipu7_isys_subdev_info **serdes_sd, return 0; } -static int set_pdata(struct ipu7_isys_subdev_info **sensor_sd, +static int set_pdata(struct ipu_isys_subdev_info **sensor_sd, struct device *dev, const char *sensor_name, const char *hid_name, @@ -363,7 +816,12 @@ static int set_pdata(struct ipu7_isys_subdev_info **sensor_sd, pdata->i2c_slave_address = addr; /* gpio */ - set_common_gpio(ctl_data, &pdata); +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) || IS_ENABLED(CONFIG_VIDEO_LT6911UXE) + if (!strcmp(sensor_name, LT6911UXC_NAME) || !strcmp(sensor_name, LT6911UXE_NAME)) + set_lt_gpio(ctl_data, &pdata, is_dummy); + else +#endif + set_common_gpio(ctl_data, &pdata); (*sensor_sd)->i2c.board_info.platform_data = pdata; } else if (connect == TYPE_SERDES) { @@ -375,13 +833,25 @@ static int set_pdata(struct ipu7_isys_subdev_info **sensor_sd, pr_debug("IPU ACPI: %s - Serdes connection", __func__); /* use ascii */ +#if IS_ENABLED(CONFIG_VIDEO_D4XX) + if (!strcmp(sensor_name, D457_NAME) && port >= 0) { + pdata->suffix = serdes_info.deser_num + SUFFIX_BASE; + pr_info("IPU ACPI: create %s %c, on deserializer port %d", + sensor_name, pdata->suffix, serdes_info.deser_num); + } else if (port >= 0) { +#else if (port >= 0) { +#endif pdata->suffix = port + SUFFIX_BASE; pr_info("IPU ACPI: create %s on mipi port %d", sensor_name, port); } else pr_err("IPU ACPI: Invalid MIPI Port : %d", port); +#if IS_ENABLED(CONFIG_VIDEO_TI960) + set_ti960_gpio(ctl_data, &pdata); +#endif + pdata->link_freq_mbps = link_freq; pdata->bus_type = (*sensor_sd)->csi2->bus_type; pdata->deser_nlanes = deser_lanes; @@ -417,13 +887,67 @@ static void set_serdes_info(struct device *dev, const char *sensor_name, /* sensor mapped addr */ serdes_info.sensor_map_addr = cam_data->i2c[i++].addr; +#if IS_ENABLED(CONFIG_VIDEO_D4XX) + if (!strcmp(sensor_name, D457_NAME) && serdes_info.i2c_num == SENSOR_2X_I2C) { + /* 2nd group of mapped addr */ + serdes_info.ser_map_addr_2 = cam_data->i2c[i++].addr; + serdes_info.sensor_map_addr_2 = cam_data->i2c[i++].addr; + } +#endif + +#if IS_ENABLED(CONFIG_VIDEO_TI960) + /* TI960 specific */ + if (!strcmp(serdes_name, TI960_NAME)) + serdes_info.gpio_powerup_seq = TI960_MAX_GPIO_POWERUP_SEQ; + else +#endif serdes_info.gpio_powerup_seq = 0; serdes_info.phy_i2c_addr = sensor_physical_addr; } +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) || IS_ENABLED(CONFIG_VIDEO_LT6911UXE) +static int populate_dummy(struct device *dev, + const char *sensor_name, + const char *hid_name, + struct sensor_bios_data *cam_data, + struct control_logic_data *ctl_data, + enum connection_type connect, + int link_freq) +{ + struct ipu_isys_subdev_info *dummy; + unsigned short addr_dummy = 0x11; + int ret; + + pr_debug("IPU ACPI: %s", __func__); + + dummy = kzalloc(sizeof(*dummy), GFP_KERNEL); + if (!dummy) + return -ENOMEM; + + ret = set_csi2(&dummy, cam_data->lanes, cam_data->pprval); + if (ret) { + kfree(dummy); + return ret; + } + + set_i2c(&dummy, dev, sensor_name, addr_dummy, NULL); + + ret = set_pdata(&dummy, dev, sensor_name, hid_name, ctl_data, cam_data->pprval, + cam_data->lanes, addr_dummy, 0, 0, true, connect, link_freq, 0); + if (ret) { + kfree(dummy); + return ret; + } + + update_pdata(dev, dummy, connect); + + return 0; +} +#endif + static int populate_sensor_pdata(struct device *dev, - struct ipu7_isys_subdev_info **sensor_sd, + struct ipu_isys_subdev_info **sensor_sd, struct sensor_bios_data *cam_data, struct control_logic_data *ctl_data, enum connection_type connect, @@ -433,8 +957,6 @@ static int populate_sensor_pdata(struct device *dev, int sensor_physical_addr, int link_freq) { - struct ipu7_isys_subdev_pdata *ptr_acpi_subdev_pdata = &acpi_subdev_pdata; - int i = 0; int ret; if (connect == TYPE_DIRECT) { @@ -453,8 +975,22 @@ static int populate_sensor_pdata(struct device *dev, cam_data->i2c_num); return -1; } + +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) || IS_ENABLED(CONFIG_VIDEO_LT6911UXE) + /* LT use LT Control Logic type */ + if (!strcmp(sensor_name, LT6911UXC_NAME) || + !strcmp(sensor_name, LT6911UXE_NAME)) { + if (ctl_data->type != CL_LT) { + dev_err(dev, "IPU ACPI: Control Logic Type\n"); + dev_err(dev, "for %s: %d is Incorrect\n", + sensor_name, ctl_data->type); + return -EINVAL; + } /* Others use DISCRETE Control Logic */ + } else if (ctl_data->type != CL_DISCRETE) { +#else if (ctl_data->type != CL_DISCRETE) { +#endif dev_err(dev, "IPU ACPI: Control Logic Type\n"); dev_err(dev, "for %s: %d is Incorrect\n", sensor_name, ctl_data->type); @@ -495,28 +1031,19 @@ static int populate_sensor_pdata(struct device *dev, if (ret) return ret; - /* update local ipu7_isys_subdev_pdata */ - while (i <= MAX_ACPI_SENSOR_NUM) { - if (!ptr_acpi_subdev_pdata->subdevs[i]) { - ptr_acpi_subdev_pdata->subdevs[i] = *sensor_sd; - ptr_acpi_subdev_pdata->subdevs[i+1] = NULL; - break; - } - i++; - } + update_pdata(dev, *sensor_sd, connect); - /* print new subdev */ - if (connect == TYPE_DIRECT) { - pr_debug("New sensor subdev\n"); - print_subdev(*sensor_sd); - } else { - pr_debug("New serdes subdev\n"); - print_serdes_subdev(*sensor_sd); + /* Lontium specific */ +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) || IS_ENABLED(CONFIG_VIDEO_LT6911UXE) + if (!strcmp(sensor_name, LT6911UXC_NAME) || !strcmp(sensor_name, LT6911UXE_NAME)) { + if (cam_data->pprval != cam_data->link) { + ret = populate_dummy(dev, sensor_name, hid_name, cam_data, ctl_data, connect, + link_freq); + if (ret) + return ret; + } } - - /* update total num of sensor connected */ - if (connect == TYPE_SERDES) - serdes_info.deser_num++; +#endif return 0; } @@ -530,12 +1057,13 @@ int get_sensor_pdata(struct device *dev, { struct sensor_bios_data *cam_data; struct control_logic_data *ctl_data; - struct ipu7_isys_subdev_info *sensor_sd; + struct ipu_isys_subdev_info *sensor_sd; int rval; cam_data = kzalloc(sizeof(*cam_data), GFP_KERNEL); if (!cam_data) return -ENOMEM; + cam_data->dev = dev; ctl_data = kzalloc(sizeof(*ctl_data), GFP_KERNEL); @@ -543,6 +1071,7 @@ int get_sensor_pdata(struct device *dev, kfree(cam_data); return -ENOMEM; } + ctl_data->dev = dev; sensor_sd = kzalloc(sizeof(*sensor_sd), GFP_KERNEL); diff --git a/drivers/media/platform/intel/ipu-acpi.c b/drivers/media/platform/intel/ipu-acpi.c index c254c82..de695be 100644 --- a/drivers/media/platform/intel/ipu-acpi.c +++ b/drivers/media/platform/intel/ipu-acpi.c @@ -32,15 +32,10 @@ #include #include #include + #include #include - -#if IS_ENABLED(CONFIG_VIDEO_ISX031) -#include -#endif - -#include "ipu7.h" -#include "ipu7-isys.h" +#include static LIST_HEAD(devices); @@ -62,6 +57,38 @@ static const struct ipu_acpi_devices supported_devices[] = { * { "ACPI ID", sensor_name, get_sensor_pdata, NULL, 0, TYPE, serdes_name, * sensor_physical_addr, link_freq(mbps) }, // Custom HID */ +#if IS_ENABLED(CONFIG_VIDEO_TI960) +#if IS_ENABLED(CONFIG_VIDEO_IMX390) + { "INTC10C1", IMX390_NAME, get_sensor_pdata, NULL, 0, TYPE_SERDES, TI960_NAME, + IMX390_I2C_ADDRESS, 1200 }, // IMX390 HID + { "INTC10CM", IMX390_NAME, get_sensor_pdata, NULL, 0, TYPE_SERDES, TI960_NAME, + IMX390_D3CM_I2C_ADDRESS, 1200 }, // D3 IMX390 HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_ISX031) + { "INTC1031", ISX031_NAME, get_sensor_pdata, NULL, 0, TYPE_SERDES, TI960_NAME, + ISX031_I2C_ADDRESS, 1600 }, // ISX031 HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_OV2311) + { "INTC102R", OV2311_NAME, get_sensor_pdata, NULL, 0, TYPE_SERDES, TI960_NAME, + OV2311_I2C_ADDRESS, 1200 }, // OV2311 HID +#endif +#endif +#if IS_ENABLED(CONFIG_VIDEO_AR0234) + { "INTC10C0", AR0234_NAME, get_sensor_pdata, NULL, 0, TYPE_DIRECT, NULL, + AR0234_I2C_ADDRESS, 1200 }, // AR0234 HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) + { "INTC10B1", LT6911UXC_NAME, get_sensor_pdata, NULL, 0, TYPE_DIRECT, NULL, + LT6911UXC_I2C_ADDRESS, 1200 }, // LT6911UXC HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXE) + { "INTC10C5", LT6911UXE_NAME, get_sensor_pdata, NULL, 0, TYPE_DIRECT, NULL, + LT6911UXE_I2C_ADDRESS, 1200 }, // LT6911UXE HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_D4XX) + { "INTC10CD", D457_NAME, get_sensor_pdata, NULL, 0, TYPE_SERDES, D457_NAME, + D4XX_I2C_ADDRESS_0, 1200 }, // D457 HID +#endif #if IS_ENABLED(CONFIG_VIDEO_MAX9X) #if IS_ENABLED(CONFIG_VIDEO_ISX031) @@ -73,7 +100,7 @@ static const struct ipu_acpi_devices supported_devices[] = { static int get_table_index(const char *acpi_name) { - unsigned int i; + int i; for (i = 0; i < ARRAY_SIZE(supported_devices); i++) { if (!strncmp(supported_devices[i].hid_name, acpi_name, @@ -90,9 +117,28 @@ static const struct acpi_device_id ipu_acpi_match[] = { /* * { "AR0234A", 0 }, // Custom HID */ +#if IS_ENABLED(CONFIG_VIDEO_IMX390) + { "INTC10C1", 0 }, // IMX390 HID + { "INTC10CM", 0 }, // D3CMC68N-106-085 IMX390 HID +#endif #if IS_ENABLED(CONFIG_VIDEO_ISX031) { "INTC1031", 0 }, // ISX031 HID { "INTC031M", 0 }, // D3CMC68N-115-084 ISX031 HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_AR0234) + { "INTC10C0", 0 }, // AR0234 HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) + { "INTC10B1", 0 }, // LT6911UXC HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXE) + { "INTC10C5", 0 }, // LT6911UXE HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_OV2311) + { "INTC102R", 0 }, // OV2311 HID +#endif +#if IS_ENABLED(CONFIG_VIDEO_D4XX) + { "INTC10CD", 0 }, // D457 HID #endif {}, }; @@ -143,8 +189,8 @@ static int ipu_acpi_test(struct device *dev, void *priv) if (acpi_idx < 0) return 0; - else - dev_info(dev, "IPU6 ACPI: ACPI device %s\n", dev_name(dev)); + + dev_info(dev, "IPU6 ACPI: ACPI device %s\n", dev_name(dev)); const char *target_hid = supported_devices[acpi_idx].hid_name; @@ -161,10 +207,10 @@ static int ipu_acpi_test(struct device *dev, void *priv) if (!adev) { dev_dbg(dev, "No ACPI device found for %s\n", target_hid); return 0; - } else { - set_primary_fwnode(dev, &adev->fwnode); - dev_dbg(dev, "Assigned fwnode to %s\n", dev_name(dev)); } + + set_primary_fwnode(dev, &adev->fwnode); + dev_dbg(dev, "Assigned fwnode to %s\n", dev_name(dev)); } if (ACPI_COMPANION(dev) != adev) { @@ -185,14 +231,52 @@ static int ipu_acpi_test(struct device *dev, void *priv) return 0; /* Continue iteration */ } +/* Scan all i2c devices and pick ones which we can handle */ + /* Try to get all IPU related devices mentioned in BIOS and all related information - * return a new generated existing pdata + * If there is existing ipu_isys_subdev_pdata, update the existing pdata + * If not, return a new generated existing pdata */ -int ipu_get_acpi_devices(void **spdata) +int ipu_get_acpi_devices(void *driver_data, + struct device *dev, + void **spdata, + void **built_in_pdata, + int (*fn) + (struct device *, void *, + void *csi2, + bool reprobe)) +{ + int rval; + + if (!built_in_pdata) + dev_dbg(dev, "Built-in pdata not found"); + else { + dev_dbg(dev, "Built-in pdata found"); + set_built_in_pdata(*built_in_pdata); + } + + if ((!fn) || (!driver_data)) + return -ENODEV; + + rval = acpi_bus_for_each_dev(ipu_acpi_test, NULL); + if (rval < 0) + return rval; + + if (!built_in_pdata) { + dev_dbg(dev, "Return ACPI generated pdata"); + *spdata = get_acpi_subdev_pdata(); + } else + dev_dbg(dev, "Return updated built-in pdata"); + + return 0; +} +EXPORT_SYMBOL(ipu_get_acpi_devices); + +int ipu_get_acpi_devices_new(void **spdata) { int rval; - struct ipu7_isys_subdev_pdata *ptr = NULL; + struct ipu_isys_subdev_pdata *ptr = NULL; rval = acpi_bus_for_each_dev(ipu_acpi_test, NULL); if (rval < 0) @@ -204,10 +288,11 @@ int ipu_get_acpi_devices(void **spdata) return 0; } -EXPORT_SYMBOL(ipu_get_acpi_devices); +EXPORT_SYMBOL(ipu_get_acpi_devices_new); static int __init ipu_acpi_init(void) { + set_built_in_pdata(NULL); return 0; } diff --git a/include/media/ipu-acpi-pdata.h b/include/media/ipu-acpi-pdata.h index e207441..4c754e9 100644 --- a/include/media/ipu-acpi-pdata.h +++ b/include/media/ipu-acpi-pdata.h @@ -3,12 +3,12 @@ #include #include #include -#if IS_ENABLED(CONFIG_VIDEO_ISX031) -#include -#endif +#include #define CL_EMPTY 0 #define CL_DISCRETE 1 +#define CL_LT 5 +#define SERDES_MAX_PORT 4 #define SERDES_MAX_GPIO_POWERUP_SEQ 4 #define LOOP_SIZE 10 @@ -26,7 +26,7 @@ int get_sensor_pdata(struct device *dev, int sensor_physical_addr, int link_freq); -struct ipu7_isys_subdev_pdata *get_acpi_subdev_pdata(void); +struct ipu_isys_subdev_pdata *get_acpi_subdev_pdata(void); struct sensor_platform_data { unsigned int port; @@ -34,37 +34,11 @@ struct sensor_platform_data { uint32_t i2c_slave_address; int irq_pin; unsigned int irq_pin_flags; - char irq_pin_name[IPU7_SPDATA_IRQ_PIN_NAME_LEN]; + char irq_pin_name[IPU_SPDATA_IRQ_PIN_NAME_LEN]; int reset_pin; int detect_pin; char suffix; - int gpios[IPU7_SPDATA_GPIO_NUM]; -}; - -struct serdes_platform_data { - unsigned int subdev_num; - struct serdes_subdev_info *subdev_info; - unsigned int reset_gpio; - unsigned int FPD_gpio; - char suffix; - unsigned int link_freq_mbps; - enum v4l2_mbus_type bus_type; - unsigned int deser_nlanes; - unsigned int ser_nlanes; - unsigned int des_port; - char ser_name[I2C_NAME_SIZE]; - struct i2c_board_info *deser_board_info; -}; - -struct serdes_subdev_info { - struct i2c_board_info board_info; - int i2c_adapter_id; - unsigned short rx_port; - unsigned short phy_i2c_addr; - unsigned short ser_alias; - char suffix[5]; /* suffix for subdevs */ - unsigned short ser_phys_addr; - unsigned int sensor_dt; + int gpios[IPU_SPDATA_GPIO_NUM]; }; struct serdes_module_pdata { diff --git a/include/media/ipu-acpi.h b/include/media/ipu-acpi.h index bc63240..a2467b3 100644 --- a/include/media/ipu-acpi.h +++ b/include/media/ipu-acpi.h @@ -16,16 +16,61 @@ #ifndef MEDIA_INTEL_IPU_ACPI_H #define MEDIA_INTEL_IPU_ACPI_H -#include "ipu7-isys.h" +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 10, 0) +#include +#include "ipu-isys.h" +#else +#include +#include + +#include + +struct ipu_isys_csi2_config { + unsigned int nlanes; + unsigned int port; + enum v4l2_mbus_type bus_type; +}; + +struct ipu_isys_subdev_i2c_info { + struct i2c_board_info board_info; + int i2c_adapter_id; + char i2c_adapter_bdf[32]; +}; + +struct ipu_isys_subdev_info { + struct ipu_isys_csi2_config *csi2; + struct ipu_isys_subdev_i2c_info i2c; +#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) + char *acpi_hid; +#endif +}; + +struct ipu_isys_clk_mapping { + struct clk_lookup clkdev_data; + char *platform_clock_name; +}; + +struct ipu_isys_subdev_pdata { + struct ipu_isys_subdev_info **subdevs; + struct ipu_isys_clk_mapping *clk_map; +}; +#endif #define MAX_ACPI_SENSOR_NUM 4 #define MAX_ACPI_I2C_NUM 12 #define MAX_ACPI_GPIO_NUM 12 #define GPIO_RESET 0x0 +#define GPIO_POWER_EN 0xb +#define GPIO_READY_STAT 0x13 +#define GPIO_HDMI_DETECT 0x14 + +#define IPU_SPDATA_GPIO_NUM 4 +#define IPU_SPDATA_IRQ_PIN_NAME_LEN 16 -#define IPU7_SPDATA_GPIO_NUM 4 -#define IPU7_SPDATA_IRQ_PIN_NAME_LEN 16 +void set_built_in_pdata(struct ipu_isys_subdev_pdata *pdata); enum connection_type { TYPE_DIRECT, @@ -122,6 +167,11 @@ struct ipu_gpio_info { bool valid; }; +struct ipu_irq_info { + int irq_pin; + char irq_pin_name[IPU_SPDATA_IRQ_PIN_NAME_LEN]; +}; + /* Each I2C client linked to 1 set of CTL Logic */ struct control_logic_data { struct device *dev; @@ -133,9 +183,7 @@ struct control_logic_data { bool completed; }; -int ipu_get_acpi_devices(void **spdata); - -struct ipu7_isys_subdev_pdata *get_built_in_pdata(void); +struct ipu_isys_subdev_pdata *get_built_in_pdata(void); int ipu_acpi_get_cam_data(struct device *dev, struct sensor_bios_data *sensor); @@ -146,17 +194,29 @@ int ipu_acpi_get_dep_data(struct device *dev, int ipu_acpi_get_control_logic_data(struct device *dev, struct control_logic_data **ctl_data); +struct intel_ipu6_regulator { + char *src_dev_name; + char *src_rail; + char *dest_rail; +}; + struct ipu_i2c_helper { int (*fn)(struct device *dev, void *priv, - struct ipu7_isys_csi2_config *csi2, + struct ipu_isys_csi2_config *csi2, bool reprobe); void *driver_data; }; +struct ipu_i2c_new_dev { + struct list_head list; + struct i2c_board_info info; + unsigned short int bus; +}; + struct ipu_camera_module_data { struct list_head list; - struct ipu7_isys_subdev_info sd; - struct ipu7_isys_csi2_config csi2; + struct ipu_isys_subdev_info sd; + struct ipu_isys_csi2_config csi2; unsigned int ext_clk; void *pdata; /* Ptr to generated platform data*/ void *priv; /* Private for specific subdevice */ diff --git a/include/media/ipu-get-acpi.h b/include/media/ipu-get-acpi.h new file mode 100644 index 0000000..da2ed51 --- /dev/null +++ b/include/media/ipu-get-acpi.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2016-2025 Intel Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef MEDIA_INTEL_IPU_GET_ACPI_H +#define MEDIA_INTEL_IPU_GET_ACPI_H + +int ipu_get_acpi_devices(void *driver_data, + struct device *dev, + void **spdata, + void **built_in_pdata, + int (*fn) + (struct device *, void *, + void *csi2, + bool reprobe)); + +int ipu_get_acpi_devices_new(void **spdata); + +#endif /* MEDIA_INTEL_IPU_GET_ACPI_H */ diff --git a/patch/v6.17_staging/0001-staging-add-ipu7-isys-reset-code.patch b/patch/v6.17_staging/0001-staging-add-ipu7-isys-reset-code.patch new file mode 100644 index 0000000..75ba2c5 --- /dev/null +++ b/patch/v6.17_staging/0001-staging-add-ipu7-isys-reset-code.patch @@ -0,0 +1,803 @@ +From b2ab04727acd72eee42f7f6094b8d88920f43787 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 24 Oct 2025 11:46:21 +0800 +Subject: [PATCH] patch: staging add ipu7 isys reset code + +Signed-off-by: linya14x +--- + drivers/staging/media/ipu7/Kconfig | 10 + + drivers/staging/media/ipu7/ipu7-isys-queue.c | 359 ++++++++++++++++++- + drivers/staging/media/ipu7/ipu7-isys-queue.h | 3 + + drivers/staging/media/ipu7/ipu7-isys-video.c | 102 ++++++ + drivers/staging/media/ipu7/ipu7-isys-video.h | 8 + + drivers/staging/media/ipu7/ipu7-isys.c | 16 + + drivers/staging/media/ipu7/ipu7-isys.h | 16 + + 7 files changed, 513 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/ipu7/Kconfig b/drivers/staging/media/ipu7/Kconfig +index 7d831ba750..c4eee7c3e6 100644 +--- a/drivers/staging/media/ipu7/Kconfig ++++ b/drivers/staging/media/ipu7/Kconfig +@@ -17,3 +17,13 @@ config VIDEO_INTEL_IPU7 + + To compile this driver, say Y here! It contains 2 modules - + intel_ipu7 and intel_ipu7_isys. ++ ++config VIDEO_INTEL_IPU7_ISYS_RESET ++ bool "IPU7 ISYS RESET" ++ depends on VIDEO_INTEL_IPU7 ++ default n ++ help ++ This option enables IPU7 ISYS reset feature to support ++ HDMI-MIPI converter hot-plugging. ++ ++ If doubt, say N here. +diff --git a/drivers/staging/media/ipu7/ipu7-isys-queue.c b/drivers/staging/media/ipu7/ipu7-isys-queue.c +index 7046c29141..0c1596a2ba 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys-queue.c ++++ b/drivers/staging/media/ipu7/ipu7-isys-queue.c +@@ -11,6 +11,9 @@ + #include + #include + #include ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++#include ++#endif + + #include + #include +@@ -26,6 +29,9 @@ + #include "ipu7-isys-csi2-regs.h" + #include "ipu7-isys-video.h" + #include "ipu7-platform-regs.h" ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++#include "ipu7-cpd.h" ++#endif + + #define IPU_MAX_FRAME_COUNTER (U8_MAX + 1) + +@@ -225,6 +231,16 @@ static int buffer_list_get(struct ipu7_isys_stream *stream, + ib = list_last_entry(&aq->incoming, + struct ipu7_isys_buffer, head); + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); ++ ++ if (av->skipframe) { ++ atomic_set(&ib->skipframe_flag, 1); ++ av->skipframe--; ++ } else { ++ atomic_set(&ib->skipframe_flag, 0); ++ } ++#endif + dev_dbg(dev, "buffer: %s: buffer %u\n", + ipu7_isys_queue_to_video(aq)->vdev.name, + ipu7_isys_buffer_to_vb2_buffer(ib)->index); +@@ -379,6 +395,18 @@ static void buf_queue(struct vb2_buffer *vb) + return; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ mutex_lock(&av->isys->reset_mutex); ++ if (av->isys->state & RESET_STATE_IN_RESET) { ++ dev_dbg(dev, "in reset, adding to incoming\n"); ++ mutex_unlock(&av->isys->reset_mutex); ++ return; ++ } ++ mutex_unlock(&av->isys->reset_mutex); ++ ++ /* ip may be cleared in ipu reset */ ++ stream = av->stream; ++#endif + mutex_lock(&stream->mutex); + + if (stream->nr_streaming != stream->nr_queues) { +@@ -480,6 +508,10 @@ static int ipu7_isys_link_fmt_validate(struct ipu7_isys_queue *aq) + static void return_buffers(struct ipu7_isys_queue *aq, + enum vb2_buffer_state state) + { ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ bool need_reset = false; ++ struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); ++#endif + struct ipu7_isys_buffer *ib; + struct vb2_buffer *vb; + unsigned long flags; +@@ -501,6 +533,9 @@ static void return_buffers(struct ipu7_isys_queue *aq, + vb2_buffer_done(vb, state); + + spin_lock_irqsave(&aq->lock, flags); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ need_reset = true; ++#endif + } + + while (!list_empty(&aq->incoming)) { +@@ -516,6 +551,14 @@ static void return_buffers(struct ipu7_isys_queue *aq, + } + + spin_unlock_irqrestore(&aq->lock, flags); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ ++ if (need_reset) { ++ mutex_lock(&av->isys->reset_mutex); ++ av->isys->need_reset = true; ++ mutex_unlock(&av->isys->reset_mutex); ++ } ++#endif + } + + static void ipu7_isys_stream_cleanup(struct ipu7_isys_video *av) +@@ -594,6 +637,9 @@ static int start_streaming(struct vb2_queue *q, unsigned int count) + + out: + mutex_unlock(&stream->mutex); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ av->start_streaming = 1; ++#endif + + return 0; + +@@ -614,17 +660,272 @@ out_return_buffers: + return ret; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++static void reset_stop_streaming(struct ipu7_isys_video *av) ++{ ++ struct ipu7_isys_queue *aq = &av->aq; ++ struct ipu7_isys_stream *stream = av->stream; ++ struct ipu7_isys_buffer *ib; ++ struct vb2_buffer *vb; ++ unsigned long flags; ++ ++ mutex_lock(&av->isys->stream_mutex); ++ if (stream->nr_streaming == stream->nr_queues && stream->streaming) ++ ipu7_isys_video_set_streaming(av, 0, NULL); ++ mutex_unlock(&av->isys->stream_mutex); ++ ++ mutex_lock(&stream->mutex); ++ stream->nr_streaming--; ++ list_del(&aq->node); ++ stream->streaming = 0; ++ mutex_unlock(&stream->mutex); ++ ++ ipu7_isys_stream_cleanup(av); ++ ++ spin_lock_irqsave(&aq->lock, flags); ++ while (!list_empty(&aq->active)) { ++ ib = list_last_entry(&aq->active, struct ipu7_isys_buffer, ++ head); ++ vb = ipu7_isys_buffer_to_vb2_buffer(ib); ++ ++ list_del(&ib->head); ++ spin_unlock_irqrestore(&aq->lock, flags); ++ ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++ ++ spin_lock_irqsave(&aq->lock, flags); ++ } ++ spin_unlock_irqrestore(&aq->lock, flags); ++ ++ ipu7_isys_fw_close(av->isys); ++} ++ ++static int reset_start_streaming(struct ipu7_isys_video *av) ++{ ++ struct ipu7_isys_queue *aq = &av->aq; ++ struct device *dev = &av->isys->adev->auxdev.dev; ++ struct ipu7_isys_buffer_list __bl, *bl = NULL; ++ struct ipu7_isys_stream *stream; ++ struct media_entity *source_entity = NULL; ++ int nr_queues; ++ int ret; ++ ++ dev_dbg(dev, "%s: reset start streaming\n", av->vdev.name); ++ ++ av->skipframe = 1; ++ ++ ret = ipu7_isys_setup_video(av, &source_entity, &nr_queues); ++ if (ret < 0) { ++ dev_dbg(dev, "failed to setup video\n"); ++ goto out_return_buffers; ++ } ++ ++ ret = ipu7_isys_link_fmt_validate(aq); ++ if (ret) { ++ dev_dbg(dev, ++ "%s: link format validation failed (%d)\n", ++ av->vdev.name, ret); ++ goto out_pipeline_stop; ++ } ++ ++ stream = av->stream; ++ mutex_lock(&stream->mutex); ++ if (!stream->nr_streaming) { ++ ret = ipu7_isys_video_prepare_stream(av, source_entity, ++ nr_queues); ++ if (ret) { ++ mutex_unlock(&stream->mutex); ++ goto out_pipeline_stop; ++ } ++ } ++ ++ stream->nr_streaming++; ++ dev_dbg(dev, "queue %u of %u\n", stream->nr_streaming, ++ stream->nr_queues); ++ ++ list_add(&aq->node, &stream->queues); ++ ++ if (stream->nr_streaming != stream->nr_queues) ++ goto out; ++ ++ bl = &__bl; ++ ret = buffer_list_get(stream, bl); ++ /* ++ * In reset start streaming and no buffer available, ++ * it is considered that gstreamer has been closed, ++ * and reset start is no needed, not driver bug. ++ */ ++ if (ret) { ++ dev_dbg(dev, "reset start: no buffer available, gstreamer colsed\n"); ++ mutex_lock(&av->isys->stream_mutex); ++ if (stream->nr_streaming == stream->nr_queues && stream->streaming) ++ ipu7_isys_video_set_streaming(av, 0, NULL); ++ mutex_unlock(&av->isys->stream_mutex); ++ ++ goto out_stream_start; ++ } ++ ++ ret = ipu7_isys_fw_open(av->isys); ++ if (ret) ++ goto out_stream_start; ++ ++ ipu7_isys_setup_hw(av->isys); ++ ++ ret = ipu7_isys_stream_start(av, bl, false); ++ if (ret) ++ goto out_isys_fw_close; ++ ++out: ++ mutex_unlock(&stream->mutex); ++ av->start_streaming = 1; ++ return 0; ++ ++out_isys_fw_close: ++ ipu7_isys_fw_close(av->isys); ++ ++out_stream_start: ++ list_del(&aq->node); ++ stream->nr_streaming--; ++ mutex_unlock(&stream->mutex); ++ ++out_pipeline_stop: ++ ipu7_isys_stream_cleanup(av); ++ ++out_return_buffers: ++ return_buffers(aq, VB2_BUF_STATE_QUEUED); ++ av->start_streaming = 0; ++ dev_dbg(dev, "%s: reset start streaming failed!\n", av->vdev.name); ++ return ret; ++} ++ ++static int ipu_isys_reset(struct ipu7_isys_video *self_av, ++ struct ipu7_isys_stream *self_stream) ++{ ++ struct ipu7_isys *isys = self_av->isys; ++ struct ipu7_bus_device *adev = isys->adev; ++ struct ipu7_isys_video *av = NULL; ++ struct ipu7_isys_stream *stream = NULL; ++ struct device *dev = &adev->auxdev.dev; ++ int i, j; ++ int has_streaming = 0; ++ const struct ipu7_isys_internal_csi2_pdata *csi2_pdata = ++ &isys->pdata->ipdata->csi2; ++ ++ mutex_lock(&isys->reset_mutex); ++ if (isys->state & RESET_STATE_IN_RESET) { ++ mutex_unlock(&isys->reset_mutex); ++ return 0; ++ } ++ isys->state |= RESET_STATE_IN_RESET; ++ dev_dbg(dev, "%s: %s\n", __func__, self_av->vdev.name); ++ ++ while (isys->state & RESET_STATE_IN_STOP_STREAMING) { ++ dev_dbg(dev, "isys reset: %s: wait for stop\n", ++ self_av->vdev.name); ++ mutex_unlock(&isys->reset_mutex); ++ usleep_range(10000, 11000); ++ mutex_lock(&isys->reset_mutex); ++ } ++ ++ mutex_unlock(&isys->reset_mutex); ++ ++ dev_dbg(dev, "reset stop streams\n"); ++ for (i = 0; i < csi2_pdata->nports; i++) { ++ for (j = 0; j < IPU7_NR_OF_CSI2_SRC_PADS; j++) { ++ av = &isys->csi2[i].av[j]; ++ if (av == self_av) ++ continue; ++ ++ stream = av->stream; ++ if (!stream || stream == self_stream) ++ continue; ++ ++ if (!stream->streaming && !stream->nr_streaming) ++ continue; ++ ++ av->reset = true; ++ has_streaming = true; ++ reset_stop_streaming(av); ++ } ++ } ++ ++ if (!has_streaming) ++ goto end_of_reset; ++ ++ ipu7_cleanup_fw_msg_bufs(isys); ++ ++ dev_dbg(dev, "reset start streams\n"); ++ ++ for (j = 0; j < csi2_pdata->nports; j++) { ++ for (i = 0; i < IPU7_NR_OF_CSI2_SRC_PADS; i++) { ++ av = &isys->csi2[j].av[i]; ++ if (!av->reset) ++ continue; ++ ++ av->reset = false; ++ reset_start_streaming(av); ++ } ++ } ++ ++end_of_reset: ++ mutex_lock(&isys->reset_mutex); ++ isys->state &= ~RESET_STATE_IN_RESET; ++ mutex_unlock(&isys->reset_mutex); ++ dev_dbg(dev, "reset done\n"); ++ ++ return 0; ++} ++ + static void stop_streaming(struct vb2_queue *q) + { + struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(q); + struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); + struct ipu7_isys_stream *stream = av->stream; ++ int ret = 0; ++ ++ struct device *dev = &av->isys->adev->auxdev.dev; ++ bool need_reset; ++ ++ dev_dbg(dev, "stop: %s: enter\n", av->vdev.name); ++ ++ mutex_lock(&av->isys->reset_mutex); ++ while (av->isys->state) { ++ mutex_unlock(&av->isys->reset_mutex); ++ dev_dbg(dev, "stop: %s: wait for rest or stop, isys->state = %d\n", ++ av->vdev.name, av->isys->state); ++ usleep_range(10000, 11000); ++ mutex_lock(&av->isys->reset_mutex); ++ } ++ ++ if (!av->start_streaming) { ++ mutex_unlock(&av->isys->reset_mutex); ++ return_buffers(aq, VB2_BUF_STATE_ERROR); ++ return; ++ } ++ ++ av->isys->state |= RESET_STATE_IN_STOP_STREAMING; ++ mutex_unlock(&av->isys->reset_mutex); ++ ++ stream = av->stream; ++ if (!stream) { ++ dev_err(dev, "stop: %s: ip cleard!\n", av->vdev.name); ++ return_buffers(aq, VB2_BUF_STATE_ERROR); ++ mutex_lock(&av->isys->reset_mutex); ++ av->isys->state &= ~RESET_STATE_IN_STOP_STREAMING; ++ mutex_unlock(&av->isys->reset_mutex); ++ return; ++ } + + mutex_lock(&stream->mutex); + mutex_lock(&av->isys->stream_mutex); + if (stream->nr_streaming == stream->nr_queues && stream->streaming) +- ipu7_isys_video_set_streaming(av, 0, NULL); ++ ret = ipu7_isys_video_set_streaming(av, 0, NULL); + mutex_unlock(&av->isys->stream_mutex); ++ if (ret) { ++ dev_err(dev, "stop: video set streaming failed\n"); ++ mutex_unlock(&stream->mutex); ++ return; ++ } + + stream->nr_streaming--; + list_del(&aq->node); +@@ -637,7 +938,58 @@ static void stop_streaming(struct vb2_queue *q) + return_buffers(aq, VB2_BUF_STATE_ERROR); + + ipu7_isys_fw_close(av->isys); ++ ++ av->start_streaming = 0; ++ mutex_lock(&av->isys->reset_mutex); ++ av->isys->state &= ~RESET_STATE_IN_STOP_STREAMING; ++ need_reset = av->isys->need_reset; ++ mutex_unlock(&av->isys->reset_mutex); ++ ++ if (need_reset) { ++ if (!stream->nr_streaming) { ++ ipu_isys_reset(av, stream); ++ } else { ++ mutex_lock(&av->isys->reset_mutex); ++ av->isys->need_reset = false; ++ mutex_unlock(&av->isys->reset_mutex); ++ } ++ } ++ ++ dev_dbg(dev, "stop: %s: exit\n", av->vdev.name); + } ++#else ++static void stop_streaming(struct vb2_queue *q) ++{ ++ struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(q); ++ struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); ++ struct ipu7_isys_stream *stream = av->stream; ++ int ret = 0; ++ ++ mutex_lock(&stream->mutex); ++ mutex_lock(&av->isys->stream_mutex); ++ if (stream->nr_streaming == stream->nr_queues && stream->streaming) ++ ret = ipu7_isys_video_set_streaming(av, 0, NULL); ++ mutex_unlock(&av->isys->stream_mutex); ++ if (ret) { ++ dev_err(&av->isys->adev->auxdev.dev, ++ "stop: video set streaming failed\n"); ++ mutex_unlock(&stream->mutex); ++ return; ++ } ++ ++ stream->nr_streaming--; ++ list_del(&aq->node); ++ stream->streaming = 0; ++ ++ mutex_unlock(&stream->mutex); ++ ++ ipu7_isys_stream_cleanup(av); ++ ++ return_buffers(aq, VB2_BUF_STATE_ERROR); ++ ++ ipu7_isys_fw_close(av->isys); ++} ++#endif + + static unsigned int + get_sof_sequence_by_timestamp(struct ipu7_isys_stream *stream, u64 time) +@@ -719,6 +1071,11 @@ static void ipu7_isys_queue_buf_done(struct ipu7_isys_buffer *ib) + * to the userspace when it is de-queued + */ + atomic_set(&ib->str2mmio_flag, 0); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ } else if (atomic_read(&ib->skipframe_flag)) { ++ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); ++ atomic_set(&ib->skipframe_flag, 0); ++#endif + } else { + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + } +diff --git a/drivers/staging/media/ipu7/ipu7-isys-queue.h b/drivers/staging/media/ipu7/ipu7-isys-queue.h +index 0cb08a38f7..5a909c3a78 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys-queue.h ++++ b/drivers/staging/media/ipu7/ipu7-isys-queue.h +@@ -31,6 +31,9 @@ struct ipu7_isys_queue { + struct ipu7_isys_buffer { + struct list_head head; + atomic_t str2mmio_flag; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ atomic_t skipframe_flag; ++#endif + }; + + struct ipu7_isys_video_buffer { +diff --git a/drivers/staging/media/ipu7/ipu7-isys-video.c b/drivers/staging/media/ipu7/ipu7-isys-video.c +index 8756da3a8f..b3d337fe78 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys-video.c ++++ b/drivers/staging/media/ipu7/ipu7-isys-video.c +@@ -18,6 +18,9 @@ + #include + #include + #include ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++#include ++#endif + + #include + #include +@@ -90,9 +93,43 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { + + static int video_open(struct file *file) + { ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ struct ipu7_isys_video *av = video_drvdata(file); ++ struct ipu7_isys *isys = av->isys; ++ struct ipu7_bus_device *adev = isys->adev; ++ ++ mutex_lock(&isys->reset_mutex); ++ if (isys->need_reset) { ++ mutex_unlock(&isys->reset_mutex); ++ dev_warn(&adev->auxdev.dev, "isys power cycle required\n"); ++ return -EIO; ++ } ++ mutex_unlock(&isys->reset_mutex); ++ ++#endif + return v4l2_fh_open(file); + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++static int video_release(struct file *file) ++{ ++ struct ipu7_isys_video *av = video_drvdata(file); ++ ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "release: %s: enter\n", av->vdev.name); ++ mutex_lock(&av->isys->reset_mutex); ++ while (av->isys->state & RESET_STATE_IN_RESET) { ++ mutex_unlock(&av->isys->reset_mutex); ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "release: %s: wait for reset\n", av->vdev.name); ++ usleep_range(10000, 11000); ++ mutex_lock(&av->isys->reset_mutex); ++ } ++ mutex_unlock(&av->isys->reset_mutex); ++ return vb2_fop_release(file); ++} ++ ++#endif + const struct ipu7_isys_pixelformat *ipu7_isys_get_isys_format(u32 pixelformat) + { + unsigned int i; +@@ -589,7 +626,11 @@ static void stop_streaming_firmware(struct ipu7_isys_video *av) + } + + tout = wait_for_completion_timeout(&stream->stream_stop_completion, ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ FW_CALL_TIMEOUT_JIFFIES_RESET); ++#else + FW_CALL_TIMEOUT_JIFFIES); ++#endif + if (!tout) + dev_warn(dev, "stream stop time out\n"); + else if (stream->error) +@@ -614,7 +655,11 @@ static void close_streaming_firmware(struct ipu7_isys_video *av) + } + + tout = wait_for_completion_timeout(&stream->stream_close_completion, ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ FW_CALL_TIMEOUT_JIFFIES_RESET); ++#else + FW_CALL_TIMEOUT_JIFFIES); ++#endif + if (!tout) + dev_warn(dev, "stream close time out\n"); + else if (stream->error) +@@ -622,6 +667,12 @@ static void close_streaming_firmware(struct ipu7_isys_video *av) + else + dev_dbg(dev, "close stream: complete\n"); + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ stream->last_sequence = atomic_read(&stream->sequence); ++ dev_dbg(dev, "ip->last_sequence = %d\n", ++ stream->last_sequence); ++ ++#endif + put_stream_opened(av); + } + +@@ -636,7 +687,18 @@ int ipu7_isys_video_prepare_stream(struct ipu7_isys_video *av, + return -EINVAL; + + stream->nr_queues = nr_queues; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ if (av->isys->state & RESET_STATE_IN_RESET) { ++ atomic_set(&stream->sequence, stream->last_sequence); ++ dev_dbg(&av->isys->adev->auxdev.dev, ++ "atomic_set : stream->last_sequence = %d\n", ++ stream->last_sequence); ++ } else { ++ atomic_set(&stream->sequence, 0); ++ } ++#else + atomic_set(&stream->sequence, 0); ++#endif + atomic_set(&stream->buf_id, 0); + + stream->seq_index = 0; +@@ -897,7 +959,11 @@ static const struct v4l2_file_operations isys_fops = { + .unlocked_ioctl = video_ioctl2, + .mmap = vb2_fop_mmap, + .open = video_open, ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ .release = video_release, ++#else + .release = vb2_fop_release, ++#endif + }; + + int ipu7_isys_fw_open(struct ipu7_isys *isys) +@@ -936,6 +1002,35 @@ out: + return ret; + } + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++void ipu7_isys_fw_close(struct ipu7_isys *isys) ++{ ++ int ret = 0; ++ ++ mutex_lock(&isys->mutex); ++ isys->ref_count--; ++ if (!isys->ref_count) { ++ /* need reset when fw close is abnormal */ ++ ret = ipu7_fw_isys_close(isys); ++ if (ret) { ++ mutex_lock(&isys->reset_mutex); ++ isys->need_reset = true; ++ mutex_unlock(&isys->reset_mutex); ++ } ++ } ++ ++ mutex_unlock(&isys->mutex); ++ ++ mutex_lock(&isys->reset_mutex); ++ if (isys->need_reset) { ++ mutex_unlock(&isys->reset_mutex); ++ pm_runtime_put_sync(&isys->adev->auxdev.dev); ++ } else { ++ mutex_unlock(&isys->reset_mutex); ++ pm_runtime_put(&isys->adev->auxdev.dev); ++ } ++} ++#else + void ipu7_isys_fw_close(struct ipu7_isys *isys) + { + mutex_lock(&isys->mutex); +@@ -946,7 +1041,9 @@ void ipu7_isys_fw_close(struct ipu7_isys *isys) + ipu7_fw_isys_close(isys); + + mutex_unlock(&isys->mutex); ++ pm_runtime_put(&isys->adev->auxdev.dev); + } ++#endif + + int ipu7_isys_setup_video(struct ipu7_isys_video *av, + struct media_entity **source_entity, int *nr_queues) +@@ -1081,6 +1178,11 @@ int ipu7_isys_video_init(struct ipu7_isys_video *av) + + __ipu_isys_vidioc_try_fmt_vid_cap(av, &format); + av->pix_fmt = format.fmt.pix; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ av->reset = false; ++ av->skipframe = 0; ++ av->start_streaming = 0; ++#endif + + set_bit(V4L2_FL_USES_V4L2_FH, &av->vdev.flags); + video_set_drvdata(&av->vdev, av); +diff --git a/drivers/staging/media/ipu7/ipu7-isys-video.h b/drivers/staging/media/ipu7/ipu7-isys-video.h +index 1ac1787fab..e6d1da2b7b 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys-video.h ++++ b/drivers/staging/media/ipu7/ipu7-isys-video.h +@@ -53,6 +53,9 @@ struct ipu7_isys_stream { + struct mutex mutex; + struct media_entity *source_entity; + atomic_t sequence; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ int last_sequence; ++#endif + atomic_t buf_id; + unsigned int seq_index; + struct sequence_info seq[IPU_ISYS_MAX_PARALLEL_SOF]; +@@ -89,6 +92,11 @@ struct ipu7_isys_video { + unsigned int streaming; + u8 vc; + u8 dt; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ unsigned int reset; ++ unsigned int skipframe; ++ unsigned int start_streaming; ++#endif + }; + + #define ipu7_isys_queue_to_video(__aq) \ +diff --git a/drivers/staging/media/ipu7/ipu7-isys.c b/drivers/staging/media/ipu7/ipu7-isys.c +index cb2f49f3e0..cfb3989fe7 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-isys.c +@@ -540,6 +540,12 @@ static int isys_runtime_pm_suspend(struct device *dev) + isys->power = 0; + spin_unlock_irqrestore(&isys->power_lock, flags); + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ mutex_lock(&isys->reset_mutex); ++ isys->need_reset = false; ++ mutex_unlock(&isys->reset_mutex); ++ ++#endif + cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); + + ipu7_mmu_hw_cleanup(adev->mmu); +@@ -594,6 +600,9 @@ static void isys_remove(struct auxiliary_device *auxdev) + + mutex_destroy(&isys->stream_mutex); + mutex_destroy(&isys->mutex); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ mutex_destroy(&isys->reset_mutex); ++#endif + } + + static int alloc_fw_msg_bufs(struct ipu7_isys *isys, int amount) +@@ -738,6 +747,10 @@ static int isys_probe(struct auxiliary_device *auxdev, + + mutex_init(&isys->mutex); + mutex_init(&isys->stream_mutex); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ mutex_init(&isys->reset_mutex); ++ isys->state = 0; ++#endif + + spin_lock_init(&isys->listlock); + INIT_LIST_HEAD(&isys->framebuflist); +@@ -767,6 +780,9 @@ static int isys_probe(struct auxiliary_device *auxdev, + if (ret) + goto out_cleanup; + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ mutex_destroy(&isys->reset_mutex); ++#endif + ipu7_mmu_hw_cleanup(adev->mmu); + pm_runtime_put(&auxdev->dev); + +diff --git a/drivers/staging/media/ipu7/ipu7-isys.h b/drivers/staging/media/ipu7/ipu7-isys.h +index ef1ab1b42f..17d4d56301 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.h ++++ b/drivers/staging/media/ipu7/ipu7-isys.h +@@ -44,8 +44,16 @@ + #define IPU_ISYS_MAX_WIDTH 8160U + #define IPU_ISYS_MAX_HEIGHT 8190U + ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++#define RESET_STATE_IN_RESET 1U ++#define RESET_STATE_IN_STOP_STREAMING 2U ++ ++#endif + #define FW_CALL_TIMEOUT_JIFFIES \ + msecs_to_jiffies(IPU_LIB_CALL_TIMEOUT_MS) ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++#define FW_CALL_TIMEOUT_JIFFIES_RESET msecs_to_jiffies(200) ++#endif + + struct isys_fw_log { + struct mutex mutex; /* protect whole struct */ +@@ -68,6 +76,9 @@ struct isys_fw_log { + * @streams_lock: serialise access to streams + * @streams: streams per firmware stream ID + * @syscom: fw communication layer context ++ #ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ * @need_reset: Isys requires d0i0->i3 transition ++ #endif + * @ref_count: total number of callers fw open + * @mutex: serialise access isys video open/release related operations + * @stream_mutex: serialise stream start and stop, queueing requests +@@ -109,6 +120,11 @@ struct ipu7_isys { + + struct ipu7_insys_config *subsys_config; + dma_addr_t subsys_config_dma_addr; ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ struct mutex reset_mutex; ++ bool need_reset; ++ int state; ++#endif + }; + + struct isys_fw_msgs { +-- +2.43.0 + diff --git a/patch/v6.17_staging/0002-staging-add-enable-CONFIG_DEBUG_FS.patch b/patch/v6.17_staging/0002-staging-add-enable-CONFIG_DEBUG_FS.patch new file mode 100644 index 0000000..640c88a --- /dev/null +++ b/patch/v6.17_staging/0002-staging-add-enable-CONFIG_DEBUG_FS.patch @@ -0,0 +1,270 @@ +From 37fb8fad4900cda5007fbce4eb6acc53f74b92d5 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Mon, 20 Oct 2025 12:36:12 +0800 +Subject: [PATCH] patch: staging add enable CONFIG_DEBUG_FS + +Signed-off-by: linya14x +--- + drivers/staging/media/ipu7/ipu7-isys.c | 84 ++++++++++++++++++++++++++ + drivers/staging/media/ipu7/ipu7-isys.h | 7 +++ + drivers/staging/media/ipu7/ipu7.c | 60 ++++++++++++++++++ + drivers/staging/media/ipu7/ipu7.h | 3 + + 4 files changed, 154 insertions(+) + +diff --git a/drivers/staging/media/ipu7/ipu7-isys.c b/drivers/staging/media/ipu7/ipu7-isys.c +index cfb3989fe7..44ea4eef19 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-isys.c +@@ -9,6 +9,9 @@ + #include + #include + #include ++#ifdef CONFIG_DEBUG_FS ++#include ++#endif + #include + #include + #include +@@ -582,6 +585,10 @@ static void isys_remove(struct auxiliary_device *auxdev) + struct isys_fw_msgs *fwmsg, *safe; + struct ipu7_bus_device *adev = auxdev_to_adev(auxdev); + ++#ifdef CONFIG_DEBUG_FS ++ if (adev->isp->ipu7_dir) ++ debugfs_remove_recursive(isys->debugfsdir); ++#endif + for (int i = 0; i < IPU_ISYS_MAX_STREAMS; i++) + mutex_destroy(&isys->streams[i].mutex); + +@@ -605,6 +612,78 @@ static void isys_remove(struct auxiliary_device *auxdev) + #endif + } + ++#ifdef CONFIG_DEBUG_FS ++static ssize_t fwlog_read(struct file *file, char __user *userbuf, size_t size, ++ loff_t *pos) ++{ ++ struct ipu7_isys *isys = file->private_data; ++ struct isys_fw_log *fw_log = isys->fw_log; ++ struct device *dev = &isys->adev->auxdev.dev; ++ u32 log_size; ++ int ret = 0; ++ void *buf; ++ ++ if (!fw_log) ++ return 0; ++ ++ buf = kvzalloc(FW_LOG_BUF_SIZE, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ mutex_lock(&fw_log->mutex); ++ if (!fw_log->size) { ++ dev_warn(dev, "no available fw log\n"); ++ mutex_unlock(&fw_log->mutex); ++ goto free_and_return; ++ } ++ ++ if (fw_log->size > FW_LOG_BUF_SIZE) ++ log_size = FW_LOG_BUF_SIZE; ++ else ++ log_size = fw_log->size; ++ ++ memcpy(buf, fw_log->addr, log_size); ++ dev_info(dev, "copy %d bytes fw log to user...\n", log_size); ++ mutex_unlock(&fw_log->mutex); ++ ++ ret = simple_read_from_buffer(userbuf, size, pos, buf, ++ log_size); ++free_and_return: ++ kvfree(buf); ++ ++ return ret; ++} ++ ++static const struct file_operations isys_fw_log_fops = { ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .read = fwlog_read, ++ .llseek = default_llseek, ++}; ++ ++static int ipu7_isys_init_debugfs(struct ipu7_isys *isys) ++{ ++ struct dentry *file; ++ struct dentry *dir; ++ ++ dir = debugfs_create_dir("isys", isys->adev->isp->ipu7_dir); ++ if (IS_ERR(dir)) ++ return -ENOMEM; ++ ++ file = debugfs_create_file("fwlog", 0400, ++ dir, isys, &isys_fw_log_fops); ++ if (IS_ERR(file)) ++ goto err; ++ ++ isys->debugfsdir = dir; ++ ++ return 0; ++err: ++ debugfs_remove_recursive(dir); ++ return -ENOMEM; ++} ++#endif ++ + static int alloc_fw_msg_bufs(struct ipu7_isys *isys, int amount) + { + struct ipu7_bus_device *adev = isys->adev; +@@ -763,6 +842,11 @@ static int isys_probe(struct auxiliary_device *auxdev, + + isys_stream_init(isys); + ++#ifdef CONFIG_DEBUG_FS ++ /* Debug fs failure is not fatal. */ ++ ipu7_isys_init_debugfs(isys); ++#endif ++ + cpu_latency_qos_add_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); + ret = alloc_fw_msg_bufs(isys, 20); + if (ret < 0) +diff --git a/drivers/staging/media/ipu7/ipu7-isys.h b/drivers/staging/media/ipu7/ipu7-isys.h +index 17d4d56301..cd73754174 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.h ++++ b/drivers/staging/media/ipu7/ipu7-isys.h +@@ -25,6 +25,10 @@ + #include "ipu7-isys-csi2.h" + #include "ipu7-isys-video.h" + ++#ifdef CONFIG_DEBUG_FS ++struct dentry; ++ ++#endif + #define IPU_ISYS_ENTITY_PREFIX "Intel IPU7" + + /* FW support max 16 streams */ +@@ -103,6 +107,9 @@ struct ipu7_isys { + unsigned int ref_count; + unsigned int stream_opened; + ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *debugfsdir; ++#endif + struct mutex mutex; /* Serialise isys video open/release related */ + struct mutex stream_mutex; /* Stream start, stop, queueing reqs */ + +diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c +index 1b4f01db13..5857c4a4bd 100644 +--- a/drivers/staging/media/ipu7/ipu7.c ++++ b/drivers/staging/media/ipu7/ipu7.c +@@ -7,6 +7,9 @@ + #include + #include + #include ++#ifdef CONFIG_DEBUG_FS ++#include ++#endif + #include + #include + #include +@@ -2248,6 +2251,49 @@ void ipu7_dump_fw_error_log(const struct ipu7_bus_device *adev) + } + EXPORT_SYMBOL_NS_GPL(ipu7_dump_fw_error_log, "INTEL_IPU7"); + ++#ifdef CONFIG_DEBUG_FS ++static struct debugfs_blob_wrapper isys_fw_error; ++static struct debugfs_blob_wrapper psys_fw_error; ++ ++static int ipu7_init_debugfs(struct ipu7_device *isp) ++{ ++ struct dentry *file; ++ struct dentry *dir; ++ ++ dir = debugfs_create_dir(pci_name(isp->pdev), NULL); ++ if (!dir) ++ return -ENOMEM; ++ ++ isys_fw_error.data = &fw_error_log[IPU_IS]; ++ isys_fw_error.size = sizeof(fw_error_log[IPU_IS]); ++ file = debugfs_create_blob("is_fw_error", 0400, dir, &isys_fw_error); ++ if (!file) ++ goto err; ++ psys_fw_error.data = &fw_error_log[IPU_PS]; ++ psys_fw_error.size = sizeof(fw_error_log[IPU_PS]); ++ file = debugfs_create_blob("ps_fw_error", 0400, dir, &psys_fw_error); ++ if (!file) ++ goto err; ++ ++ isp->ipu7_dir = dir; ++ ++ return 0; ++err: ++ debugfs_remove_recursive(dir); ++ return -ENOMEM; ++} ++ ++static void ipu7_remove_debugfs(struct ipu7_device *isp) ++{ ++ /* ++ * Since isys and psys debugfs dir will be created under ipu root dir, ++ * mark its dentry to NULL to avoid duplicate removal. ++ */ ++ debugfs_remove_recursive(isp->ipu7_dir); ++ isp->ipu7_dir = NULL; ++} ++#endif /* CONFIG_DEBUG_FS */ ++ + static int ipu7_pci_config_setup(struct pci_dev *dev) + { + u16 pci_command; +@@ -2610,6 +2656,13 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + pm_runtime_put(&isp->psys->auxdev.dev); + } + ++#ifdef CONFIG_DEBUG_FS ++ ret = ipu7_init_debugfs(isp); ++ if (ret) { ++ dev_err_probe(dev, ret, "Failed to initialize debugfs\n"); ++ goto out_ipu_bus_del_devices; ++ } ++#endif + pm_runtime_put_noidle(dev); + pm_runtime_allow(dev); + +@@ -2622,6 +2675,10 @@ out_ipu_bus_del_devices: + ipu7_unmap_fw_code_region(isp->isys); + if (!IS_ERR_OR_NULL(isp->psys) && isp->psys->fw_sgt.nents) + ipu7_unmap_fw_code_region(isp->psys); ++#ifdef CONFIG_DEBUG_FS ++ if (!IS_ERR_OR_NULL(isp->fw_code_region)) ++ vfree(isp->fw_code_region); ++#endif + if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys->mmu)) + ipu7_mmu_cleanup(isp->psys->mmu); + if (!IS_ERR_OR_NULL(isp->isys) && !IS_ERR_OR_NULL(isp->isys->mmu)) +@@ -2640,6 +2697,9 @@ static void ipu7_pci_remove(struct pci_dev *pdev) + { + struct ipu7_device *isp = pci_get_drvdata(pdev); + ++#ifdef CONFIG_DEBUG_FS ++ ipu7_remove_debugfs(isp); ++#endif + if (!IS_ERR_OR_NULL(isp->isys) && isp->isys->fw_sgt.nents) + ipu7_unmap_fw_code_region(isp->isys); + if (!IS_ERR_OR_NULL(isp->psys) && isp->psys->fw_sgt.nents) +diff --git a/drivers/staging/media/ipu7/ipu7.h b/drivers/staging/media/ipu7/ipu7.h +index ac8ac06894..3b3ea5fb61 100644 +--- a/drivers/staging/media/ipu7/ipu7.h ++++ b/drivers/staging/media/ipu7/ipu7.h +@@ -81,6 +81,9 @@ struct ipu7_device { + + void __iomem *base; + void __iomem *pb_base; ++#ifdef CONFIG_DEBUG_FS ++ struct dentry *ipu7_dir; ++#endif + u8 hw_ver; + bool ipc_reinit; + bool secure_mode; +-- +2.43.0 + diff --git a/patch/v6.17_staging/0003-staging-add-enable-CONFIG_INTEL_IPU_ACPI.patch b/patch/v6.17_staging/0003-staging-add-enable-CONFIG_INTEL_IPU_ACPI.patch new file mode 100644 index 0000000..22e0123 --- /dev/null +++ b/patch/v6.17_staging/0003-staging-add-enable-CONFIG_INTEL_IPU_ACPI.patch @@ -0,0 +1,404 @@ +From cfe2cce760509c0731bb9d93c07edf9770ca4230 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 24 Oct 2025 12:16:13 +0800 +Subject: [PATCH] patch: staging add enable CONFIG_INTEL_IPU_ACPI + +Signed-off-by: linya14x +--- + drivers/staging/media/ipu7/ipu7-isys.c | 231 ++++++++++++++++++++++++- + drivers/staging/media/ipu7/ipu7-isys.h | 15 ++ + drivers/staging/media/ipu7/ipu7.c | 10 ++ + drivers/staging/media/ipu7/ipu7.h | 3 + + 4 files changed, 257 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/media/ipu7/ipu7-isys.c b/drivers/staging/media/ipu7/ipu7-isys.c +index 44ea4eef19..b71e2841de 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-isys.c +@@ -96,6 +96,126 @@ skip_unregister_subdev: + return ret; + } + ++struct isys_i2c_test { ++ u8 bus_nr; ++ u16 addr; ++ struct i2c_client *client; ++}; ++ ++static int isys_i2c_test(struct device *dev, void *priv) ++{ ++ struct i2c_client *client = i2c_verify_client(dev); ++ struct isys_i2c_test *test = priv; ++ ++ if (!client) ++ return 0; ++ ++ if (i2c_adapter_id(client->adapter) != test->bus_nr || ++ client->addr != test->addr) ++ return 0; ++ ++ test->client = client; ++ ++ return 0; ++} ++ ++static ++struct i2c_client *isys_find_i2c_subdev(struct i2c_adapter *adapter, ++ struct ipu7_isys_subdev_info *sd_info) ++{ ++ struct i2c_board_info *info = &sd_info->i2c.board_info; ++ struct isys_i2c_test test = { ++ .bus_nr = i2c_adapter_id(adapter), ++ .addr = info->addr, ++ }; ++ int ret; ++ ++ ret = i2c_for_each_dev(&test, isys_i2c_test); ++ if (ret || !test.client) ++ return NULL; ++ return test.client; ++} ++ ++static int isys_register_ext_subdev(struct ipu7_isys *isys, ++ struct ipu7_isys_subdev_info *sd_info) ++{ ++ struct device *dev = &isys->adev->auxdev.dev; ++ struct i2c_adapter *adapter; ++ struct v4l2_subdev *sd; ++ struct i2c_client *client; ++ int ret; ++ int bus; ++ ++ bus = sd_info->i2c.i2c_adapter_id; ++ adapter = i2c_get_adapter(bus); ++ if (!adapter) { ++ dev_warn(dev, "can't find adapter\n"); ++ return -ENOENT; ++ } ++ ++ dev_info(dev, "creating i2c subdev for %s (address %2.2x, bus %d)\n", ++ sd_info->i2c.board_info.type, sd_info->i2c.board_info.addr, ++ bus); ++ ++ if (sd_info->csi2) { ++ dev_info(dev, "sensor device on CSI port: %d\n", ++ sd_info->csi2->port); ++ if (sd_info->csi2->port >= isys->pdata->ipdata->csi2.nports || ++ !isys->csi2[sd_info->csi2->port].isys) { ++ dev_warn(dev, "invalid csi2 port %u\n", ++ sd_info->csi2->port); ++ ret = -EINVAL; ++ goto skip_put_adapter; ++ } ++ } else { ++ dev_info(dev, "No camera subdevice\n"); ++ } ++ ++ client = isys_find_i2c_subdev(adapter, sd_info); ++ if (client) { ++ dev_warn(dev, "Device exists\n"); ++#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) ++ /* TODO: remove i2c_unregister_device() */ ++ i2c_unregister_device(client); ++#else ++ ret = 0; ++ goto skip_put_adapter; ++#endif ++ } ++ ++ sd = v4l2_i2c_new_subdev_board(&isys->v4l2_dev, adapter, ++ &sd_info->i2c.board_info, NULL); ++ if (!sd) { ++ dev_warn(dev, "can't create new i2c subdev\n"); ++ ret = -EINVAL; ++ goto skip_put_adapter; ++ } ++ ++ if (!sd_info->csi2) ++ return 0; ++ ++ return isys_complete_ext_device_registration(isys, sd, sd_info->csi2); ++ ++skip_put_adapter: ++ i2c_put_adapter(adapter); ++ ++ return ret; ++} ++ ++static void isys_register_ext_subdevs(struct ipu7_isys *isys) ++{ ++ struct ipu7_isys_subdev_pdata *spdata = isys->pdata->spdata; ++ struct ipu7_isys_subdev_info **sd_info; ++ ++ if (!spdata) { ++ dev_info(&isys->adev->auxdev.dev, ++ "no subdevice info provided\n"); ++ return; ++ } ++ for (sd_info = spdata->subdevs; *sd_info; sd_info++) ++ isys_register_ext_subdev(isys, *sd_info); ++} ++ + static void isys_stream_init(struct ipu7_isys *isys) + { + unsigned int i; +@@ -142,6 +262,7 @@ static int isys_fw_log_init(struct ipu7_isys *isys) + return 0; + } + ++#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) + /* The .bound() notifier callback when a match is found */ + static int isys_notifier_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, +@@ -260,6 +381,7 @@ static void isys_notifier_cleanup(struct ipu7_isys *isys) + v4l2_async_nf_unregister(&isys->notifier); + v4l2_async_nf_cleanup(&isys->notifier); + } ++#endif + + static void isys_unregister_video_devices(struct ipu7_isys *isys) + { +@@ -374,6 +496,73 @@ static int isys_csi2_create_media_links(struct ipu7_isys *isys) + return 0; + } + ++#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) ++static int isys_register_devices(struct ipu7_isys *isys) ++{ ++ struct device *dev = &isys->adev->auxdev.dev; ++ struct pci_dev *pdev = isys->adev->isp->pdev; ++ int ret; ++ ++ media_device_pci_init(&isys->media_dev, ++ pdev, IPU_MEDIA_DEV_MODEL_NAME); ++ ++ strscpy(isys->v4l2_dev.name, isys->media_dev.model, ++ sizeof(isys->v4l2_dev.name)); ++ ++ ret = media_device_register(&isys->media_dev); ++ if (ret < 0) ++ goto out_media_device_unregister; ++ ++ isys->v4l2_dev.mdev = &isys->media_dev; ++ isys->v4l2_dev.ctrl_handler = NULL; ++ ++ ret = v4l2_device_register(dev, &isys->v4l2_dev); ++ if (ret < 0) ++ goto out_media_device_unregister; ++ ++ ret = isys_register_video_devices(isys); ++ if (ret) ++ goto out_v4l2_device_unregister; ++ ++ ret = isys_csi2_register_subdevices(isys); ++ if (ret) ++ goto out_video_unregister_device; ++ ++ ret = isys_csi2_create_media_links(isys); ++ if (ret) ++ goto out_csi2_unregister_subdevices; ++ ++ if (!isys->pdata->spdata) { ++ ret = isys_notifier_init(isys); ++ if (ret) ++ goto out_csi2_unregister_subdevices; ++ } else { ++ isys_register_ext_subdevs(isys); ++ ret = v4l2_device_register_subdev_nodes(&isys->v4l2_dev); ++ if (ret) ++ goto out_csi2_unregister_subdevices; ++ } ++ ++ return 0; ++ ++out_csi2_unregister_subdevices: ++ isys_csi2_unregister_subdevices(isys); ++ ++out_video_unregister_device: ++ isys_unregister_video_devices(isys); ++ ++out_v4l2_device_unregister: ++ v4l2_device_unregister(&isys->v4l2_dev); ++ ++out_media_device_unregister: ++ media_device_unregister(&isys->media_dev); ++ media_device_cleanup(&isys->media_dev); ++ ++ dev_err(dev, "failed to register isys devices\n"); ++ ++ return ret; ++} ++#else + static int isys_register_devices(struct ipu7_isys *isys) + { + struct device *dev = &isys->adev->auxdev.dev; +@@ -409,7 +598,8 @@ static int isys_register_devices(struct ipu7_isys *isys) + if (ret) + goto out_csi2_unregister_subdevices; + +- ret = isys_notifier_init(isys); ++ isys_register_ext_subdevs(isys); ++ ret = v4l2_device_register_subdev_nodes(&isys->v4l2_dev); + if (ret) + goto out_csi2_unregister_subdevices; + +@@ -432,6 +622,7 @@ out_media_device_unregister: + + return ret; + } ++#endif + + static void isys_unregister_devices(struct ipu7_isys *isys) + { +@@ -579,6 +770,7 @@ static const struct dev_pm_ops isys_pm_ops = { + .resume = isys_resume, + }; + ++#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) + static void isys_remove(struct auxiliary_device *auxdev) + { + struct ipu7_isys *isys = dev_get_drvdata(&auxdev->dev); +@@ -600,7 +792,9 @@ static void isys_remove(struct auxiliary_device *auxdev) + ipu7_dma_free(adev, sizeof(struct isys_fw_msgs), + fwmsg, fwmsg->dma_addr, 0); + +- isys_notifier_cleanup(isys); ++ if (!isys->pdata->spdata) ++ isys_notifier_cleanup(isys); ++ + isys_unregister_devices(isys); + + cpu_latency_qos_remove_request(&isys->pm_qos); +@@ -611,6 +805,39 @@ static void isys_remove(struct auxiliary_device *auxdev) + mutex_destroy(&isys->reset_mutex); + #endif + } ++#else ++static void isys_remove(struct auxiliary_device *auxdev) ++{ ++ struct ipu7_isys *isys = dev_get_drvdata(&auxdev->dev); ++ struct isys_fw_msgs *fwmsg, *safe; ++ struct ipu7_bus_device *adev = auxdev_to_adev(auxdev); ++ ++#ifdef CONFIG_DEBUG_FS ++ if (adev->isp->ipu7_dir) ++ debugfs_remove_recursive(isys->debugfsdir); ++#endif ++ for (int i = 0; i < IPU_ISYS_MAX_STREAMS; i++) ++ mutex_destroy(&isys->streams[i].mutex); ++ ++ list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head) ++ ipu7_dma_free(adev, sizeof(struct isys_fw_msgs), ++ fwmsg, fwmsg->dma_addr, 0); ++ ++ list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head) ++ ipu7_dma_free(adev, sizeof(struct isys_fw_msgs), ++ fwmsg, fwmsg->dma_addr, 0); ++ ++ isys_unregister_devices(isys); ++ ++ cpu_latency_qos_remove_request(&isys->pm_qos); ++ ++ mutex_destroy(&isys->stream_mutex); ++ mutex_destroy(&isys->mutex); ++#ifdef CONFIG_VIDEO_INTEL_IPU7_ISYS_RESET ++ mutex_destroy(&isys->reset_mutex); ++#endif ++} ++#endif + + #ifdef CONFIG_DEBUG_FS + static ssize_t fwlog_read(struct file *file, char __user *userbuf, size_t size, +diff --git a/drivers/staging/media/ipu7/ipu7-isys.h b/drivers/staging/media/ipu7/ipu7-isys.h +index cd73754174..2e45258bb6 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.h ++++ b/drivers/staging/media/ipu7/ipu7-isys.h +@@ -150,6 +150,21 @@ struct ipu7_isys_csi2_config { + enum v4l2_mbus_type bus_type; + }; + ++struct ipu7_isys_subdev_i2c_info { ++ struct i2c_board_info board_info; ++ int i2c_adapter_id; ++ char i2c_adapter_bdf[32]; ++}; ++ ++struct ipu7_isys_subdev_info { ++ struct ipu7_isys_csi2_config *csi2; ++ struct ipu7_isys_subdev_i2c_info i2c; ++}; ++ ++struct ipu7_isys_subdev_pdata { ++ struct ipu7_isys_subdev_info **subdevs; ++}; ++ + struct sensor_async_sd { + struct v4l2_async_connection asc; + struct ipu7_isys_csi2_config csi2; +diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c +index 5857c4a4bd..e4dab55fbb 100644 +--- a/drivers/staging/media/ipu7/ipu7.c ++++ b/drivers/staging/media/ipu7/ipu7.c +@@ -40,6 +40,10 @@ + #include "ipu7-mmu.h" + #include "ipu7-platform-regs.h" + ++#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) ++#include ++ ++#endif + #define IPU_PCI_BAR 0 + #define IPU_PCI_PBBAR 4 + +@@ -2130,6 +2134,7 @@ static int ipu7_isys_check_fwnode_graph(struct fwnode_handle *fwnode) + static struct ipu7_bus_device * + ipu7_isys_init(struct pci_dev *pdev, struct device *parent, + const struct ipu_buttress_ctrl *ctrl, void __iomem *base, ++ struct ipu7_isys_subdev_pdata *spdata, + const struct ipu_isys_internal_pdata *ipdata, + unsigned int nr) + { +@@ -2160,6 +2165,7 @@ ipu7_isys_init(struct pci_dev *pdev, struct device *parent, + + pdata->base = base; + pdata->ipdata = ipdata; ++ pdata->spdata = spdata; + + isys_adev = ipu7_bus_initialize_device(pdev, parent, pdata, ctrl, + IPU_ISYS_NAME); +@@ -2588,7 +2594,11 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + goto out_ipu_bus_del_devices; + } + ++#if IS_ENABLED(CONFIG_INTEL_IPU_ACPI) ++ ipu_get_acpi_devices_new(&dev->platform_data); ++#endif + isp->isys = ipu7_isys_init(pdev, dev, isys_ctrl, isys_base, ++ dev->platform_data, + isys_ipdata, 0); + if (IS_ERR(isp->isys)) { + ret = PTR_ERR(isp->isys); +diff --git a/drivers/staging/media/ipu7/ipu7.h b/drivers/staging/media/ipu7/ipu7.h +index 3b3ea5fb61..21988ce41a 100644 +--- a/drivers/staging/media/ipu7/ipu7.h ++++ b/drivers/staging/media/ipu7/ipu7.h +@@ -144,6 +144,8 @@ struct ipu7_device { + /* Currently chosen arbitration mechanism for VC1 */ + #define IPU_BTRS_ARB_STALL_MODE_VC1 IPU_BTRS_ARB_MODE_TYPE_REARB + ++struct ipu7_isys_subdev_pdata; ++ + /* One L2 entry maps 1024 L1 entries and one L1 entry per page */ + #define IPU_MMUV2_L2_RANGE (1024 * PAGE_SIZE) + /* Max L2 blocks per stream */ +@@ -226,6 +228,7 @@ struct ipu_isys_internal_pdata { + struct ipu7_isys_pdata { + void __iomem *base; + const struct ipu_isys_internal_pdata *ipdata; ++ struct ipu7_isys_subdev_pdata *spdata; + }; + + struct ipu_psys_internal_pdata { +-- +2.43.0 + diff --git a/patch/v6.17_staging/0004-staging-add-patch-for-use-DPHY-as-the-default-.patch b/patch/v6.17_staging/0004-staging-add-patch-for-use-DPHY-as-the-default-.patch new file mode 100644 index 0000000..3d64133 --- /dev/null +++ b/patch/v6.17_staging/0004-staging-add-patch-for-use-DPHY-as-the-default-.patch @@ -0,0 +1,32 @@ +From dfe5a9b11231a0f77cdaef579ce56a695658a9ef Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 24 Oct 2025 12:44:25 +0800 +Subject: [PATCH] patch: staging add patch for use DPHY as the default phy mode + +Signed-off-by: Bingbu Cao +Signed-off-by: linya14x +--- + drivers/staging/media/ipu7/ipu7-isys.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/ipu7/ipu7-isys.c b/drivers/staging/media/ipu7/ipu7-isys.c +index 946e601c8a..4282077109 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-isys.c +@@ -84,10 +84,10 @@ isys_complete_ext_device_registration(struct ipu7_isys *isys, + } + + isys->csi2[csi2->port].nlanes = csi2->nlanes; +- if (csi2->bus_type == V4L2_MBUS_CSI2_DPHY) +- isys->csi2[csi2->port].phy_mode = PHY_MODE_DPHY; +- else ++ if (csi2->bus_type == V4L2_MBUS_CSI2_CPHY) + isys->csi2[csi2->port].phy_mode = PHY_MODE_CPHY; ++ else ++ isys->csi2[csi2->port].phy_mode = PHY_MODE_DPHY; + + return 0; + +-- +2.43.0 + diff --git a/patch/v6.17_staging/0005-staging-add-patch-for-increase-fw-msg-bufs-ini.patch b/patch/v6.17_staging/0005-staging-add-patch-for-increase-fw-msg-bufs-ini.patch new file mode 100644 index 0000000..95c5a3b --- /dev/null +++ b/patch/v6.17_staging/0005-staging-add-patch-for-increase-fw-msg-bufs-ini.patch @@ -0,0 +1,29 @@ +From ca666f9cf3084a9d3e25841d24990f6b82e473e8 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 24 Oct 2025 12:47:37 +0800 +Subject: [PATCH] patch: staging add patch for increase fw msg bufs initial + amount to 40 + +Change-Id: 09d80b512367371db6bbad83d3eaaab17dadf742 +Signed-off-by: hepengpx +Signed-off-by: linya14x +--- + drivers/staging/media/ipu7/ipu7-isys.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/media/ipu7/ipu7-isys.c b/drivers/staging/media/ipu7/ipu7-isys.c +index 4282077109..10857a7206 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-isys.c +@@ -1075,7 +1075,7 @@ static int isys_probe(struct auxiliary_device *auxdev, + #endif + + cpu_latency_qos_add_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); +- ret = alloc_fw_msg_bufs(isys, 20); ++ ret = alloc_fw_msg_bufs(isys, 40); + if (ret < 0) + goto out_cleanup_isys; + +-- +2.43.0 + diff --git a/patch/v6.17_staging/0006-staging-add-fixup-some-PCI-probe-and-release-i.patch b/patch/v6.17_staging/0006-staging-add-fixup-some-PCI-probe-and-release-i.patch new file mode 100644 index 0000000..6a0ae5f --- /dev/null +++ b/patch/v6.17_staging/0006-staging-add-fixup-some-PCI-probe-and-release-i.patch @@ -0,0 +1,98 @@ +From 7b6f4d656c37ca7b0ee9734c991932be19ebe315 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 24 Oct 2025 14:58:47 +0800 +Subject: [PATCH] patch: staging add fixup some PCI probe and release issues + +Signed-off-by: Bingbu Cao +Signed-off-by: linya14x + +Change-Id: Iee60c79f422d1ebbf017da2615e5775cc48a3900 +--- + drivers/staging/media/ipu7/ipu7.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/media/ipu7/ipu7.c b/drivers/staging/media/ipu7/ipu7.c +index e4dab55fbb..0337d9d74b 100644 +--- a/drivers/staging/media/ipu7/ipu7.c ++++ b/drivers/staging/media/ipu7/ipu7.c +@@ -2300,20 +2300,13 @@ static void ipu7_remove_debugfs(struct ipu7_device *isp) + } + #endif /* CONFIG_DEBUG_FS */ + +-static int ipu7_pci_config_setup(struct pci_dev *dev) ++static void ipu7_pci_config_setup(struct pci_dev *dev) + { + u16 pci_command; +- int ret; + + pci_read_config_word(dev, PCI_COMMAND, &pci_command); + pci_command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_word(dev, PCI_COMMAND, pci_command); +- +- ret = pci_enable_msi(dev); +- if (ret) +- dev_err(&dev->dev, "Failed to enable msi (%d)\n", ret); +- +- return ret; + } + + static int ipu7_map_fw_code_region(struct ipu7_bus_device *sys, +@@ -2487,7 +2480,6 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (!isp) + return -ENOMEM; + +- dev_set_name(dev, "intel-ipu7"); + isp->pdev = pdev; + INIT_LIST_HEAD(&isp->devices); + +@@ -2562,13 +2554,15 @@ static int ipu7_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) + + dma_set_max_seg_size(dev, UINT_MAX); + +- ret = ipu7_pci_config_setup(pdev); +- if (ret) +- return ret; ++ ipu7_pci_config_setup(pdev); ++ ++ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); ++ if (ret < 0) ++ return dev_err_probe(dev, ret, "Failed to alloc irq vector\n"); + + ret = ipu_buttress_init(isp); + if (ret) +- return ret; ++ goto pci_irq_free; + + dev_info(dev, "firmware cpd file: %s\n", isp->cpd_fw_name); + +@@ -2699,6 +2693,8 @@ out_ipu_bus_del_devices: + release_firmware(isp->cpd_fw); + buttress_exit: + ipu_buttress_exit(isp); ++pci_irq_free: ++ pci_free_irq_vectors(pdev); + + return ret; + } +@@ -2718,6 +2714,9 @@ static void ipu7_pci_remove(struct pci_dev *pdev) + if (!IS_ERR_OR_NULL(isp->fw_code_region)) + vfree(isp->fw_code_region); + ++ ipu7_mmu_cleanup(isp->isys->mmu); ++ ipu7_mmu_cleanup(isp->psys->mmu); ++ + ipu7_bus_del_devices(pdev); + + pm_runtime_forbid(&pdev->dev); +@@ -2727,8 +2726,6 @@ static void ipu7_pci_remove(struct pci_dev *pdev) + + release_firmware(isp->cpd_fw); + +- ipu7_mmu_cleanup(isp->psys->mmu); +- ipu7_mmu_cleanup(isp->isys->mmu); + } + + static void ipu7_pci_reset_prepare(struct pci_dev *pdev) +-- +2.43.0 + diff --git a/patch/v6.17_staging/0007-staging-add-pacth-for-ipu7-Kconfig-Makefile.patch b/patch/v6.17_staging/0007-staging-add-pacth-for-ipu7-Kconfig-Makefile.patch new file mode 100644 index 0000000..8f7c1dc --- /dev/null +++ b/patch/v6.17_staging/0007-staging-add-pacth-for-ipu7-Kconfig-Makefile.patch @@ -0,0 +1,79 @@ +From 412dd7088d21d21e95f7fa2ffda6497abcd64feb Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 24 Oct 2025 15:39:28 +0800 +Subject: [PATCH] patch: staging add pacth for ipu7 Kconfig Makefile + +Support kernel v6.10 + +Due to change "kbuild: use $(src) instead of $(srctree)/$(src) for +source directory" at https://lore.kernel.org/lkml/20240416121838. +95427-5-masahiroy@kernel.org/, the old include paths in Makefile +can't work on kernel v6.10. To keep compatible with < v6.10 kernel, +add another check in Makefile. +Signed-off-by: linya14x + +Change-Id: I5975ee086d25cdf62ed1ee66f892ec9805695a25 +Signed-off-by: Hao Yao +--- + drivers/staging/media/ipu7/Kconfig | 11 ++++++++--- + drivers/staging/media/ipu7/Makefile | 11 +++++++++++ + 2 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/media/ipu7/Kconfig b/drivers/staging/media/ipu7/Kconfig +index c4eee7c3e6..0a6e68c763 100644 +--- a/drivers/staging/media/ipu7/Kconfig ++++ b/drivers/staging/media/ipu7/Kconfig +@@ -4,7 +4,12 @@ config VIDEO_INTEL_IPU7 + depends on VIDEO_DEV + depends on X86 && HAS_DMA + depends on IPU_BRIDGE || !IPU_BRIDGE +- depends on PCI ++ # ++ # This driver incorrectly tries to override the dma_ops. It should ++ # never have done that, but for now keep it working on architectures ++ # that use dma ops ++ # ++ depends on ARCH_HAS_DMA_OPS + select AUXILIARY_BUS + select IOMMU_IOVA + select VIDEO_V4L2_SUBDEV_API +@@ -15,8 +20,8 @@ config VIDEO_INTEL_IPU7 + This is the 7th Gen Intel Image Processing Unit, found in Intel SoCs + and used for capturing images and video from camera sensors. + +- To compile this driver, say Y here! It contains 2 modules - +- intel_ipu7 and intel_ipu7_isys. ++ To compile this driver, say Y here! It contains 3 modules - ++ intel_ipu7, intel_ipu7_isys and intel_ipu7_psys. + + config VIDEO_INTEL_IPU7_ISYS_RESET + bool "IPU7 ISYS RESET" +diff --git a/drivers/staging/media/ipu7/Makefile b/drivers/staging/media/ipu7/Makefile +index 6d2aec219e..3c35ca5664 100644 +--- a/drivers/staging/media/ipu7/Makefile ++++ b/drivers/staging/media/ipu7/Makefile +@@ -1,6 +1,13 @@ + # SPDX-License-Identifier: GPL-2.0 + # Copyright (c) 2017 - 2025 Intel Corporation. + ++is_kernel_lt_6_10 = $(shell if [ $$(printf "6.10\n$(KERNELVERSION)" | sort -V | head -n1) != "6.10" ]; then echo 1; fi) ++ifeq ($(is_kernel_lt_6_10), 1) ++ifneq ($(EXTERNAL_BUILD), 1) ++src := $(srctree)/$(src) ++endif ++endif ++ + intel-ipu7-objs += ipu7.o \ + ipu7-bus.o \ + ipu7-dma.o \ +@@ -21,3 +28,7 @@ intel-ipu7-isys-objs += ipu7-isys.o \ + ipu7-isys-subdev.o + + obj-$(CONFIG_VIDEO_INTEL_IPU7) += intel-ipu7-isys.o ++ ++obj-$(CONFIG_VIDEO_INTEL_IPU7) += psys/ ++ ++ccflags-y += -I$(src)/ +-- +2.43.0 + diff --git a/patch/v6.17_staging/0008-staging-add-Update-firmware-ABI-version.patch b/patch/v6.17_staging/0008-staging-add-Update-firmware-ABI-version.patch new file mode 100644 index 0000000..cdb3bf1 --- /dev/null +++ b/patch/v6.17_staging/0008-staging-add-Update-firmware-ABI-version.patch @@ -0,0 +1,145 @@ +From 0719c0526372c9d710f48b21c18610d03253b5f5 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Fri, 14 Nov 2025 18:41:08 +0800 +Subject: [PATCH] media: ipu: Update firmware ABI version to + 1.2.1.20251028_225604 + +media: ipu7: Workaround for FW breaking ABI compatibility +commit-id: ab9874f2747fd6af6cee621b05341f18d6212437 +commit-id: c3b8dc8ad76895b6a9f17e705442ca19de05e76c +Signed-off-by: Hao Yao +Signed-off-by: linya14x +--- + .../staging/media/ipu7/abi/ipu7_fw_boot_abi.h | 1 + + .../staging/media/ipu7/abi/ipu7_fw_isys_abi.h | 29 +++++++++++++++++-- + .../staging/media/ipu7/abi/ipu7_fw_msg_abi.h | 2 +- + drivers/staging/media/ipu7/ipu7-fw-isys.c | 23 ++++++++++++++- + 4 files changed, 50 insertions(+), 5 deletions(-) + +diff --git a/drivers/staging/media/ipu7/abi/ipu7_fw_boot_abi.h b/drivers/staging/media/ipu7/abi/ipu7_fw_boot_abi.h +index a1519c4fe6..4ce304f54e 100644 +--- a/drivers/staging/media/ipu7/abi/ipu7_fw_boot_abi.h ++++ b/drivers/staging/media/ipu7/abi/ipu7_fw_boot_abi.h +@@ -153,6 +153,7 @@ enum ia_gofo_boot_state { + IA_GOFO_FW_BOOT_STATE_CRIT_MPU_CONFIG_FAILURE = 0xdead1013U, + IA_GOFO_FW_BOOT_STATE_CRIT_SHARED_BUFFER_FAILURE = 0xdead1014U, + IA_GOFO_FW_BOOT_STATE_CRIT_CMEM_FAILURE = 0xdead1015U, ++ IA_GOFO_FW_BOOT_STATE_CRIT_SYSCOM_CONTEXT_FAILURE = 0xDEAD1016U, + IA_GOFO_FW_BOOT_STATE_SHUTDOWN_CMD = 0x57a7f001U, + IA_GOFO_FW_BOOT_STATE_SHUTDOWN_START = 0x57a7e200U, + IA_GOFO_FW_BOOT_STATE_INACTIVE = 0x57a7e300U, +diff --git a/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h b/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h +index 45db85eb13..171b69c8c8 100644 +--- a/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h ++++ b/drivers/staging/media/ipu7/abi/ipu7_fw_isys_abi.h +@@ -47,7 +47,6 @@ enum ipu7_insys_resp_type { + IPU_INSYS_RESP_TYPE_FRAME_EOF = 8, + IPU_INSYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE = 9, + IPU_INSYS_RESP_TYPE_STREAM_CAPTURE_DONE = 10, +- IPU_INSYS_RESP_TYPE_PWM_IRQ = 11, + N_IPU_INSYS_RESP_TYPE + }; + +@@ -201,7 +200,8 @@ enum ipu7_insys_mipi_dt_rename_mode { + enum ipu7_insys_output_link_dest { + IPU_INSYS_OUTPUT_LINK_DEST_MEM = 0, + IPU_INSYS_OUTPUT_LINK_DEST_PSYS = 1, +- IPU_INSYS_OUTPUT_LINK_DEST_IPU_EXTERNAL = 2 ++ IPU_INSYS_OUTPUT_LINK_DEST_IPU_EXTERNAL = 2, ++ N_IPU_INSYS_OUTPUT_LINK_DEST + }; + + enum ipu7_insys_dpcm_type { +@@ -220,9 +220,12 @@ enum ipu7_insys_dpcm_predictor { + + enum ipu7_insys_send_queue_token_flag { + IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_NONE = 0, +- IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_FLUSH_FORCE = 1 ++ IPU_INSYS_SEND_QUEUE_TOKEN_FLAG_FLUSH_FORCE = 1, ++ N_IPU_INSYS_SEND_QUEUE_TOKEN_FLAG + }; + ++#define IPU_INSYS_MIPI_FRAME_NUMBER_DONT_CARE UINT16_MAX ++ + #pragma pack(push, 1) + struct ipu7_insys_resolution { + u32 width; +@@ -349,6 +352,26 @@ struct ipu7_insys_buffset { + }; + + struct ipu7_insys_resp { ++ u64 buf_id; ++ struct ipu7_insys_capture_output_pin_payload pin; ++ struct ia_gofo_msg_err error_info; ++ u32 timestamp[2]; ++ u16 mipi_fn; ++ u8 type; ++ u8 msg_link_streaming_mode; ++ u8 stream_id; ++ u8 pin_id; ++ u8 frame_id; ++ u8 skip_frame; ++}; ++ ++/** ++ * TODO: Revert this change after firmware ABI fixed. ++ * This is an internal workaround. ++ * IPU7.5 firmware changed its ABI and breaks ++ * compatibility with IPU7 Lunar Lake. ++ */ ++struct ipu7_insys_legacy_resp { + u64 buf_id; + struct ipu7_insys_capture_output_pin_payload pin; + struct ia_gofo_msg_err error_info; +diff --git a/drivers/staging/media/ipu7/abi/ipu7_fw_msg_abi.h b/drivers/staging/media/ipu7/abi/ipu7_fw_msg_abi.h +index 8a78dd0936..1319f0eb63 100644 +--- a/drivers/staging/media/ipu7/abi/ipu7_fw_msg_abi.h ++++ b/drivers/staging/media/ipu7/abi/ipu7_fw_msg_abi.h +@@ -217,7 +217,7 @@ struct ipu7_msg_task { + u8 frag_id; + u8 req_done_msg; + u8 req_done_irq; +- u8 reserved[1]; ++ u8 disable_save; + ipu7_msg_teb_t payload_reuse_bm; + ia_gofo_addr_t term_buffers[IPU_MSG_MAX_NODE_TERMS]; + }; +diff --git a/drivers/staging/media/ipu7/ipu7-fw-isys.c b/drivers/staging/media/ipu7/ipu7-fw-isys.c +index 2958e39a35..26704c6fad 100644 +--- a/drivers/staging/media/ipu7/ipu7-fw-isys.c ++++ b/drivers/staging/media/ipu7/ipu7-fw-isys.c +@@ -195,9 +195,30 @@ int ipu7_fw_isys_close(struct ipu7_isys *isys) + + struct ipu7_insys_resp *ipu7_fw_isys_get_resp(struct ipu7_isys *isys) + { +- return (struct ipu7_insys_resp *) ++ /** ++ * TODO: Revert this change after firmware ABI fixed. ++ * This is an internal workaround. ++ * IPU7.5 firmware changed its ABI and breaks ++ * compatibility with IPU7 Lunar Lake. ++ */ ++ struct ipu7_insys_resp *resp = + ipu7_syscom_get_token(isys->adev->syscom, + IPU_INSYS_OUTPUT_MSG_QUEUE); ++ ++ if (resp && isys->adev->isp->hw_ver == IPU_VER_7) { ++ struct ipu7_insys_legacy_resp lnl_resp; ++ ++ memcpy(&lnl_resp, resp, sizeof(struct ipu7_insys_resp)); ++ resp->mipi_fn = 0; ++ resp->type = lnl_resp.type; ++ resp->msg_link_streaming_mode = lnl_resp.msg_link_streaming_mode; ++ resp->stream_id = lnl_resp.stream_id; ++ resp->pin_id = lnl_resp.pin_id; ++ resp->frame_id = lnl_resp.frame_id; ++ resp->skip_frame = lnl_resp.skip_frame; ++ } ++ ++ return resp; + } + + void ipu7_fw_isys_put_resp(struct ipu7_isys *isys) +-- +2.43.0 + diff --git a/patch/v6.17_staging/0009-INT3472-Support-LT6911GXD.patch b/patch/v6.17_staging/0009-INT3472-Support-LT6911GXD.patch new file mode 100644 index 0000000..4732a4c --- /dev/null +++ b/patch/v6.17_staging/0009-INT3472-Support-LT6911GXD.patch @@ -0,0 +1,58 @@ +From 342e6971338dd46ab022db76764efa490d97508d Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Sat, 1 Nov 2025 17:10:48 +0800 +Subject: [PATCH] INT3472: Support LT6911GXD + +Signed-off-by: linya14x +--- + drivers/platform/x86/intel/int3472/discrete.c | 7 ++++++- + include/linux/platform_data/x86/int3472.h | 1 + + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel/int3472/discrete.c b/drivers/platform/x86/intel/int3472/discrete.c +index 4c0aed6e62..cdbb3a7b16 100644 +--- a/drivers/platform/x86/intel/int3472/discrete.c ++++ b/drivers/platform/x86/intel/int3472/discrete.c +@@ -177,6 +177,10 @@ static void int3472_get_con_id_and_polarity(struct int3472_discrete_device *int3 + } + + switch (*type) { ++ case INT3472_GPIO_TYPE_HOTPLUG_DETECT: ++ *con_id = "hpd"; ++ *gpio_flags = GPIO_ACTIVE_HIGH; ++ break; + case INT3472_GPIO_TYPE_RESET: + *con_id = "reset"; + *gpio_flags = GPIO_ACTIVE_LOW; +@@ -292,6 +296,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, + switch (type) { + case INT3472_GPIO_TYPE_RESET: + case INT3472_GPIO_TYPE_POWERDOWN: ++ case INT3472_GPIO_TYPE_HOTPLUG_DETECT: + ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, con_id, gpio_flags); + if (ret) + err_msg = "Failed to map GPIO pin to sensor\n"; +@@ -430,7 +435,7 @@ static int skl_int3472_discrete_probe(struct platform_device *pdev) + return ret; + } + +- if (cldb.control_logic_type != 1) { ++ if (cldb.control_logic_type != 1 && cldb.control_logic_type != 5) { + dev_err(&pdev->dev, "Unsupported control logic type %u\n", + cldb.control_logic_type); + return -EINVAL; +diff --git a/include/linux/platform_data/x86/int3472.h b/include/linux/platform_data/x86/int3472.h +index 78276a11c4..1571e9157f 100644 +--- a/include/linux/platform_data/x86/int3472.h ++++ b/include/linux/platform_data/x86/int3472.h +@@ -27,6 +27,7 @@ + #define INT3472_GPIO_TYPE_CLK_ENABLE 0x0c + #define INT3472_GPIO_TYPE_PRIVACY_LED 0x0d + #define INT3472_GPIO_TYPE_HANDSHAKE 0x12 ++#define INT3472_GPIO_TYPE_HOTPLUG_DETECT 0x13 + + #define INT3472_PDEV_MAX_NAME_LEN 23 + #define INT3472_MAX_SENSOR_GPIOS 3 +-- +2.43.0 + diff --git a/patch/v6.17_staging/0010-media-i2c-add-support-for-lt6911gxd.patch b/patch/v6.17_staging/0010-media-i2c-add-support-for-lt6911gxd.patch new file mode 100644 index 0000000..34d64ca --- /dev/null +++ b/patch/v6.17_staging/0010-media-i2c-add-support-for-lt6911gxd.patch @@ -0,0 +1,45 @@ +From 53209b07b5b6d663c4b13e94f255b2b272ea2e03 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Sat, 25 Oct 2025 16:30:08 +0800 +Subject: [PATCH] media: i2c: add support for lt6911gxd + +Signed-off-by: linya14x +--- + drivers/media/i2c/Kconfig | 11 +++++++++++ + drivers/media/i2c/Makefile | 1 + + 2 files changed, 12 insertions(+) + +diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig +index 6237fe804a..6dccc8e58d 100644 +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -267,6 +267,17 @@ config VIDEO_IMX415 + To compile this driver as a module, choose M here: the + module will be called imx415. + ++config VIDEO_LT6911GXD ++ tristate "Lontium LT6911GXD decoder" ++ depends on ACPI || COMPILE_TEST ++ select V4L2_CCI_I2C ++ help ++ This is a Video4Linux2 sensor-level driver for the Lontium ++ LT6911GXD HDMI to MIPI CSI-2 bridge. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called lt6911gxd. ++ + config VIDEO_MAX9271_LIB + tristate + +diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile +index 5873d29433..2fbdd4c181 100644 +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -162,3 +162,4 @@ obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o + obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o + obj-$(CONFIG_VIDEO_WM8739) += wm8739.o + obj-$(CONFIG_VIDEO_WM8775) += wm8775.o ++obj-$(CONFIG_VIDEO_LT6911GXD) += lt6911gxd.o +-- +2.43.0 + diff --git a/patch/v6.17_staging/0011-media-pci-enable-lt6911gxd-in-ipu-bridge.patch b/patch/v6.17_staging/0011-media-pci-enable-lt6911gxd-in-ipu-bridge.patch new file mode 100644 index 0000000..857cb99 --- /dev/null +++ b/patch/v6.17_staging/0011-media-pci-enable-lt6911gxd-in-ipu-bridge.patch @@ -0,0 +1,26 @@ +From 320ed1876280472444fb425c28989b67e028e971 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Sat, 6 Sep 2025 17:14:52 +0800 +Subject: [PATCH] media: pci: enable lt6911gxd in ipu-bridge + +Signed-off-by: linya14x +--- + drivers/media/pci/intel/ipu-bridge.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c +index 4e579352ab..e58b354ad9 100644 +--- a/drivers/media/pci/intel/ipu-bridge.c ++++ b/drivers/media/pci/intel/ipu-bridge.c +@@ -92,6 +92,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { + IPU_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000), + /* Toshiba T4KA3 */ + IPU_SENSOR_CONFIG("XMCC0003", 1, 321468000), ++ /* Lontium lt6911gxd */ ++ IPU_SENSOR_CONFIG("INTC1124", 0), + }; + + static const struct ipu_property_names prop_names = { +-- +2.43.0 + diff --git a/patch/v6.17_staging/0012-ipu-bridge-add-CPHY-support.patch b/patch/v6.17_staging/0012-ipu-bridge-add-CPHY-support.patch new file mode 100644 index 0000000..7630f50 --- /dev/null +++ b/patch/v6.17_staging/0012-ipu-bridge-add-CPHY-support.patch @@ -0,0 +1,109 @@ +From 8e711b6da5f7f35274781cd2a52cbaf2c6d9b950 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Sat, 25 Oct 2025 16:36:18 +0800 +Subject: [PATCH] ipu-bridge: add CPHY support + +get DPHY or CPHY mode when parse ssdb + +Signed-off-by: linya14x linx.yang@intel.com +--- + drivers/media/pci/intel/ipu-bridge.c | 23 ++++++++++++++++++++++- + include/media/ipu-bridge.h | 7 +++++-- + 2 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c +index e58b354ad9..3c947d1a48 100644 +--- a/drivers/media/pci/intel/ipu-bridge.c ++++ b/drivers/media/pci/intel/ipu-bridge.c +@@ -35,6 +35,9 @@ + */ + #define IVSC_DEV_NAME "intel_vsc" + ++#define PHY_MODE_DPHY 0 ++#define PHY_MODE_CPHY 1 ++ + /* + * Extend this array with ACPI Hardware IDs of devices known to be working + * plus the number of link-frequencies expected by their drivers, along with +@@ -314,6 +317,7 @@ int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor) + + sensor->link = ssdb.link; + sensor->lanes = ssdb.lanes; ++ sensor->phyconfig = ssdb.phyconfig; + sensor->mclkspeed = ssdb.mclkspeed; + sensor->rotation = ipu_bridge_parse_rotation(adev, &ssdb); + sensor->orientation = ipu_bridge_parse_orientation(adev); +@@ -332,6 +336,7 @@ static void ipu_bridge_create_fwnode_properties( + { + struct ipu_property_names *names = &sensor->prop_names; + struct software_node *nodes = sensor->swnodes; ++ u8 bus_type; + + sensor->prop_names = prop_names; + +@@ -389,9 +394,16 @@ static void ipu_bridge_create_fwnode_properties( + PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); + } + ++ if (sensor->phyconfig == PHY_MODE_DPHY) ++ bus_type = V4L2_FWNODE_BUS_TYPE_CSI2_DPHY; ++ else if (sensor->phyconfig == PHY_MODE_CPHY) ++ bus_type = V4L2_FWNODE_BUS_TYPE_CSI2_CPHY; ++ else ++ bus_type = V4L2_FWNODE_BUS_TYPE_GUESS; ++ + sensor->ep_properties[0] = PROPERTY_ENTRY_U32( + sensor->prop_names.bus_type, +- V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); ++ bus_type); + sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN( + sensor->prop_names.data_lanes, + bridge->data_lanes, sensor->lanes); +@@ -411,6 +423,15 @@ static void ipu_bridge_create_fwnode_properties( + sensor->ipu_properties[1] = PROPERTY_ENTRY_REF_ARRAY( + sensor->prop_names.remote_endpoint, + sensor->remote_ref); ++ ++ /* ++ * TODO: Remove the bus_type property for IPU ++ * 1. keep fwnode property list no change. ++ * 2. IPU driver needs to get bus_type from remote sensor ep. ++ */ ++ sensor->ipu_properties[2] = PROPERTY_ENTRY_U32 ++ (sensor->prop_names.bus_type, ++ bus_type); + } + + static void ipu_bridge_init_swnode_names(struct ipu_sensor *sensor) +diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h +index 16fac76545..f8642d0996 100644 +--- a/include/media/ipu-bridge.h ++++ b/include/media/ipu-bridge.h +@@ -91,7 +91,9 @@ struct ipu_sensor_ssdb { + u8 controllogicid; + u8 reserved1[3]; + u8 mclkport; +- u8 reserved2[13]; ++ u8 reserved2[5]; ++ u8 phyconfig; ++ u8 reserved3[7]; + } __packed; + + struct ipu_property_names { +@@ -139,11 +141,12 @@ struct ipu_sensor { + u32 rotation; + enum v4l2_fwnode_orientation orientation; + const char *vcm_type; ++ u8 phyconfig; + + struct ipu_property_names prop_names; + struct property_entry ep_properties[5]; + struct property_entry dev_properties[5]; +- struct property_entry ipu_properties[3]; ++ struct property_entry ipu_properties[4]; + struct property_entry ivsc_properties[1]; + struct property_entry ivsc_sensor_ep_properties[4]; + struct property_entry ivsc_ipu_ep_properties[4]; +-- +2.43.0 + diff --git a/patch/v6.17_staging/0013-media-ipu-Dma-sync-at-buffer_prepare-callback-as-DMA.patch b/patch/v6.17_staging/0013-media-ipu-Dma-sync-at-buffer_prepare-callback-as-DMA.patch new file mode 100644 index 0000000..fabd351 --- /dev/null +++ b/patch/v6.17_staging/0013-media-ipu-Dma-sync-at-buffer_prepare-callback-as-DMA.patch @@ -0,0 +1,42 @@ +From ec0ba9818f6dbf0c71c625d1120c7b58bf5a1f10 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Sat, 25 Oct 2025 16:42:45 +0800 +Subject: [PATCH] media: ipu: Dma sync at buffer_prepare callback as DMA is non-coherent + +Test Platform: +PTLRVP +LNLRVP + +Signed-off-by: Bingbu Cao +Signed-off-by: linya14x +--- + drivers/staging/media/ipu7/ipu7-isys-queue.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/staging/media/ipu7/ipu7-isys-queue.c b/drivers/staging/media/ipu7/ipu7-isys-queue.c +index 74067263d5..b780c73580 100644 +--- a/drivers/staging/media/ipu7/ipu7-isys-queue.c ++++ b/drivers/staging/media/ipu7/ipu7-isys-queue.c +@@ -91,7 +91,9 @@ static int ipu7_isys_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, + static int ipu7_isys_buf_prepare(struct vb2_buffer *vb) + { + struct ipu7_isys_queue *aq = vb2_queue_to_isys_queue(vb->vb2_queue); ++ struct ipu7_isys *isys = vb2_get_drv_priv(vb->vb2_queue); + struct ipu7_isys_video *av = ipu7_isys_queue_to_video(aq); ++ struct sg_table *sg = vb2_dma_sg_plane_desc(vb, 0); + struct device *dev = &av->isys->adev->auxdev.dev; + u32 bytesperline = av->pix_fmt.bytesperline; + u32 height = av->pix_fmt.height; +@@ -106,6 +108,9 @@ static int ipu7_isys_buf_prepare(struct vb2_buffer *vb) + av->vdev.name, bytesperline, height); + vb2_set_plane_payload(vb, 0, bytesperline * height); + ++ /* assume IPU is not DMA coherent */ ++ ipu7_dma_sync_sgtable(isys->adev, sg); ++ + return 0; + } + +-- +2.43.0 + diff --git a/patch/v6.17_staging/0014-max9x-add-config-in-makefile-kconfig.patch b/patch/v6.17_staging/0014-max9x-add-config-in-makefile-kconfig.patch new file mode 100644 index 0000000..b27a9e6 --- /dev/null +++ b/patch/v6.17_staging/0014-max9x-add-config-in-makefile-kconfig.patch @@ -0,0 +1,55 @@ +From f2a75c840e0905d72d6d613f81337376a5414038 Mon Sep 17 00:00:00 2001 +From: linya14x +Date: Sat, 25 Oct 2025 16:46:35 +0800 +Subject: [PATCH] max9x: add config in makefile & kconfig + +Signed-off-by: hepengpx +Signed-off-by: linya14x +--- + drivers/media/i2c/Kconfig | 16 ++++++++++++++++ + drivers/media/i2c/Makefile | 2 ++ + 2 files changed, 18 insertions(+) + +diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig +index 6dccc8e58d..f65a2f6118 100644 +--- a/drivers/media/i2c/Kconfig ++++ b/drivers/media/i2c/Kconfig +@@ -278,6 +278,22 @@ config VIDEO_LT6911GXD + To compile this driver as a module, choose M here: the + module will be called lt6911gxd. + ++config VIDEO_ISX031 ++ tristate "ISX031 sensor support" ++ depends on VIDEO_DEV && I2C ++ select VIDEO_V4L2_SUBDEV_API ++ depends on MEDIA_CAMERA_SUPPORT ++ help ++ This is a Video4Linux2 sensor-level driver for ISX031 camera. ++ ++config VIDEO_MAX9X ++ tristate "MAX9X serdes support" ++ depends on VIDEO_DEV && I2C ++ select VIDEO_V4L2_SUBDEV_API ++ depends on MEDIA_CAMERA_SUPPORT ++ help ++ This is a Video4Linux2 sensor-level driver for MAX9X serdes. ++ + config VIDEO_MAX9271_LIB + tristate + +diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile +index 2fbdd4c181..085c0e0e15 100644 +--- a/drivers/media/i2c/Makefile ++++ b/drivers/media/i2c/Makefile +@@ -61,6 +61,8 @@ obj-$(CONFIG_VIDEO_IMX412) += imx412.o + obj-$(CONFIG_VIDEO_IMX415) += imx415.o + obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o + obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o ++obj-$(CONFIG_VIDEO_MAX9X) += max9x/ ++obj-$(CONFIG_VIDEO_ISX031) += isx031.o + obj-$(CONFIG_VIDEO_KS0127) += ks0127.o + obj-$(CONFIG_VIDEO_LM3560) += lm3560.o + obj-$(CONFIG_VIDEO_LM3646) += lm3646.o +-- +2.43.0 + diff --git a/patch/v6.17_staging/0015-drivers-media-set-v4l2_subdev_enable_streams_api-tru.patch b/patch/v6.17_staging/0015-drivers-media-set-v4l2_subdev_enable_streams_api-tru.patch new file mode 100644 index 0000000..6f16df1 --- /dev/null +++ b/patch/v6.17_staging/0015-drivers-media-set-v4l2_subdev_enable_streams_api-tru.patch @@ -0,0 +1,27 @@ +From 8ceeec3023334389a058b317fdf8c178bd4a03d7 Mon Sep 17 00:00:00 2001 +From: hepengpx +Date: Wed, 27 Aug 2025 11:10:06 +0800 +Subject: [PATCH 2/2] drivers: media: set v4l2_subdev_enable_streams_api=true + for WA + +Signed-off-by: hepengpx +--- + drivers/media/v4l2-core/v4l2-subdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c +index 4fd25fea3b..60a05561f3 100644 +--- a/drivers/media/v4l2-core/v4l2-subdev.c ++++ b/drivers/media/v4l2-core/v4l2-subdev.c +@@ -32,7 +32,7 @@ + * 'v4l2_subdev_enable_streams_api' to 1 below. + */ + +-static bool v4l2_subdev_enable_streams_api; ++static bool v4l2_subdev_enable_streams_api = true; + #endif + + /* +-- +2.34.1 +