From patchwork Fri Mar 26 06:44:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: You-Sheng Yang X-Patchwork-Id: 1458661 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4F6CCz0dckz9sWd; Fri, 26 Mar 2021 17:45:51 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1lPgE6-00073s-2n; Fri, 26 Mar 2021 06:45:46 +0000 Received: from mail-pf1-f173.google.com ([209.85.210.173]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lPgCp-0006uw-08 for kernel-team@lists.ubuntu.com; Fri, 26 Mar 2021 06:44:27 +0000 Received: by mail-pf1-f173.google.com with SMTP id l3so4226050pfc.7 for ; Thu, 25 Mar 2021 23:44:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rD1t+HtjeChmZqAjL4JrU22y2/ybCtaUi6jEH/n9ESU=; b=SJeJxRMPymj3gbzSjqvTssDkSnnfJAygGobUkWXA67EDp9Y1B7VMRRE75nKecjZo6F Zm7h16nKZskiqb83a6qt9Gc16AO4Oq6jMgUMZ8zR+IuF23iMeKCNcBmW8FIqAD/1B95F 4gGtyRE+uhBeniODkGPeubems7t2YJwRnL4KLqS2K0Oa+PQXq+DzQFwCMk49AScFwBFJ 1ZdTP4PNcL2wiqPcMG1+0SuzOGbmcFtjD2bXPs/PViiRcBcGLKaYwzLP7hYro4tmIer4 5CvteU0j/8IY3PAyXBl3b8OF0btXykds82kwj4KEBibW5C+5mUyppD18bYTqO6mQO3FM rtnQ== X-Gm-Message-State: AOAM532yDCih4bHT78trxZVrsQcdJZzZfYAIBxYl+7M5tghpoqWryLli 8f9wQTroXO/Hvjq85/dnE5RROif2XCE= X-Google-Smtp-Source: ABdhPJzr41TXuHYz/sICUOioZ1LtDtmvg2SnrsAgGoL0cfbyAgQ30dN8tk1Lk9kcDJ29OGS0hVz5DA== X-Received: by 2002:a63:cf45:: with SMTP id b5mr10526463pgj.372.1616741063545; Thu, 25 Mar 2021 23:44:23 -0700 (PDT) Received: from localhost (61-220-137-37.HINET-IP.hinet.net. [61.220.137.37]) by smtp.gmail.com with ESMTPSA id f21sm7040053pjj.52.2021.03.25.23.44.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Mar 2021 23:44:22 -0700 (PDT) From: You-Sheng Yang To: kernel-team@lists.ubuntu.com Subject: [PATCH 4/7][SRU][OEM-5.10] UBUNTU: SAUCE: IPU driver release WW52 Date: Fri, 26 Mar 2021 14:44:04 +0800 Message-Id: <20210326064407.1789434-5-vicamo.yang@canonical.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210326064407.1789434-1-vicamo.yang@canonical.com> References: <20210326064407.1789434-1-vicamo.yang@canonical.com> MIME-Version: 1.0 Received-SPF: pass client-ip=209.85.210.173; envelope-from=vicamo@gmail.com; helo=mail-pf1-f173.google.com X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Wang Yating BugLink: https://bugs.launchpad.net/bugs/1921345 Signed-off-by: Wang Yating (backported from https://github.com/intel/ipu6-drivers/commit/71392b666a028c77126a9098fedb1fb30fc30568) Signed-off-by: You-Sheng Yang --- drivers/media/i2c/hm11b1.c | 8 +- drivers/media/i2c/ov01a1s.c | 8 +- drivers/media/i2c/pmic_dsc1.c | 158 +++++++++++ drivers/media/i2c/pmic_dsc1.h | 33 +++ drivers/media/pci/intel/Kconfig | 37 +-- drivers/media/pci/intel/Makefile | 4 +- drivers/media/pci/intel/ipu-buttress.c | 262 ++++++------------ drivers/media/pci/intel/ipu-buttress.h | 5 +- drivers/media/pci/intel/ipu-dma.c | 2 + drivers/media/pci/intel/ipu-fw-isys.c | 2 + .../media/pci/intel/ipu-isys-csi2-be-soc.c | 32 +++ drivers/media/pci/intel/ipu-isys-csi2-be.c | 31 +++ drivers/media/pci/intel/ipu-isys-queue.c | 4 + drivers/media/pci/intel/ipu-isys-video.c | 98 +++++-- drivers/media/pci/intel/ipu-isys-video.h | 4 + drivers/media/pci/intel/ipu-isys.c | 21 +- drivers/media/pci/intel/ipu-mmu.c | 4 +- drivers/media/pci/intel/ipu-psys-compat32.c | 5 +- drivers/media/pci/intel/ipu-psys.c | 9 +- drivers/media/pci/intel/ipu-psys.h | 2 +- drivers/media/pci/intel/ipu-trace.c | 20 +- drivers/media/pci/intel/ipu.c | 6 + drivers/media/pci/intel/ipu6/Makefile | 6 +- .../intel/ipu6/ipu-platform-buttress-regs.h | 6 +- .../media/pci/intel/ipu6/ipu-platform-isys.h | 8 + .../media/pci/intel/ipu6/ipu-platform-psys.h | 3 +- drivers/media/pci/intel/ipu6/ipu-resources.c | 2 - .../media/pci/intel/ipu6/ipu6-fw-resources.c | 20 -- drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 2 +- drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c | 18 +- drivers/media/pci/intel/ipu6/ipu6-isys-phy.c | 23 +- .../media/pci/intel/ipu6/ipu6-l-scheduler.c | 28 +- drivers/media/pci/intel/ipu6/ipu6-ppg.c | 22 +- drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c | 18 +- drivers/media/pci/intel/ipu6/ipu6-psys.c | 38 +-- drivers/media/pci/intel/ipu6/ipu6.c | 23 -- .../pci/intel/ipu6/ipu6se-fw-resources.c | 2 - include/uapi/linux/ipu-isys.h | 1 + 38 files changed, 558 insertions(+), 417 deletions(-) create mode 100644 drivers/media/i2c/pmic_dsc1.c create mode 100644 drivers/media/i2c/pmic_dsc1.h diff --git a/drivers/media/i2c/hm11b1.c b/drivers/media/i2c/hm11b1.c index 9c1662b842de..35f49eb7b852 100644 --- a/drivers/media/i2c/hm11b1.c +++ b/drivers/media/i2c/hm11b1.c @@ -10,6 +10,7 @@ #include #include #include +#include "pmic_dsc1.h" #define HM11B1_LINK_FREQ_384MHZ 384000000ULL #define HM11B1_SCLK 72000000LL @@ -1000,6 +1001,7 @@ static int hm11b1_start_streaming(struct hm11b1 *hm11b1) int link_freq_index; int ret = 0; + pmic_dsc1_set_power(1); link_freq_index = hm11b1->cur_mode->link_freq_index; reg_list = &link_freq_configs[link_freq_index].reg_list; ret = hm11b1_write_reg_list(hm11b1, reg_list); @@ -1034,6 +1036,7 @@ static void hm11b1_stop_streaming(struct hm11b1 *hm11b1) if (hm11b1_write_reg(hm11b1, HM11B1_REG_MODE_SELECT, 1, HM11B1_MODE_STANDBY)) dev_err(&client->dev, "failed to stop streaming"); + pmic_dsc1_set_power(0); } static int hm11b1_set_stream(struct v4l2_subdev *sd, int enable) @@ -1275,6 +1278,8 @@ static int hm11b1_probe(struct i2c_client *client) return -ENOMEM; v4l2_i2c_subdev_init(&hm11b1->sd, client, &hm11b1_subdev_ops); + pmic_dsc1_set_power(0); + pmic_dsc1_set_power(1); ret = hm11b1_identify_module(hm11b1); if (ret) { dev_err(&client->dev, "failed to find sensor: %d", ret); @@ -1315,6 +1320,7 @@ static int hm11b1_probe(struct i2c_client *client) pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); + pmic_dsc1_set_power(0); return 0; probe_error_media_entity_cleanup: @@ -1333,7 +1339,7 @@ static const struct dev_pm_ops hm11b1_pm_ops = { #ifdef CONFIG_ACPI static const struct acpi_device_id hm11b1_acpi_ids[] = { - {"HM11B1"}, + {"HIMX11B1"}, {} }; diff --git a/drivers/media/i2c/ov01a1s.c b/drivers/media/i2c/ov01a1s.c index 1d05b75347a1..766fe30116c3 100644 --- a/drivers/media/i2c/ov01a1s.c +++ b/drivers/media/i2c/ov01a1s.c @@ -10,6 +10,7 @@ #include #include #include +#include "pmic_dsc1.h" #define OV01A1S_LINK_FREQ_400MHZ 400000000ULL #define OV01A1S_SCLK 40000000LL @@ -566,6 +567,7 @@ static int ov01a1s_start_streaming(struct ov01a1s *ov01a1s) int link_freq_index; int ret = 0; + pmic_dsc1_set_power(1); link_freq_index = ov01a1s->cur_mode->link_freq_index; reg_list = &link_freq_configs[link_freq_index].reg_list; ret = ov01a1s_write_reg_list(ov01a1s, reg_list); @@ -602,6 +604,7 @@ static void ov01a1s_stop_streaming(struct ov01a1s *ov01a1s) OV01A1S_MODE_STANDBY); if (ret) dev_err(&client->dev, "failed to stop streaming"); + pmic_dsc1_set_power(0); } static int ov01a1s_set_stream(struct v4l2_subdev *sd, int enable) @@ -843,6 +846,8 @@ static int ov01a1s_probe(struct i2c_client *client) return -ENOMEM; v4l2_i2c_subdev_init(&ov01a1s->sd, client, &ov01a1s_subdev_ops); + pmic_dsc1_set_power(0); + pmic_dsc1_set_power(1); ret = ov01a1s_identify_module(ov01a1s); if (ret) { dev_err(&client->dev, "failed to find sensor: %d", ret); @@ -883,6 +888,7 @@ static int ov01a1s_probe(struct i2c_client *client) pm_runtime_enable(&client->dev); pm_runtime_idle(&client->dev); + pmic_dsc1_set_power(0); return 0; probe_error_media_entity_cleanup: @@ -901,7 +907,7 @@ static const struct dev_pm_ops ov01a1s_pm_ops = { #ifdef CONFIG_ACPI static const struct acpi_device_id ov01a1s_acpi_ids[] = { - { "OVTI01AF" }, + { "OVTI01AS" }, {} }; diff --git a/drivers/media/i2c/pmic_dsc1.c b/drivers/media/i2c/pmic_dsc1.c new file mode 100644 index 000000000000..9892bc506e0b --- /dev/null +++ b/drivers/media/i2c/pmic_dsc1.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020 Intel Corporation. + +#include +#include +#include "pmic_dsc1.h" + +/* mcu gpio resources*/ +static const struct acpi_gpio_params camreset_gpio = { 0, 0, false }; +static const struct acpi_gpio_params campwdn_gpio = { 1, 0, false }; +static const struct acpi_gpio_params midmclken_gpio = { 2, 0, false }; +static const struct acpi_gpio_params led_gpio = { 3, 0, false }; +static const struct acpi_gpio_mapping dsc1_acpi_gpios[] = { + { "camreset-gpios", &camreset_gpio, 1 }, + { "campwdn-gpios", &campwdn_gpio, 1 }, + { "midmclken-gpios", &midmclken_gpio, 1 }, + { "indled-gpios", &led_gpio, 1 }, + { } +}; + +static const char * const pin_names[] = { + "camreset", "campwdn", "midmclken", "indled" +}; + +struct pmic_dsc1 pmic = { + .reset_gpio = NULL, + .powerdn_gpio = NULL, + .clocken_gpio = NULL, + .indled_gpio = NULL, + .power_on = false, + .gpio_ready = false, +}; + +static int get_gpio_pin(struct gpio_desc **pin_d, struct pci_dev *pdev, int idx) +{ + int count = PMIC_DSC1_PROBE_MAX_TRY; + + do { + dev_dbg(&pdev->dev, "get %s:tried once\n", pin_names[idx]); + *pin_d = devm_gpiod_get(&pdev->dev, pin_names[idx], + GPIOD_OUT_LOW); + if (!IS_ERR(*pin_d)) + return 0; + *pin_d = NULL; + msleep_interruptible(PMIC_DSC1_PROBE_TRY_GAP); + } while (--count > 0); + + return -EBUSY; +} + +static int pmic_dsc1_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + int ret; + + if (!pdev) { + dev_err(&pdev->dev, "@%s: probed null pdev %x:%x\n", + __func__, PCI_BRG_VENDOR_ID, PCI_BRG_PRODUCT_ID); + return -ENODEV; + } + dev_dbg(&pdev->dev, "@%s, enter\n", __func__); + + ret = devm_acpi_dev_add_driver_gpios(&pdev->dev, dsc1_acpi_gpios); + if (ret) { + dev_err(&pdev->dev, "@%s: fail to add gpio\n", __func__); + return -EBUSY; + } + ret = get_gpio_pin(&pmic.reset_gpio, pdev, 0); + if (ret) + goto pmic_dsc1_probe_end; + ret = get_gpio_pin(&pmic.powerdn_gpio, pdev, 1); + if (ret) + goto pmic_dsc1_probe_end; + ret = get_gpio_pin(&pmic.clocken_gpio, pdev, 2); + if (ret) + goto pmic_dsc1_probe_end; + ret = get_gpio_pin(&pmic.indled_gpio, pdev, 3); + if (ret) + goto pmic_dsc1_probe_end; + + mutex_lock(&pmic.status_lock); + pmic.gpio_ready = true; + mutex_unlock(&pmic.status_lock); + +pmic_dsc1_probe_end: + dev_dbg(&pdev->dev, "@%s, exit\n", __func__); + return ret; +} + +static void pmic_dsc1_remove(struct pci_dev *pdev) +{ + dev_dbg(&pdev->dev, "@%s, enter\n", __func__); + mutex_lock(&pmic.status_lock); + pmic.gpio_ready = false; + gpiod_set_value_cansleep(pmic.reset_gpio, 0); + gpiod_put(pmic.reset_gpio); + gpiod_set_value_cansleep(pmic.powerdn_gpio, 0); + gpiod_put(pmic.powerdn_gpio); + gpiod_set_value_cansleep(pmic.clocken_gpio, 0); + gpiod_put(pmic.clocken_gpio); + gpiod_set_value_cansleep(pmic.indled_gpio, 0); + gpiod_put(pmic.indled_gpio); + mutex_unlock(&pmic.status_lock); + dev_dbg(&pdev->dev, "@%s, exit\n", __func__); +} + +static struct pci_device_id pmic_dsc1_ids[] = { + { PCI_DEVICE(PCI_BRG_VENDOR_ID, PCI_BRG_PRODUCT_ID) }, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, pmic_dsc1_ids); + +static struct pci_driver pmic_dsc1_driver = { + .name = PMIC_DRV_NAME, + .id_table = pmic_dsc1_ids, + .probe = pmic_dsc1_probe, + .remove = pmic_dsc1_remove, +}; + +static int __init pmic_dsc1_init(void) +{ + mutex_init(&pmic.status_lock); + return pci_register_driver(&pmic_dsc1_driver); +} + +static void __exit pmic_dsc1_exit(void) +{ + pci_unregister_driver(&pmic_dsc1_driver); +} +module_init(pmic_dsc1_init); +module_exit(pmic_dsc1_exit); + +int pmic_dsc1_set_power(int on) +{ + mutex_lock(&pmic.status_lock); + if (!pmic.gpio_ready || on < 0 || on > 1) { + pr_debug("@%s,failed to set power, gpio_ready=%d, on=%d\n", + __func__, pmic.gpio_ready, on); + mutex_unlock(&pmic.status_lock); + return -EBUSY; + } + if (pmic.power_on != on) { + gpiod_set_value_cansleep(pmic.reset_gpio, on); + gpiod_set_value_cansleep(pmic.powerdn_gpio, on); + gpiod_set_value_cansleep(pmic.clocken_gpio, on); + gpiod_set_value_cansleep(pmic.indled_gpio, on); + pmic.power_on = on; + } + mutex_unlock(&pmic.status_lock); + return 0; +} +EXPORT_SYMBOL_GPL(pmic_dsc1_set_power); + +MODULE_AUTHOR("Bingbu Cao "); +MODULE_AUTHOR("Qiu, Tianshu "); +MODULE_AUTHOR("Xu, Chongyang "); +MODULE_DESCRIPTION("PMIC-CRDG DSC1 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/i2c/pmic_dsc1.h b/drivers/media/i2c/pmic_dsc1.h new file mode 100644 index 000000000000..19f1112f85f8 --- /dev/null +++ b/drivers/media/i2c/pmic_dsc1.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2020 Intel Corporation. */ + +#ifndef _PMIC_DSC1_H_ +#define _PMIC_DSC1_H_ + +#include +#include +#include + +/* pmic dsc1 pci id */ +#define PCI_BRG_VENDOR_ID 0x8086 +#define PCI_BRG_PRODUCT_ID 0x9a14 + +#define PMIC_DRV_NAME "pmic_dsc1" +#define PMIC_DSC1_PROBE_MAX_TRY 5 +#define PMIC_DSC1_PROBE_TRY_GAP 500 /* in millseconds */ + +struct pmic_dsc1 { + /* gpio resource*/ + struct gpio_desc *reset_gpio; + struct gpio_desc *powerdn_gpio; + struct gpio_desc *clocken_gpio; + struct gpio_desc *indled_gpio; + /* status */ + struct mutex status_lock; + bool power_on; + bool gpio_ready; +}; + +/* exported function for extern module */ +int pmic_dsc1_set_power(int on); +#endif diff --git a/drivers/media/pci/intel/Kconfig b/drivers/media/pci/intel/Kconfig index 8ea99271932b..9017ccfc7a55 100644 --- a/drivers/media/pci/intel/Kconfig +++ b/drivers/media/pci/intel/Kconfig @@ -1,11 +1,12 @@ -config VIDEO_INTEL_IPU +config VIDEO_INTEL_IPU6 tristate "Intel IPU driver" depends on ACPI depends on MEDIA_SUPPORT depends on MEDIA_PCI_SUPPORT + depends on X86_64 select IOMMU_API select IOMMU_IOVA - select X86_DEV_DMA_OPS if X86 + select X86_DEV_DMA_OPS select VIDEOBUF2_DMA_CONTIG select V4L2_FWNODE select PHYS_ADDR_T_64BIT @@ -14,24 +15,12 @@ config VIDEO_INTEL_IPU This is the Intel imaging processing unit, found in Intel SoCs and used for capturing images and video from a camera sensor. - To compile this driver, say Y here! - -choice - prompt "intel ipu generation type" - depends on VIDEO_INTEL_IPU - default VIDEO_INTEL_IPU6 - -config VIDEO_INTEL_IPU6 - bool "Compile for IPU6 driver" - help - Sixth generation Intel imaging processing unit found in Intel - SoCs. - - To compile this driver, say Y here! -endchoice + To compile this driver, say Y here! It contains 3 modules - + intel_ipu6, intel_ipu6_isys and intel_ipu6_psys. config VIDEO_INTEL_IPU_TPG bool "Compile for TPG driver" + depends on VIDEO_INTEL_IPU6 help If selected, TPG device nodes would be created. @@ -40,18 +29,4 @@ config VIDEO_INTEL_IPU_TPG If you want to the TPG devices exposed to user as media entity, you must select this option, otherwise no. -config VIDEO_INTEL_IPU_WERROR - bool "Force GCC to throw an error instead of a warning when compiling" - depends on VIDEO_INTEL_IPU - depends on EXPERT - depends on !COMPILE_TEST - default n - help - Add -Werror to the build flags for (and only for) intel ipu module. - Do not enable this unless you are writing code for the ipu module. - - Recommended for driver developers only. - - If in doubt, say "N". - source "drivers/media/pci/intel/ipu3/Kconfig" diff --git a/drivers/media/pci/intel/Makefile b/drivers/media/pci/intel/Makefile index a0ccb70023e5..608acd574921 100644 --- a/drivers/media/pci/intel/Makefile +++ b/drivers/media/pci/intel/Makefile @@ -11,7 +11,5 @@ subdir-ccflags-y += $(call cc-disable-warning, implicit-fallthrough) subdir-ccflags-y += $(call cc-disable-warning, missing-field-initializers) subdir-ccflags-$(CONFIG_VIDEO_INTEL_IPU_WERROR) += -Werror -obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3/ -#obj-$(CONFIG_VIDEO_INTEL_IPU4) += ipu4/ -#obj-$(CONFIG_VIDEO_INTEL_IPU4P) += ipu4/ +obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3/ obj-$(CONFIG_VIDEO_INTEL_IPU6) += ipu6/ diff --git a/drivers/media/pci/intel/ipu-buttress.c b/drivers/media/pci/intel/ipu-buttress.c index 2ee8a9e554b6..ee014a8bea66 100644 --- a/drivers/media/pci/intel/ipu-buttress.c +++ b/drivers/media/pci/intel/ipu-buttress.c @@ -51,23 +51,6 @@ #define BUTTRESS_IPC_CMD_SEND_RETRY 1 -static const struct ipu_buttress_sensor_clk_freq sensor_clk_freqs[] = { - {6750000, BUTTRESS_SENSOR_CLK_FREQ_6P75MHZ}, - {8000000, BUTTRESS_SENSOR_CLK_FREQ_8MHZ}, - {9600000, BUTTRESS_SENSOR_CLK_FREQ_9P6MHZ}, - {12000000, BUTTRESS_SENSOR_CLK_FREQ_12MHZ}, - {13600000, BUTTRESS_SENSOR_CLK_FREQ_13P6MHZ}, - {14400000, BUTTRESS_SENSOR_CLK_FREQ_14P4MHZ}, - {15800000, BUTTRESS_SENSOR_CLK_FREQ_15P8MHZ}, - {16200000, BUTTRESS_SENSOR_CLK_FREQ_16P2MHZ}, - {17300000, BUTTRESS_SENSOR_CLK_FREQ_17P3MHZ}, - {18600000, BUTTRESS_SENSOR_CLK_FREQ_18P6MHZ}, - {19200000, BUTTRESS_SENSOR_CLK_FREQ_19P2MHZ}, - {24000000, BUTTRESS_SENSOR_CLK_FREQ_24MHZ}, - {26000000, BUTTRESS_SENSOR_CLK_FREQ_26MHZ}, - {27000000, BUTTRESS_SENSOR_CLK_FREQ_27MHZ} -}; - static const u32 ipu_adev_irq_mask[] = { BUTTRESS_ISR_IS_IRQ, BUTTRESS_ISR_PS_IRQ }; @@ -75,7 +58,7 @@ static const u32 ipu_adev_irq_mask[] = { int ipu_buttress_ipc_reset(struct ipu_device *isp, struct ipu_buttress_ipc *ipc) { struct ipu_buttress *b = &isp->buttress; - unsigned int timeout = BUTTRESS_IPC_RESET_TIMEOUT; + unsigned int retries = BUTTRESS_IPC_RESET_TIMEOUT; u32 val = 0, csr_in_clr; if (!isp->secure_mode) { @@ -103,7 +86,7 @@ int ipu_buttress_ipc_reset(struct ipu_device *isp, struct ipu_buttress_ipc *ipc) BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID | BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ | QUERY; - while (timeout--) { + while (retries--) { usleep_range(400, 500); val = readl(isp->base + ipc->csr_in); switch (val) { @@ -124,7 +107,7 @@ int ipu_buttress_ipc_reset(struct ipu_device *isp, struct ipu_buttress_ipc *ipc) writel(QUERY, isp->base + ipc->csr_out); break; case ENTRY: - case ENTRY | QUERY: + case (ENTRY | QUERY): dev_dbg(&isp->pdev->dev, "%s:IPC_PEER_COMP_ACTIONS_RST_PHASE1\n", __func__); @@ -139,7 +122,7 @@ int ipu_buttress_ipc_reset(struct ipu_device *isp, struct ipu_buttress_ipc *ipc) writel(ENTRY, isp->base + ipc->csr_out); break; case EXIT: - case EXIT | QUERY: + case (EXIT | QUERY): dev_dbg(&isp->pdev->dev, "%s: IPC_PEER_COMP_ACTIONS_RST_PHASE2\n", __func__); @@ -512,7 +495,8 @@ int ipu_buttress_power(struct device *dev, } else { val = BUTTRESS_FREQ_CTL_START | ctrl->divisor << ctrl->divisor_shift | - ctrl->qos_floor << BUTTRESS_FREQ_CTL_QOS_FLOOR_SHIFT; + ctrl->qos_floor << BUTTRESS_FREQ_CTL_QOS_FLOOR_SHIFT | + BUTTRESS_FREQ_CTL_ICCMAX_LEVEL; pwr_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift; } @@ -629,6 +613,28 @@ static void ipu_buttress_set_psys_ratio(struct ipu_device *isp, mutex_unlock(&isp->buttress.power_mutex); } +static void ipu_buttress_set_isys_ratio(struct ipu_device *isp, + unsigned int isys_divisor) +{ + struct ipu_buttress_ctrl *ctrl = isp->isys->ctrl; + + mutex_lock(&isp->buttress.power_mutex); + + if (ctrl->divisor == isys_divisor) + goto out_mutex_unlock; + + ctrl->divisor = isys_divisor; + + if (ctrl->started) { + writel(BUTTRESS_FREQ_CTL_START | + ctrl->qos_floor << BUTTRESS_FREQ_CTL_QOS_FLOOR_SHIFT | + isys_divisor, isp->base + BUTTRESS_REG_IS_FREQ_CTL); + } + +out_mutex_unlock: + mutex_unlock(&isp->buttress.power_mutex); +} + static void ipu_buttress_set_psys_freq(struct ipu_device *isp, unsigned int freq) { @@ -955,165 +961,6 @@ struct clk_ipu_sensor { #define to_clk_ipu_sensor(_hw) container_of(_hw, struct clk_ipu_sensor, hw) -static int ipu_buttress_clk_pll_prepare(struct clk_hw *hw) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - int ret; - - /* Workaround needed to get sensor clock running in some cases */ - ret = pm_runtime_get_sync(&ck->isp->isys->dev); - return ret >= 0 ? 0 : ret; -} - -static void ipu_buttress_clk_pll_unprepare(struct clk_hw *hw) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - - /* Workaround needed to get sensor clock stopped in some cases */ - pm_runtime_put(&ck->isp->isys->dev); -} - -static int ipu_buttress_clk_pll_enable(struct clk_hw *hw) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - u32 val; - unsigned int i; - - /* - * Start bit behaves like master clock request towards ICLK. - * It is needed regardless of the 24 MHz or per clock out pll - * setting. - */ - val = readl(ck->isp->base + BUTTRESS_REG_SENSOR_FREQ_CTL); - val |= BUTTRESS_FREQ_CTL_START; - val &= ~BUTTRESS_SENSOR_FREQ_CTL_OSC_OUT_FREQ_MASK(ck->id); - for (i = 0; i < ARRAY_SIZE(sensor_clk_freqs); i++) - if (sensor_clk_freqs[i].rate == ck->rate) - break; - - if (i < ARRAY_SIZE(sensor_clk_freqs)) - val |= sensor_clk_freqs[i].val << - BUTTRESS_SENSOR_FREQ_CTL_OSC_OUT_FREQ_SHIFT(ck->id); - else - val |= BUTTRESS_SENSOR_FREQ_CTL_OSC_OUT_FREQ_DEFAULT(ck->id); - - writel(val, ck->isp->base + BUTTRESS_REG_SENSOR_FREQ_CTL); - - return 0; -} - -static void ipu_buttress_clk_pll_disable(struct clk_hw *hw) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - u32 val; - int i; - - val = readl(ck->isp->base + BUTTRESS_REG_SENSOR_CLK_CTL); - for (i = 0; i < IPU_BUTTRESS_NUM_OF_SENS_CKS; i++) { - if (val & - (1 << BUTTRESS_SENSOR_CLK_CTL_OSC_CLK_OUT_EN_SHIFT(i))) - return; - } - - /* See enable control above */ - val = readl(ck->isp->base + BUTTRESS_REG_SENSOR_FREQ_CTL); - val &= ~BUTTRESS_FREQ_CTL_START; - writel(val, ck->isp->base + BUTTRESS_REG_SENSOR_FREQ_CTL); -} - -static int ipu_buttress_clk_enable(struct clk_hw *hw) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - u32 val; - - val = readl(ck->isp->base + BUTTRESS_REG_SENSOR_CLK_CTL); - val |= 1 << BUTTRESS_SENSOR_CLK_CTL_OSC_CLK_OUT_EN_SHIFT(ck->id); - - /* Enable dynamic sensor clock */ - val |= 1 << BUTTRESS_SENSOR_CLK_CTL_OSC_CLK_OUT_SEL_SHIFT(ck->id); - writel(val, ck->isp->base + BUTTRESS_REG_SENSOR_CLK_CTL); - - return 0; -} - -static void ipu_buttress_clk_disable(struct clk_hw *hw) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - u32 val; - - val = readl(ck->isp->base + BUTTRESS_REG_SENSOR_CLK_CTL); - val &= ~(1 << BUTTRESS_SENSOR_CLK_CTL_OSC_CLK_OUT_EN_SHIFT(ck->id)); - writel(val, ck->isp->base + BUTTRESS_REG_SENSOR_CLK_CTL); -} - -static long ipu_buttress_clk_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long best = ULONG_MAX; - unsigned long round_rate = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(sensor_clk_freqs); i++) { - long diff = sensor_clk_freqs[i].rate - rate; - - if (diff == 0) - return rate; - - diff = abs(diff); - if (diff < best) { - best = diff; - round_rate = sensor_clk_freqs[i].rate; - } - } - - return round_rate; -} - -static unsigned long -ipu_buttress_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - - return ck->rate; -} - -static int ipu_buttress_clk_set_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long parent_rate) -{ - struct clk_ipu_sensor *ck = to_clk_ipu_sensor(hw); - - /* - * R N P PVD PLLout - * 1 45 128 2 6.75 - * 1 40 96 2 8 - * 1 40 80 2 9.6 - * 1 15 20 4 14.4 - * 1 40 32 2 24 - * 1 65 48 1 26 - * - */ - ck->rate = rate; - - return 0; -} - -static const struct clk_ops ipu_buttress_clk_sensor_ops = { - .enable = ipu_buttress_clk_enable, - .disable = ipu_buttress_clk_disable, -}; - -static const struct clk_ops ipu_buttress_clk_sensor_ops_parent = { - .enable = ipu_buttress_clk_pll_enable, - .disable = ipu_buttress_clk_pll_disable, - .prepare = ipu_buttress_clk_pll_prepare, - .unprepare = ipu_buttress_clk_pll_unprepare, - .round_rate = ipu_buttress_clk_round_rate, - .recalc_rate = ipu_buttress_clk_recalc_rate, - .set_rate = ipu_buttress_clk_set_rate, -}; - int ipu_buttress_tsc_read(struct ipu_device *isp, u64 *val) { struct ipu_buttress *b = &isp->buttress; @@ -1265,6 +1112,54 @@ static int ipu_buttress_psys_force_freq_set(void *data, u64 val) return 0; } +int ipu_buttress_isys_freq_get(void *data, u64 *val) +{ + struct ipu_device *isp = data; + u32 reg_val; + int rval; + + rval = pm_runtime_get_sync(&isp->isys->dev); + if (rval < 0) { + pm_runtime_put(&isp->isys->dev); + dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n", rval); + return rval; + } + + reg_val = readl(isp->base + BUTTRESS_REG_IS_FREQ_CTL); + + pm_runtime_put(&isp->isys->dev); + + *val = IPU_IS_FREQ_RATIO_BASE * + (reg_val & IPU_BUTTRESS_IS_FREQ_CTL_DIVISOR_MASK); + + return 0; +} + +int ipu_buttress_isys_freq_set(void *data, u64 val) +{ + struct ipu_device *isp = data; + int rval; + + if (val < BUTTRESS_MIN_FORCE_IS_FREQ || + val > BUTTRESS_MAX_FORCE_IS_FREQ) + return -EINVAL; + + rval = pm_runtime_get_sync(&isp->isys->dev); + if (rval < 0) { + pm_runtime_put(&isp->isys->dev); + dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n", rval); + return rval; + } + + do_div(val, BUTTRESS_IS_FREQ_STEP); + if (val) + ipu_buttress_set_isys_ratio(isp, val); + + pm_runtime_put(&isp->isys->dev); + + return 0; +} + DEFINE_SIMPLE_ATTRIBUTE(ipu_buttress_psys_force_freq_fops, ipu_buttress_psys_force_freq_get, ipu_buttress_psys_force_freq_set, "%llu\n"); @@ -1273,7 +1168,8 @@ DEFINE_SIMPLE_ATTRIBUTE(ipu_buttress_psys_freq_fops, ipu_buttress_psys_freq_get, NULL, "%llu\n"); DEFINE_SIMPLE_ATTRIBUTE(ipu_buttress_isys_freq_fops, - ipu_buttress_isys_freq_get, NULL, "%llu\n"); + ipu_buttress_isys_freq_get, + ipu_buttress_isys_freq_set, "%llu\n"); int ipu_buttress_debugfs_init(struct ipu_device *isp) { @@ -1318,7 +1214,7 @@ int ipu_buttress_debugfs_init(struct ipu_device *isp) if (!file) goto err; - file = debugfs_create_file("isys_freq", 0400, dir, isp, + file = debugfs_create_file("isys_freq", 0700, dir, isp, &ipu_buttress_isys_freq_fops); if (!file) goto err; diff --git a/drivers/media/pci/intel/ipu-buttress.h b/drivers/media/pci/intel/ipu-buttress.h index 02c8b46947a1..e1d054c3cd07 100644 --- a/drivers/media/pci/intel/ipu-buttress.h +++ b/drivers/media/pci/intel/ipu-buttress.h @@ -18,6 +18,10 @@ #define BUTTRESS_MIN_FORCE_PS_FREQ (BUTTRESS_PS_FREQ_STEP * 8) #define BUTTRESS_MAX_FORCE_PS_FREQ (BUTTRESS_PS_FREQ_STEP * 32) +#define BUTTRESS_IS_FREQ_STEP 25U +#define BUTTRESS_MIN_FORCE_IS_FREQ (BUTTRESS_IS_FREQ_STEP * 8) +#define BUTTRESS_MAX_FORCE_IS_FREQ (BUTTRESS_IS_FREQ_STEP * 16) + struct ipu_buttress_ctrl { u32 freq_ctl, pwr_sts_shift, pwr_sts_mask, pwr_sts_on, pwr_sts_off; union { @@ -122,5 +126,4 @@ void ipu_buttress_csi_port_config(struct ipu_device *isp, int ipu_buttress_restore(struct ipu_device *isp); int ipu_buttress_psys_freq_get(void *data, u64 *val); -int ipu_buttress_isys_freq_get(void *data, u64 *val); #endif /* IPU_BUTTRESS_H */ diff --git a/drivers/media/pci/intel/ipu-dma.c b/drivers/media/pci/intel/ipu-dma.c index 34fa1fb6b060..2e844dd16e61 100644 --- a/drivers/media/pci/intel/ipu-dma.c +++ b/drivers/media/pci/intel/ipu-dma.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include "ipu-dma.h" #include "ipu-bus.h" diff --git a/drivers/media/pci/intel/ipu-fw-isys.c b/drivers/media/pci/intel/ipu-fw-isys.c index 974c6f59d34d..307117818a52 100644 --- a/drivers/media/pci/intel/ipu-fw-isys.c +++ b/drivers/media/pci/intel/ipu-fw-isys.c @@ -643,6 +643,8 @@ ipu_fw_isys_dump_stream_cfg(struct device *dev, stream_cfg->output_pins[i].output_res.height); dev_dbg(dev, "Stride %d\n", stream_cfg->output_pins[i].stride); dev_dbg(dev, "Pin type %d\n", stream_cfg->output_pins[i].pt); + dev_dbg(dev, "Payload %d\n", + stream_cfg->output_pins[i].payload_buf_size); dev_dbg(dev, "Ft %d\n", stream_cfg->output_pins[i].ft); dev_dbg(dev, "Watermar in lines %d\n", stream_cfg->output_pins[i].watermark_in_lines); diff --git a/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c b/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c index db90680e736d..501d5620e7e1 100644 --- a/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c +++ b/drivers/media/pci/intel/ipu-isys-csi2-be-soc.c @@ -50,6 +50,17 @@ static struct v4l2_subdev_internal_ops csi2_be_soc_sd_internal_ops = { static const struct v4l2_subdev_core_ops csi2_be_soc_sd_core_ops = { }; +static const struct v4l2_ctrl_config compression_ctrl_cfg = { + .ops = NULL, + .id = V4L2_CID_IPU_ISYS_COMPRESSION, + .name = "ISYS BE-SOC compression", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .min = 0, + .max = 1, + .step = 1, + .def = 0, +}; + static int set_stream(struct v4l2_subdev *sd, int enable) { return 0; @@ -164,6 +175,7 @@ void ipu_isys_csi2_be_soc_cleanup(struct ipu_isys_csi2_be_soc *csi2_be_soc) { v4l2_device_unregister_subdev(&csi2_be_soc->asd.sd); ipu_isys_subdev_cleanup(&csi2_be_soc->asd); + v4l2_ctrl_handler_free(&csi2_be_soc->av.ctrl_handler); ipu_isys_video_cleanup(&csi2_be_soc->av); } @@ -242,6 +254,26 @@ int ipu_isys_csi2_be_soc_init(struct ipu_isys_csi2_be_soc *csi2_be_soc, csi2_be_soc->av.aq.vbq.buf_struct_size = sizeof(struct ipu_isys_video_buffer); + /* create v4l2 ctrl for be-soc video node */ + rval = v4l2_ctrl_handler_init(&csi2_be_soc->av.ctrl_handler, 0); + if (rval) { + dev_err(&isys->adev->dev, + "failed to init v4l2 ctrl handler for be_soc\n"); + goto fail; + } + + csi2_be_soc->av.compression_ctrl = + v4l2_ctrl_new_custom(&csi2_be_soc->av.ctrl_handler, + &compression_ctrl_cfg, NULL); + if (!csi2_be_soc->av.compression_ctrl) { + dev_err(&isys->adev->dev, + "failed to create BE-SOC cmprs ctrl\n"); + goto fail; + } + csi2_be_soc->av.compression = 0; + csi2_be_soc->av.vdev.ctrl_handler = + &csi2_be_soc->av.ctrl_handler; + rval = ipu_isys_video_init(&csi2_be_soc->av, &csi2_be_soc->asd.sd.entity, CSI2_BE_SOC_PAD_SOURCE, diff --git a/drivers/media/pci/intel/ipu-isys-csi2-be.c b/drivers/media/pci/intel/ipu-isys-csi2-be.c index 9aae37af8011..99ceb607feda 100644 --- a/drivers/media/pci/intel/ipu-isys-csi2-be.c +++ b/drivers/media/pci/intel/ipu-isys-csi2-be.c @@ -48,6 +48,17 @@ static struct v4l2_subdev_internal_ops csi2_be_sd_internal_ops = { static const struct v4l2_subdev_core_ops csi2_be_sd_core_ops = { }; +static const struct v4l2_ctrl_config compression_ctrl_cfg = { + .ops = NULL, + .id = V4L2_CID_IPU_ISYS_COMPRESSION, + .name = "ISYS CSI-BE compression", + .type = V4L2_CTRL_TYPE_BOOLEAN, + .min = 0, + .max = 1, + .step = 1, + .def = 0, +}; + static int set_stream(struct v4l2_subdev *sd, int enable) { return 0; @@ -201,6 +212,7 @@ static void csi2_be_set_ffmt(struct v4l2_subdev *sd, void ipu_isys_csi2_be_cleanup(struct ipu_isys_csi2_be *csi2_be) { + v4l2_ctrl_handler_free(&csi2_be->av.ctrl_handler); v4l2_device_unregister_subdev(&csi2_be->asd.sd); ipu_isys_subdev_cleanup(&csi2_be->asd); ipu_isys_video_cleanup(&csi2_be->av); @@ -278,6 +290,25 @@ int ipu_isys_csi2_be_init(struct ipu_isys_csi2_be *csi2_be, csi2_be->av.aq.vbq.buf_struct_size = sizeof(struct ipu_isys_video_buffer); + /* create v4l2 ctrl for csi-be video node */ + rval = v4l2_ctrl_handler_init(&csi2_be->av.ctrl_handler, 0); + if (rval) { + dev_err(&isys->adev->dev, + "failed to init v4l2 ctrl handler for csi2_be\n"); + goto fail; + } + + csi2_be->av.compression_ctrl = + v4l2_ctrl_new_custom(&csi2_be->av.ctrl_handler, + &compression_ctrl_cfg, NULL); + if (!csi2_be->av.compression_ctrl) { + dev_err(&isys->adev->dev, + "failed to create CSI-BE cmprs ctrl\n"); + goto fail; + } + csi2_be->av.compression = 0; + csi2_be->av.vdev.ctrl_handler = &csi2_be->av.ctrl_handler; + rval = ipu_isys_video_init(&csi2_be->av, &csi2_be->asd.sd.entity, CSI2_BE_PAD_SOURCE, MEDIA_PAD_FL_SINK, 0); if (rval) { diff --git a/drivers/media/pci/intel/ipu-isys-queue.c b/drivers/media/pci/intel/ipu-isys-queue.c index 10498dddaf09..1f379f0464a1 100644 --- a/drivers/media/pci/intel/ipu-isys-queue.c +++ b/drivers/media/pci/intel/ipu-isys-queue.c @@ -336,6 +336,10 @@ ipu_isys_buffer_to_fw_frame_buff_pin(struct vb2_buffer *vb, struct ipu_fw_isys_frame_buff_set_abi *set) { struct ipu_isys_queue *aq = vb2_queue_to_ipu_isys_queue(vb->vb2_queue); + struct ipu_isys_video *av = container_of(aq, struct ipu_isys_video, aq); + + if (av->compression) + set->output_pins[aq->fw_output].compress = 1; set->output_pins[aq->fw_output].addr = vb2_dma_contig_plane_dma_addr(vb, 0); diff --git a/drivers/media/pci/intel/ipu-isys-video.c b/drivers/media/pci/intel/ipu-isys-video.c index a4088b30c144..d1c76ee4c3de 100644 --- a/drivers/media/pci/intel/ipu-isys-video.c +++ b/drivers/media/pci/intel/ipu-isys-video.c @@ -154,7 +154,7 @@ static int video_open(struct file *file) if (rval) goto out_power_down; - rval = v4l2_pipeline_pm_use(&av->vdev.entity, 1); + rval = v4l2_pipeline_pm_get(&av->vdev.entity); if (rval) goto out_v4l2_fh_release; @@ -199,7 +199,7 @@ static int video_open(struct file *file) out_lib_init: isys->video_opened--; mutex_unlock(&isys->mutex); - v4l2_pipeline_pm_use(&av->vdev.entity, 0); + v4l2_pipeline_pm_put(&av->vdev.entity); out_v4l2_fh_release: v4l2_fh_release(file); @@ -228,7 +228,7 @@ static int video_release(struct file *file) mutex_unlock(&av->isys->mutex); - v4l2_pipeline_pm_use(&av->vdev.entity, 0); + v4l2_pipeline_pm_put(&av->vdev.entity); if (av->isys->reset_needed) pm_runtime_put_sync(&av->isys->adev->dev); @@ -418,6 +418,43 @@ ipu_isys_video_try_fmt_vid_mplane(struct ipu_isys_video *av, max(mpix->plane_fmt[0].bytesperline, av->isys->pdata->ipdata->isys_dma_overshoot)), 1U); + if (av->compression_ctrl) + av->compression = v4l2_ctrl_g_ctrl(av->compression_ctrl); + + /* overwrite bpl/height with compression alignment */ + if (av->compression) { + u32 planar_tile_status_size, tile_status_size; + + mpix->plane_fmt[0].bytesperline = + ALIGN(mpix->plane_fmt[0].bytesperline, + IPU_ISYS_COMPRESSION_LINE_ALIGN); + mpix->height = ALIGN(mpix->height, + IPU_ISYS_COMPRESSION_HEIGHT_ALIGN); + + mpix->plane_fmt[0].sizeimage = + ALIGN(mpix->plane_fmt[0].bytesperline * mpix->height, + IPU_ISYS_COMPRESSION_PAGE_ALIGN); + + /* ISYS compression only for RAW and single plannar */ + planar_tile_status_size = + DIV_ROUND_UP_ULL((mpix->plane_fmt[0].bytesperline * + mpix->height / + IPU_ISYS_COMPRESSION_TILE_SIZE_BYTES) * + IPU_ISYS_COMPRESSION_TILE_STATUS_BITS, + BITS_PER_BYTE); + tile_status_size = ALIGN(planar_tile_status_size, + IPU_ISYS_COMPRESSION_PAGE_ALIGN); + + /* tile status buffer offsets relative to buffer base address */ + av->ts_offsets[0] = mpix->plane_fmt[0].sizeimage; + mpix->plane_fmt[0].sizeimage += tile_status_size; + + dev_dbg(&av->isys->adev->dev, + "cmprs: bpl:%d, height:%d img size:%d, ts_sz:%d\n", + mpix->plane_fmt[0].bytesperline, mpix->height, + av->ts_offsets[0], tile_status_size); + } + memset(mpix->plane_fmt[0].reserved, 0, sizeof(mpix->plane_fmt[0].reserved)); @@ -637,19 +674,17 @@ static int get_external_facing_format(struct ipu_isys_pipeline *ip, static void short_packet_queue_destroy(struct ipu_isys_pipeline *ip) { struct ipu_isys_video *av = container_of(ip, struct ipu_isys_video, ip); - unsigned long attrs; unsigned int i; - attrs = DMA_ATTR_NON_CONSISTENT; if (!ip->short_packet_bufs) return; for (i = 0; i < IPU_ISYS_SHORT_PACKET_BUFFER_NUM; i++) { if (ip->short_packet_bufs[i].buffer) - dma_free_attrs(&av->isys->adev->dev, - ip->short_packet_buffer_size, - ip->short_packet_bufs[i].buffer, - ip->short_packet_bufs[i].dma_addr, - attrs); + dma_free_noncoherent(&av->isys->adev->dev, + ip->short_packet_buffer_size, + ip->short_packet_bufs[i].buffer, + ip->short_packet_bufs[i].dma_addr, + DMA_BIDIRECTIONAL); } kfree(ip->short_packet_bufs); ip->short_packet_bufs = NULL; @@ -659,7 +694,6 @@ static int short_packet_queue_setup(struct ipu_isys_pipeline *ip) { struct ipu_isys_video *av = container_of(ip, struct ipu_isys_video, ip); struct v4l2_subdev_format source_fmt = { 0 }; - unsigned long attrs; unsigned int i; int rval; size_t buf_size; @@ -683,7 +717,6 @@ static int short_packet_queue_setup(struct ipu_isys_pipeline *ip) /* Initialize short packet queue. */ INIT_LIST_HEAD(&ip->short_packet_incoming); INIT_LIST_HEAD(&ip->short_packet_active); - attrs = DMA_ATTR_NON_CONSISTENT; ip->short_packet_bufs = kzalloc(sizeof(struct ipu_isys_private_buffer) * @@ -698,9 +731,11 @@ static int short_packet_queue_setup(struct ipu_isys_pipeline *ip) buf->ip = ip; buf->ib.type = IPU_ISYS_SHORT_PACKET_BUFFER; buf->bytesused = buf_size; - buf->buffer = dma_alloc_attrs(&av->isys->adev->dev, buf_size, - &buf->dma_addr, GFP_KERNEL, - attrs); + buf->buffer = dma_alloc_noncoherent(&av->isys->adev->dev, + buf_size, + &buf->dma_addr, + DMA_BIDIRECTIONAL, + GFP_KERNEL); if (!buf->buffer) { short_packet_queue_destroy(ip); return -ENOMEM; @@ -813,9 +848,30 @@ ipu_isys_prepare_fw_cfg_default(struct ipu_isys_video *av, pin_info->snoopable = true; pin_info->error_handling_enable = false; break; - /* snoopable sensor data to CPU */ - case IPU_FW_ISYS_PIN_TYPE_MIPI: case IPU_FW_ISYS_PIN_TYPE_RAW_SOC: + if (av->compression) { + type_index = IPU_FW_ISYS_VC1_SENSOR_DATA; + pin_info->sensor_type + = isys->sensor_types[type_index]++; + pin_info->snoopable = false; + pin_info->error_handling_enable = false; + type = isys->sensor_types[type_index]; + if (type > isys->sensor_info.vc1_data_end) + isys->sensor_types[type_index] = + isys->sensor_info.vc1_data_start; + } else { + type_index = IPU_FW_ISYS_VC0_SENSOR_DATA; + pin_info->sensor_type + = isys->sensor_types[type_index]++; + pin_info->snoopable = true; + pin_info->error_handling_enable = false; + type = isys->sensor_types[type_index]; + if (type > isys->sensor_info.vc0_data_end) + isys->sensor_types[type_index] = + isys->sensor_info.vc0_data_start; + } + break; + case IPU_FW_ISYS_PIN_TYPE_MIPI: type_index = IPU_FW_ISYS_VC0_SENSOR_DATA; pin_info->sensor_type = isys->sensor_types[type_index]++; pin_info->snoopable = true; @@ -826,6 +882,7 @@ ipu_isys_prepare_fw_cfg_default(struct ipu_isys_video *av, isys->sensor_info.vc0_data_start; break; + default: dev_err(&av->isys->adev->dev, "Unknown pin type, use metadata type as default\n"); @@ -834,6 +891,11 @@ ipu_isys_prepare_fw_cfg_default(struct ipu_isys_video *av, pin_info->snoopable = true; pin_info->error_handling_enable = false; } + if (av->compression) { + pin_info->payload_buf_size = av->mpix.plane_fmt[0].sizeimage; + pin_info->reserve_compression = av->compression; + pin_info->ts_offsets[0] = av->ts_offsets[0]; + } } static unsigned int ipu_isys_get_compression_scheme(u32 code) @@ -1660,7 +1722,7 @@ int ipu_isys_video_init(struct ipu_isys_video *av, mutex_lock(&av->mutex); - rval = video_register_device(&av->vdev, VFL_TYPE_GRABBER, -1); + rval = video_register_device(&av->vdev, VFL_TYPE_VIDEO, -1); if (rval) goto out_media_entity_cleanup; diff --git a/drivers/media/pci/intel/ipu-isys-video.h b/drivers/media/pci/intel/ipu-isys-video.h index 455b534b41f7..6d8701d28843 100644 --- a/drivers/media/pci/intel/ipu-isys-video.h +++ b/drivers/media/pci/intel/ipu-isys-video.h @@ -121,6 +121,10 @@ struct ipu_isys_video { struct ipu_isys_pipeline ip; unsigned int streaming; bool packed; + bool compression; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *compression_ctrl; + unsigned int ts_offsets[VIDEO_MAX_PLANES]; unsigned int line_header_length; /* bits */ unsigned int line_footer_length; /* bits */ diff --git a/drivers/media/pci/intel/ipu-isys.c b/drivers/media/pci/intel/ipu-isys.c index 69043915fd43..a193d7ed041c 100644 --- a/drivers/media/pci/intel/ipu-isys.c +++ b/drivers/media/pci/intel/ipu-isys.c @@ -656,6 +656,7 @@ static int isys_register_devices(struct ipu_isys *isys) rval = isys_notifier_init(isys); if (rval) goto out_isys_unregister_subdevices; + rval = v4l2_device_register_subdev_nodes(&isys->v4l2_dev); if (rval) goto out_isys_notifier_cleanup; @@ -704,7 +705,7 @@ static int isys_runtime_pm_resume(struct device *dev) ipu_trace_restore(dev); - pm_qos_update_request(&isys->pm_qos, ISYS_PM_QOS_VALUE); + cpu_latency_qos_update_request(&isys->pm_qos, ISYS_PM_QOS_VALUE); ret = ipu_buttress_start_tsc_sync(isp); if (ret) @@ -743,7 +744,7 @@ static int isys_runtime_pm_suspend(struct device *dev) isys->reset_needed = false; mutex_unlock(&isys->mutex); - pm_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); + cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); ipu_mmu_hw_cleanup(adev->mmu); @@ -810,7 +811,8 @@ static void isys_remove(struct ipu_bus_device *adev) ipu_trace_uninit(&adev->dev); isys_notifier_cleanup(isys); isys_unregister_devices(isys); - pm_qos_remove_request(&isys->pm_qos); + + cpu_latency_qos_remove_request(&isys->pm_qos); if (!isp->secure_mode) { ipu_cpd_free_pkg_dir(adev, isys->pkg_dir, @@ -825,12 +827,10 @@ static void isys_remove(struct ipu_bus_device *adev) if (isys->short_packet_source == IPU_ISYS_SHORT_PACKET_FROM_TUNIT) { u32 trace_size = IPU_ISYS_SHORT_PACKET_TRACE_BUFFER_SIZE; - unsigned long attrs; - - attrs = DMA_ATTR_NON_CONSISTENT; - dma_free_attrs(&adev->dev, trace_size, - isys->short_packet_trace_buffer, - isys->short_packet_trace_buffer_dma_addr, attrs); + dma_free_noncoherent(&adev->dev, trace_size, + isys->short_packet_trace_buffer, + isys->short_packet_trace_buffer_dma_addr, + DMA_BIDIRECTIONAL); } } @@ -1142,8 +1142,7 @@ static int isys_probe(struct ipu_bus_device *adev) ipu_trace_init(adev->isp, isys->pdata->base, &adev->dev, isys_trace_blocks); - pm_qos_add_request(&isys->pm_qos, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); + cpu_latency_qos_add_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE); alloc_fw_msg_bufs(isys, 20); rval = isys_register_devices(isys); diff --git a/drivers/media/pci/intel/ipu-mmu.c b/drivers/media/pci/intel/ipu-mmu.c index f570d5e08eef..476ef7b5cc2e 100644 --- a/drivers/media/pci/intel/ipu-mmu.c +++ b/drivers/media/pci/intel/ipu-mmu.c @@ -455,7 +455,7 @@ int ipu_mmu_hw_init(struct ipu_mmu *mmu) } EXPORT_SYMBOL(ipu_mmu_hw_init); -struct ipu_mmu_info *ipu_mmu_alloc(struct ipu_device *isp) +static struct ipu_mmu_info *ipu_mmu_alloc(struct ipu_device *isp) { struct ipu_mmu_info *mmu_info; void *ptr; @@ -551,7 +551,7 @@ phys_addr_t ipu_mmu_iova_to_phys(struct ipu_mmu_info *mmu_info, << ISP_PAGE_SHIFT; } -/** +/* * The following four functions are implemented based on iommu.c * drivers/iommu/iommu.c/iommu_pgsize(). */ diff --git a/drivers/media/pci/intel/ipu-psys-compat32.c b/drivers/media/pci/intel/ipu-psys-compat32.c index 5283c85bd57b..ba13127d946e 100644 --- a/drivers/media/pci/intel/ipu-psys-compat32.c +++ b/drivers/media/pci/intel/ipu-psys-compat32.c @@ -204,11 +204,10 @@ long ipu_psys_compat_ioctl32(struct file *file, unsigned int cmd, if (compatible_arg) { err = native_ioctl(file, cmd, (unsigned long)up); } else { - mm_segment_t old_fs = get_fs(); + mm_segment_t old_fs = force_uaccess_begin(); - set_fs(KERNEL_DS); err = native_ioctl(file, cmd, (unsigned long)&karg); - set_fs(old_fs); + force_uaccess_end(old_fs); } if (err) diff --git a/drivers/media/pci/intel/ipu-psys.c b/drivers/media/pci/intel/ipu-psys.c index 904884f244b3..0efed22ae8b8 100644 --- a/drivers/media/pci/intel/ipu-psys.c +++ b/drivers/media/pci/intel/ipu-psys.c @@ -162,7 +162,7 @@ static int ipu_psys_get_userpages(struct ipu_dma_buf_attach *attach) if (!pages) goto free_sgt; - down_read(¤t->mm->mmap_sem); + mmap_read_lock(current->mm); vma = find_vma(current->mm, start); if (!vma) { ret = -EFAULT; @@ -201,7 +201,7 @@ static int ipu_psys_get_userpages(struct ipu_dma_buf_attach *attach) if (nr < npages) goto error_up_read; } - up_read(¤t->mm->mmap_sem); + mmap_read_unlock(current->mm); attach->pages = pages; attach->npages = npages; @@ -218,7 +218,7 @@ static int ipu_psys_get_userpages(struct ipu_dma_buf_attach *attach) return 0; error_up_read: - up_read(¤t->mm->mmap_sem); + mmap_read_unlock(current->mm); error: if (!attach->vma_is_io) while (nr > 0) @@ -364,8 +364,7 @@ static void *ipu_dma_buf_vmap(struct dma_buf *dmabuf) if (!ipu_attach || !ipu_attach->pages || !ipu_attach->npages) return NULL; - return vm_map_ram(ipu_attach->pages, - ipu_attach->npages, 0, PAGE_KERNEL); + return vm_map_ram(ipu_attach->pages, ipu_attach->npages, 0); } static void ipu_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) diff --git a/drivers/media/pci/intel/ipu-psys.h b/drivers/media/pci/intel/ipu-psys.h index 61ff388f8458..7a1d7d42c98d 100644 --- a/drivers/media/pci/intel/ipu-psys.h +++ b/drivers/media/pci/intel/ipu-psys.h @@ -13,7 +13,7 @@ #include "ipu-platform-psys.h" #define IPU_PSYS_PG_POOL_SIZE 16 -#define IPU_PSYS_PG_MAX_SIZE 2048 +#define IPU_PSYS_PG_MAX_SIZE 8192 #define IPU_MAX_PSYS_CMD_BUFFERS 32 #define IPU_PSYS_EVENT_CMD_COMPLETE IPU_FW_PSYS_EVENT_TYPE_SUCCESS #define IPU_PSYS_EVENT_FRAGMENT_COMPLETE IPU_FW_PSYS_EVENT_TYPE_SUCCESS diff --git a/drivers/media/pci/intel/ipu-trace.c b/drivers/media/pci/intel/ipu-trace.c index 10e4d5c68619..b3042993298a 100644 --- a/drivers/media/pci/intel/ipu-trace.c +++ b/drivers/media/pci/intel/ipu-trace.c @@ -160,10 +160,12 @@ static void __ipu_trace_restore(struct device *dev) if (!sys->memory.memory_buffer) { sys->memory.memory_buffer = - dma_alloc_attrs(dev, MEMORY_RING_BUFFER_SIZE + - MEMORY_RING_BUFFER_GUARD, - &sys->memory.dma_handle, - GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); + dma_alloc_noncoherent(dev, + MEMORY_RING_BUFFER_SIZE + + MEMORY_RING_BUFFER_GUARD, + &sys->memory.dma_handle, + DMA_BIDIRECTIONAL, + GFP_KERNEL); } if (!sys->memory.memory_buffer) { @@ -810,11 +812,11 @@ void ipu_trace_uninit(struct device *dev) mutex_lock(&trace->lock); if (sys->memory.memory_buffer) - dma_free_attrs(sys->dev, - MEMORY_RING_BUFFER_SIZE + - MEMORY_RING_BUFFER_GUARD, - sys->memory.memory_buffer, - sys->memory.dma_handle, DMA_ATTR_NON_CONSISTENT); + dma_free_noncoherent(sys->dev, + MEMORY_RING_BUFFER_SIZE + MEMORY_RING_BUFFER_GUARD, + sys->memory.memory_buffer, + sys->memory.dma_handle, + DMA_BIDIRECTIONAL); sys->dev = NULL; sys->memory.memory_buffer = NULL; diff --git a/drivers/media/pci/intel/ipu.c b/drivers/media/pci/intel/ipu.c index 84f301c72571..40d7268615b1 100644 --- a/drivers/media/pci/intel/ipu.c +++ b/drivers/media/pci/intel/ipu.c @@ -47,6 +47,10 @@ static struct ipu_bus_device *ipu_isys_init(struct pci_dev *pdev, pdata->base = base; pdata->ipdata = ipdata; + /* Use 250MHz for ipu6 se */ + if (ipu_ver == IPU_VER_6SE) + ctrl->ratio = IPU6SE_IS_FREQ_CTL_DEFAULT_RATIO; + isys = ipu_bus_add_device(pdev, parent, pdata, ctrl, IPU_ISYS_NAME, nr); if (IS_ERR(isys)) @@ -430,6 +434,8 @@ static int ipu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return rval; } + dma_set_max_seg_size(&pdev->dev, UINT_MAX); + rval = ipu_pci_config_setup(pdev); if (rval) return rval; diff --git a/drivers/media/pci/intel/ipu6/Makefile b/drivers/media/pci/intel/ipu6/Makefile index d845028191e8..f2aeade54082 100644 --- a/drivers/media/pci/intel/ipu6/Makefile +++ b/drivers/media/pci/intel/ipu6/Makefile @@ -18,7 +18,7 @@ intel-ipu6-objs += ../ipu.o \ ipu6.o \ ../ipu-fw-com.o -obj-$(CONFIG_VIDEO_INTEL_IPU) += intel-ipu6.o +obj-$(CONFIG_VIDEO_INTEL_IPU6) += intel-ipu6.o intel-ipu6-isys-objs += ../ipu-isys.o \ ../ipu-isys-csi2.o \ @@ -37,7 +37,7 @@ ifdef CONFIG_VIDEO_INTEL_IPU_TPG intel-ipu6-isys-objs += ../ipu-isys-tpg.o endif -obj-$(CONFIG_VIDEO_INTEL_IPU) += intel-ipu6-isys.o +obj-$(CONFIG_VIDEO_INTEL_IPU6) += intel-ipu6-isys.o intel-ipu6-psys-objs += ../ipu-psys.o \ ipu6-psys.o \ @@ -55,7 +55,7 @@ ifeq ($(CONFIG_COMPAT),y) intel-ipu6-psys-objs += ../ipu-psys-compat32.o endif -obj-$(CONFIG_VIDEO_INTEL_IPU) += intel-ipu6-psys.o +obj-$(CONFIG_VIDEO_INTEL_IPU6) += intel-ipu6-psys.o ccflags-y += -I$(srcpath)/$(src)/../../../../../include/ ccflags-y += -I$(srcpath)/$(src)/../ diff --git a/drivers/media/pci/intel/ipu6/ipu-platform-buttress-regs.h b/drivers/media/pci/intel/ipu6/ipu-platform-buttress-regs.h index e91524c8e7f7..343d75bd4cc6 100644 --- a/drivers/media/pci/intel/ipu6/ipu-platform-buttress-regs.h +++ b/drivers/media/pci/intel/ipu6/ipu-platform-buttress-regs.h @@ -21,8 +21,9 @@ #define IPU_BUTTRESS_PS_FREQ_CTL_DIVISOR_MASK 0xff /* should be tuned for real silicon */ -#define IPU_IS_FREQ_CTL_DEFAULT_RATIO 0x08 -#define IPU_PS_FREQ_CTL_DEFAULT_RATIO 0x10 +#define IPU_IS_FREQ_CTL_DEFAULT_RATIO 0x08 +#define IPU6SE_IS_FREQ_CTL_DEFAULT_RATIO 0x0a +#define IPU_PS_FREQ_CTL_DEFAULT_RATIO 0x10 #define IPU_IS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO 0x10 #define IPU_PS_FREQ_CTL_DEFAULT_QOS_FLOOR_RATIO 0x0708 @@ -69,6 +70,7 @@ #define BUTTRESS_FREQ_CTL_START BIT(31) #define BUTTRESS_FREQ_CTL_START_SHIFT 31 #define BUTTRESS_FREQ_CTL_QOS_FLOOR_SHIFT 8 +#define BUTTRESS_FREQ_CTL_ICCMAX_LEVEL (GENMASK(19, 16)) #define BUTTRESS_FREQ_CTL_QOS_FLOOR_MASK (0xff << 8) #define BUTTRESS_REG_PWR_STATE 0x5c diff --git a/drivers/media/pci/intel/ipu6/ipu-platform-isys.h b/drivers/media/pci/intel/ipu6/ipu-platform-isys.h index 886947870387..82ca971cd996 100644 --- a/drivers/media/pci/intel/ipu6/ipu-platform-isys.h +++ b/drivers/media/pci/intel/ipu6/ipu-platform-isys.h @@ -15,4 +15,12 @@ IPU_ISYS_UNISPART_IRQ_CSI0 | \ IPU_ISYS_UNISPART_IRQ_CSI1) +/* IPU6 ISYS compression alignment */ +#define IPU_ISYS_COMPRESSION_LINE_ALIGN 512 +#define IPU_ISYS_COMPRESSION_HEIGHT_ALIGN 1 +#define IPU_ISYS_COMPRESSION_TILE_SIZE_BYTES 512 +#define IPU_ISYS_COMPRESSION_PAGE_ALIGN 0x1000 +#define IPU_ISYS_COMPRESSION_TILE_STATUS_BITS 4 +#define IPU_ISYS_COMPRESSION_MAX 3 + #endif diff --git a/drivers/media/pci/intel/ipu6/ipu-platform-psys.h b/drivers/media/pci/intel/ipu6/ipu-platform-psys.h index 5573e617d2b9..e44eaf3b580f 100644 --- a/drivers/media/pci/intel/ipu6/ipu-platform-psys.h +++ b/drivers/media/pci/intel/ipu6/ipu-platform-psys.h @@ -69,7 +69,8 @@ struct ipu_psys_buffer_set { }; int ipu_psys_kcmd_start(struct ipu_psys *psys, struct ipu_psys_kcmd *kcmd); -void ipu_psys_kcmd_complete(struct ipu_psys_ppg *kppg, struct ipu_psys_kcmd *kcmd, +void ipu_psys_kcmd_complete(struct ipu_psys_ppg *kppg, + struct ipu_psys_kcmd *kcmd, int error); int ipu_psys_fh_init(struct ipu_psys_fh *fh); int ipu_psys_fh_deinit(struct ipu_psys_fh *fh); diff --git a/drivers/media/pci/intel/ipu6/ipu-resources.c b/drivers/media/pci/intel/ipu6/ipu-resources.c index 418dd55c1e3a..5a2dd03a85c5 100644 --- a/drivers/media/pci/intel/ipu6/ipu-resources.c +++ b/drivers/media/pci/intel/ipu6/ipu-resources.c @@ -242,7 +242,6 @@ static int __alloc_one_resrc(const struct device *dev, const u16 resource_req = pm->dev_chn_size[resource_id]; const u16 resource_offset_req = pm->dev_chn_offset[resource_id]; unsigned long retl; - const struct ipu_fw_resource_definitions *res_defs; if (resource_req <= 0) return 0; @@ -251,7 +250,6 @@ static int __alloc_one_resrc(const struct device *dev, dev_err(dev, "out of resource handles\n"); return -ENOSPC; } - res_defs = get_res(); if (resource_offset_req != (u16)(-1)) retl = ipu_resource_alloc_with_pos (resource, diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c b/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c index 6c2885a3d564..4b646783704d 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c +++ b/drivers/media/pci/intel/ipu6/ipu6-fw-resources.c @@ -426,24 +426,6 @@ const struct ipu_fw_resource_definitions *ipu6_res_defs = &ipu6_defs; /********** Generic resource handling **********/ -/* - * Extension library gives byte offsets to its internal structures. - * use those offsets to update fields. Without extension lib access - * structures directly. - */ -int ipu6_fw_psys_set_process_cell_id(struct ipu_fw_psys_process *ptr, u8 index, - u8 value) -{ - struct ipu_fw_psys_process_group *parent = - (struct ipu_fw_psys_process_group *)((char *)ptr + - ptr->parent_offset); - - ptr->cells[index] = value; - parent->resource_bitmap |= 1 << value; - - return 0; -} - int ipu6_fw_psys_set_proc_dev_chn(struct ipu_fw_psys_process *ptr, u16 offset, u16 value) { @@ -565,7 +547,6 @@ void ipu6_fw_psys_pg_dump(struct ipu_psys *psys, u8 processes = pg->process_count; u16 *process_offset_table = (u16 *)((char *)pg + pg->processes_offset); unsigned int p, chn, mem, mem_id; - int cell; dev_dbg(&psys->adev->dev, "%s %s pgid %i has %i processes:\n", __func__, note, pgid, processes); @@ -577,7 +558,6 @@ void ipu6_fw_psys_pg_dump(struct ipu_psys *psys, struct ipu6_fw_psys_process_ext *pm_ext = (struct ipu6_fw_psys_process_ext *)((u8 *)process + process->process_extension_offset); - cell = process->cells[0]; dev_dbg(&psys->adev->dev, "\t process %i size=%u", p, process->size); if (!process->process_extension_offset) diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c index afd84e5ca814..86d895e0640c 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c @@ -355,7 +355,7 @@ int ipu_isys_csi2_set_stream(struct v4l2_subdev *sd, IPU6SE_CSI_RX_ERROR_IRQ_MASK; if (!enable) { - ipu_isys_csi2_error(csi2); + writel(0, csi2->base + CSI_REG_CSI_FE_ENABLE); writel(0, csi2->base + CSI_REG_PPI2CSI_ENABLE); diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c b/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c index 227a5ba9ed03..bd8044255efe 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c @@ -178,20 +178,14 @@ int ipu_isys_gpc_init_debugfs(struct ipu_isys *isys) if (IS_ERR(file)) goto err; - file = debugfs_create_u32("source", 0600, dir, - &isys_gpcs->gpc[i].source); - if (IS_ERR(file)) - goto err; + debugfs_create_u32("source", 0600, dir, + &isys_gpcs->gpc[i].source); - file = debugfs_create_u32("route", 0600, dir, - &isys_gpcs->gpc[i].route); - if (IS_ERR(file)) - goto err; + debugfs_create_u32("route", 0600, dir, + &isys_gpcs->gpc[i].route); - file = debugfs_create_u32("sense", 0600, dir, - &isys_gpcs->gpc[i].sense); - if (IS_ERR(file)) - goto err; + debugfs_create_u32("sense", 0600, dir, + &isys_gpcs->gpc[i].sense); isys_gpcs->gpc[i].gpcindex = i; isys_gpcs->gpc[i].prit = isys; diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c b/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c index 82d457fc8d64..a1165e718def 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-phy.c @@ -555,7 +555,8 @@ static int ipu6_isys_driver_port_to_phy_port(struct ipu_isys_csi2_config *cfg) int ipu6_isys_phy_config(struct ipu_isys *isys) { - unsigned int phy_port, phy_id; + int phy_port; + unsigned int phy_id; void __iomem *phy_base; struct ipu_bus_device *adev = to_ipu_bus_device(&isys->adev->dev); struct ipu_device *isp = adev->isp; @@ -592,23 +593,3 @@ int ipu6_isys_phy_config(struct ipu_isys *isys) return 0; } - -void __maybe_unused ipu6_isys_phy_dump_status(struct ipu_isys *isys, - struct ipu_isys_csi2_config *cfg) -{ - unsigned int port, phy_id, nlanes; - struct ipu_bus_device *adev = to_ipu_bus_device(&isys->adev->dev); - struct ipu_device *isp = adev->isp; - void __iomem *isp_base = isp->base; - void __iomem *cbbs1_base; - - port = cfg->port; - phy_id = port / 4; - nlanes = cfg->nlanes; - cbbs1_base = isp_base + IPU6_ISYS_PHY_BASE(phy_id) + PHY_CBBS1_BASE; - - dev_dbg(&isys->adev->dev, "phy rcomp_status 0x%08x, cbb_status 0x%08x", - readl(cbbs1_base + PHY_CBBS1_RCOMP_STATUS_REG_1), - readl(cbbs1_base + PHY_CBBS1_CBB_STATUS_REG)); - -} diff --git a/drivers/media/pci/intel/ipu6/ipu6-l-scheduler.c b/drivers/media/pci/intel/ipu6/ipu6-l-scheduler.c index eed5022b88d3..3d3cd0c0841f 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-l-scheduler.c +++ b/drivers/media/pci/intel/ipu6/ipu6-l-scheduler.c @@ -145,7 +145,7 @@ static int ipu_psys_detect_resource_contention(struct ipu_psys_ppg *kppg) static void ipu_psys_scheduler_ppg_sort(struct ipu_psys *psys, bool *stopping) { - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_scheduler *sched; struct ipu_psys_fh *fh; @@ -158,7 +158,7 @@ static void ipu_psys_scheduler_ppg_sort(struct ipu_psys *psys, bool *stopping) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); if (kppg->state == PPG_STATE_START || kppg->state == PPG_STATE_RESUME) { @@ -184,11 +184,11 @@ static void ipu_psys_scheduler_ppg_sort(struct ipu_psys *psys, bool *stopping) static void ipu_psys_scheduler_update_start_ppg_priority(void) { struct sched_list *sc_list = get_sc_list(SCHED_START_LIST); - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; mutex_lock(&sc_list->lock); if (!list_empty(&sc_list->list)) - list_for_each_entry(kppg, &sc_list->list, sched_list) + list_for_each_entry_safe(kppg, tmp, &sc_list->list, sched_list) kppg->pri_dynamic--; mutex_unlock(&sc_list->lock); } @@ -324,7 +324,7 @@ static bool ipu_psys_scheduler_ppg_enqueue_bufset(struct ipu_psys *psys) static bool ipu_psys_scheduler_ppg_halt(struct ipu_psys *psys) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; bool stopping_exit = false; @@ -336,7 +336,7 @@ static bool ipu_psys_scheduler_ppg_halt(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); if (kppg->state & PPG_STATE_STOP) { ipu_psys_ppg_stop(kppg); @@ -407,7 +407,7 @@ static void ipu_psys_scheduler_kcmd_set(struct ipu_psys *psys) { struct ipu_psys_kcmd *kcmd; struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; list_for_each_entry(fh, &psys->fhs, list) { @@ -418,7 +418,7 @@ static void ipu_psys_scheduler_kcmd_set(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); if (list_empty(&kppg->kcmds_new_list)) { mutex_unlock(&kppg->mutex); @@ -437,7 +437,7 @@ static void ipu_psys_scheduler_kcmd_set(struct ipu_psys *psys) static bool is_ready_to_enter_power_gating(struct ipu_psys *psys) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; list_for_each_entry(fh, &psys->fhs, list) { @@ -448,7 +448,7 @@ static bool is_ready_to_enter_power_gating(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); if (!list_empty(&kppg->kcmds_new_list) || !list_empty(&kppg->kcmds_processing_list)) { @@ -474,7 +474,7 @@ static bool is_ready_to_enter_power_gating(struct ipu_psys *psys) static bool has_pending_kcmd(struct ipu_psys *psys) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; list_for_each_entry(fh, &psys->fhs, list) { @@ -485,7 +485,7 @@ static bool has_pending_kcmd(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); if (!list_empty(&kppg->kcmds_new_list) || !list_empty(&kppg->kcmds_processing_list)) { @@ -515,7 +515,7 @@ static bool ipu_psys_scheduler_exit_power_gating(struct ipu_psys *psys) static bool ipu_psys_scheduler_enter_power_gating(struct ipu_psys *psys) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; if (!enable_power_gating) @@ -540,7 +540,7 @@ static bool ipu_psys_scheduler_enter_power_gating(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); if (kppg->state == PPG_STATE_RUNNING) { kppg->state = PPG_STATE_SUSPEND; diff --git a/drivers/media/pci/intel/ipu6/ipu6-ppg.c b/drivers/media/pci/intel/ipu6/ipu6-ppg.c index 22b602306b4a..a6860df5db18 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-ppg.c +++ b/drivers/media/pci/intel/ipu6/ipu6-ppg.c @@ -121,12 +121,9 @@ int ipu_psys_ppg_get_bufset(struct ipu_psys_kcmd *kcmd, { struct ipu_psys *psys = kppg->fh->psys; struct ipu_psys_buffer_set *kbuf_set; - size_t buf_set_size; unsigned int i; int ret; - buf_set_size = ipu_fw_psys_ppg_get_buffer_set_size(kcmd); - kbuf_set = ipu_psys_create_buffer_set(kcmd, kppg); if (!kbuf_set) { ret = -EINVAL; @@ -171,7 +168,6 @@ void ipu_psys_ppg_complete(struct ipu_psys *psys, struct ipu_psys_ppg *kppg) mutex_lock(&kppg->mutex); old_ppg_state = kppg->state; if (kppg->state == PPG_STATE_STOPPING) { - unsigned long flags; struct ipu_psys_kcmd tmp_kcmd = { .kpg = kppg->kpg, }; @@ -182,9 +178,6 @@ void ipu_psys_ppg_complete(struct ipu_psys *psys, struct ipu_psys_ppg *kppg) queue_id = ipu_fw_psys_ppg_get_base_queue_id(&tmp_kcmd); ipu_psys_free_cmd_queue_resource(&psys->resource_pool_running, queue_id); - spin_lock_irqsave(&psys->pgs_lock, flags); - kppg->kpg->pg_size = 0; - spin_unlock_irqrestore(&psys->pgs_lock, flags); pm_runtime_put(&psys->adev->dev); } else { if (kppg->state == PPG_STATE_SUSPENDING) { @@ -391,21 +384,18 @@ int ipu_psys_ppg_stop(struct ipu_psys_ppg *kppg) dev_err(&psys->adev->dev, "ppg(%d) failed to resume\n", ppg_id); } else if (kcmd != &kcmd_temp) { - unsigned long flags; - ipu_psys_free_cmd_queue_resource( &psys->resource_pool_running, ipu_fw_psys_ppg_get_base_queue_id(kcmd)); ipu_psys_kcmd_complete(kppg, kcmd, 0); - spin_lock_irqsave(&psys->pgs_lock, flags); - kppg->kpg->pg_size = 0; - spin_unlock_irqrestore(&psys->pgs_lock, flags); dev_dbg(&psys->adev->dev, "s_change:%s %p %d -> %d\n", __func__, kppg, kppg->state, PPG_STATE_STOPPED); pm_runtime_put(&psys->adev->dev); kppg->state = PPG_STATE_STOPPED; return 0; + } else { + return 0; } } dev_dbg(&psys->adev->dev, "s_change:%s %p %d -> %d\n", @@ -499,7 +489,7 @@ bool ipu_psys_ppg_enqueue_bufsets(struct ipu_psys_ppg *kppg) void ipu_psys_enter_power_gating(struct ipu_psys *psys) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; int ret = 0; @@ -511,7 +501,7 @@ void ipu_psys_enter_power_gating(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); /* kppg has already power down */ if (kppg->state == PPG_STATE_STOPPED) { @@ -535,7 +525,7 @@ void ipu_psys_enter_power_gating(struct ipu_psys *psys) void ipu_psys_exit_power_gating(struct ipu_psys *psys) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; int ret = 0; @@ -547,7 +537,7 @@ void ipu_psys_exit_power_gating(struct ipu_psys *psys) continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); /* kppg is not started and power up */ if (kppg->state == PPG_STATE_START || diff --git a/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c b/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c index 4d8ef61d8449..3bf35d245a4f 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c +++ b/drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c @@ -185,20 +185,14 @@ int ipu_psys_gpc_init_debugfs(struct ipu_psys *psys) if (IS_ERR(file)) goto err; - file = debugfs_create_u32("source", 0600, dir, - &psys_gpcs->gpc[idx].source); - if (IS_ERR(file)) - goto err; + debugfs_create_u32("source", 0600, dir, + &psys_gpcs->gpc[idx].source); - file = debugfs_create_u32("route", 0600, dir, - &psys_gpcs->gpc[idx].route); - if (IS_ERR(file)) - goto err; + debugfs_create_u32("route", 0600, dir, + &psys_gpcs->gpc[idx].route); - file = debugfs_create_u32("sense", 0600, dir, - &psys_gpcs->gpc[idx].sense); - if (IS_ERR(file)) - goto err; + debugfs_create_u32("sense", 0600, dir, + &psys_gpcs->gpc[idx].sense); psys_gpcs->gpc[idx].gpcindex = idx; psys_gpcs->gpc[idx].prit = psys; diff --git a/drivers/media/pci/intel/ipu6/ipu6-psys.c b/drivers/media/pci/intel/ipu6/ipu6-psys.c index 10c6366c60c9..06560b91948b 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-psys.c +++ b/drivers/media/pci/intel/ipu6/ipu6-psys.c @@ -161,13 +161,13 @@ void ipu_psys_setup_hw(struct ipu_psys *psys) static struct ipu_psys_ppg *ipu_psys_identify_kppg(struct ipu_psys_kcmd *kcmd) { struct ipu_psys_scheduler *sched = &kcmd->fh->sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; mutex_lock(&kcmd->fh->mutex); if (list_empty(&sched->ppgs)) goto not_found; - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { if (ipu_fw_psys_pg_get_token(kcmd) != kppg->token) continue; @@ -184,7 +184,7 @@ static struct ipu_psys_ppg *ipu_psys_identify_kppg(struct ipu_psys_kcmd *kcmd) * Called to free up all resources associated with a kcmd. * After this the kcmd doesn't anymore exist in the driver. */ -void ipu_psys_kcmd_free(struct ipu_psys_kcmd *kcmd) +static void ipu_psys_kcmd_free(struct ipu_psys_kcmd *kcmd) { struct ipu_psys_ppg *kppg; struct ipu_psys_scheduler *sched; @@ -421,7 +421,7 @@ static struct ipu_psys_ppg *ipu_psys_lookup_ppg(struct ipu_psys *psys, dma_addr_t pg_addr) { struct ipu_psys_scheduler *sched; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_fh *fh; list_for_each_entry(fh, &psys->fhs, list) { @@ -432,7 +432,7 @@ static struct ipu_psys_ppg *ipu_psys_lookup_ppg(struct ipu_psys *psys, continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { if (pg_addr != kppg->kpg->pg_dma_addr) continue; mutex_unlock(&fh->mutex); @@ -654,9 +654,6 @@ static int ipu_psys_kcmd_send_to_ppg(struct ipu_psys_kcmd *kcmd) id = ipu_fw_psys_ppg_get_base_queue_id(kcmd); ipu_psys_free_cmd_queue_resource(rpr, id); ipu_psys_kcmd_complete(kppg, kcmd, 0); - spin_lock_irqsave(&psys->pgs_lock, flags); - kppg->kpg->pg_size = 0; - spin_unlock_irqrestore(&psys->pgs_lock, flags); pm_runtime_put(&psys->adev->dev); resche = false; } else { @@ -740,7 +737,7 @@ static bool ipu_psys_kcmd_is_valid(struct ipu_psys *psys, { struct ipu_psys_fh *fh; struct ipu_psys_kcmd *kcmd0; - struct ipu_psys_ppg *kppg; + struct ipu_psys_ppg *kppg, *tmp; struct ipu_psys_scheduler *sched; list_for_each_entry(fh, &psys->fhs, list) { @@ -750,7 +747,7 @@ static bool ipu_psys_kcmd_is_valid(struct ipu_psys *psys, mutex_unlock(&fh->mutex); continue; } - list_for_each_entry(kppg, &sched->ppgs, list) { + list_for_each_entry_safe(kppg, tmp, &sched->ppgs, list) { mutex_lock(&kppg->mutex); list_for_each_entry(kcmd0, &kppg->kcmds_processing_list, @@ -920,12 +917,12 @@ int ipu_psys_fh_deinit(struct ipu_psys_fh *fh) mutex_lock(&fh->mutex); if (!list_empty(&sched->ppgs)) { list_for_each_entry_safe(kppg, kppg0, &sched->ppgs, list) { - mutex_unlock(&fh->mutex); + unsigned long flags; + mutex_lock(&kppg->mutex); if (!(kppg->state & (PPG_STATE_STOPPED | PPG_STATE_STOPPING))) { - unsigned long flags; struct ipu_psys_kcmd tmp = { .kpg = kppg->kpg, }; @@ -940,42 +937,45 @@ int ipu_psys_fh_deinit(struct ipu_psys_fh *fh) "s_change:%s %p %d -> %d\n", __func__, kppg, kppg->state, PPG_STATE_STOPPED); kppg->state = PPG_STATE_STOPPED; - spin_lock_irqsave(&psys->pgs_lock, flags); - kppg->kpg->pg_size = 0; - spin_unlock_irqrestore(&psys->pgs_lock, flags); if (psys->power_gating != PSYS_POWER_GATED) pm_runtime_put(&psys->adev->dev); } + list_del(&kppg->list); mutex_unlock(&kppg->mutex); list_for_each_entry_safe(kcmd, kcmd0, &kppg->kcmds_new_list, list) { kcmd->pg_user = NULL; + mutex_unlock(&fh->mutex); ipu_psys_kcmd_free(kcmd); + mutex_lock(&fh->mutex); } list_for_each_entry_safe(kcmd, kcmd0, &kppg->kcmds_processing_list, list) { kcmd->pg_user = NULL; + mutex_unlock(&fh->mutex); ipu_psys_kcmd_free(kcmd); + mutex_lock(&fh->mutex); } list_for_each_entry_safe(kcmd, kcmd0, &kppg->kcmds_finished_list, list) { kcmd->pg_user = NULL; + mutex_unlock(&fh->mutex); ipu_psys_kcmd_free(kcmd); + mutex_lock(&fh->mutex); } - mutex_lock(&kppg->mutex); - list_del(&kppg->list); - mutex_unlock(&kppg->mutex); + spin_lock_irqsave(&psys->pgs_lock, flags); + kppg->kpg->pg_size = 0; + spin_unlock_irqrestore(&psys->pgs_lock, flags); mutex_destroy(&kppg->mutex); kfree(kppg->manifest); kfree(kppg); - mutex_lock(&fh->mutex); } } mutex_unlock(&fh->mutex); diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c index a404c2f301d0..da33bc952624 100644 --- a/drivers/media/pci/intel/ipu6/ipu6.c +++ b/drivers/media/pci/intel/ipu6/ipu6.c @@ -341,29 +341,6 @@ int ipu_buttress_psys_freq_get(void *data, u64 *val) return 0; } -int ipu_buttress_isys_freq_get(void *data, u64 *val) -{ - struct ipu_device *isp = data; - u32 reg_val; - int rval; - - rval = pm_runtime_get_sync(&isp->isys->dev); - if (rval < 0) { - pm_runtime_put(&isp->isys->dev); - dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n", rval); - return rval; - } - - reg_val = readl(isp->base + BUTTRESS_REG_IS_FREQ_CTL); - - pm_runtime_put(&isp->isys->dev); - - *val = IPU_IS_FREQ_RATIO_BASE * - (reg_val & IPU_BUTTRESS_IS_FREQ_CTL_DIVISOR_MASK); - - return 0; -} - void ipu_internal_pdata_init(void) { if (ipu_ver == IPU_VER_6) { diff --git a/drivers/media/pci/intel/ipu6/ipu6se-fw-resources.c b/drivers/media/pci/intel/ipu6/ipu6se-fw-resources.c index e94519a34f6b..c0413fbddef6 100644 --- a/drivers/media/pci/intel/ipu6/ipu6se-fw-resources.c +++ b/drivers/media/pci/intel/ipu6/ipu6se-fw-resources.c @@ -317,7 +317,6 @@ void ipu6se_fw_psys_pg_dump(struct ipu_psys *psys, u8 processes = pg->process_count; u16 *process_offset_table = (u16 *)((char *)pg + pg->processes_offset); unsigned int p, chn, mem, mem_id; - int cell; dev_dbg(&psys->adev->dev, "%s %s pgid %i has %i processes:\n", __func__, note, pgid, processes); @@ -329,7 +328,6 @@ void ipu6se_fw_psys_pg_dump(struct ipu_psys *psys, struct ipu6se_fw_psys_process_ext *pm_ext = (struct ipu6se_fw_psys_process_ext *)((u8 *)process + process->process_extension_offset); - cell = process->cells[0]; dev_dbg(&psys->adev->dev, "\t process %i size=%u", p, process->size); if (!process->process_extension_offset) diff --git a/include/uapi/linux/ipu-isys.h b/include/uapi/linux/ipu-isys.h index a0e657704087..4aabb14328a5 100644 --- a/include/uapi/linux/ipu-isys.h +++ b/include/uapi/linux/ipu-isys.h @@ -7,6 +7,7 @@ #define V4L2_CID_IPU_BASE (V4L2_CID_USER_BASE + 0x1080) #define V4L2_CID_IPU_STORE_CSI2_HEADER (V4L2_CID_IPU_BASE + 2) +#define V4L2_CID_IPU_ISYS_COMPRESSION (V4L2_CID_IPU_BASE + 3) #define VIDIOC_IPU_GET_DRIVER_VERSION \ _IOWR('v', BASE_VIDIOC_PRIVATE + 3, uint32_t)