]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
UBUNTU: SAUCE: IPU driver release WW52
authorWang Yating <yating.wang@intel.com>
Thu, 29 Jul 2021 06:48:23 +0000 (14:48 +0800)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Tue, 31 May 2022 16:26:26 +0000 (18:26 +0200)
BugLink: https://bugs.launchpad.net/bugs/1955383
Signed-off-by: Wang Yating <yating.wang@intel.com>
(backported from commit 71392b666a028c77126a9098fedb1fb30fc30568 github.com/intel/ipu6-drivers)
Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
Acked-by: Andrea Righi <andrea.righi@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
38 files changed:
drivers/media/i2c/hm11b1.c
drivers/media/i2c/ov01a1s.c
drivers/media/i2c/pmic_dsc1.c [new file with mode: 0644]
drivers/media/i2c/pmic_dsc1.h [new file with mode: 0644]
drivers/media/pci/intel/Kconfig
drivers/media/pci/intel/Makefile
drivers/media/pci/intel/ipu-buttress.c
drivers/media/pci/intel/ipu-buttress.h
drivers/media/pci/intel/ipu-dma.c
drivers/media/pci/intel/ipu-fw-isys.c
drivers/media/pci/intel/ipu-isys-csi2-be-soc.c
drivers/media/pci/intel/ipu-isys-csi2-be.c
drivers/media/pci/intel/ipu-isys-queue.c
drivers/media/pci/intel/ipu-isys-video.c
drivers/media/pci/intel/ipu-isys-video.h
drivers/media/pci/intel/ipu-isys.c
drivers/media/pci/intel/ipu-mmu.c
drivers/media/pci/intel/ipu-psys-compat32.c
drivers/media/pci/intel/ipu-psys.c
drivers/media/pci/intel/ipu-psys.h
drivers/media/pci/intel/ipu-trace.c
drivers/media/pci/intel/ipu.c
drivers/media/pci/intel/ipu6/Makefile
drivers/media/pci/intel/ipu6/ipu-platform-buttress-regs.h
drivers/media/pci/intel/ipu6/ipu-platform-isys.h
drivers/media/pci/intel/ipu6/ipu-platform-psys.h
drivers/media/pci/intel/ipu6/ipu-resources.c
drivers/media/pci/intel/ipu6/ipu6-fw-resources.c
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
drivers/media/pci/intel/ipu6/ipu6-isys-gpc.c
drivers/media/pci/intel/ipu6/ipu6-isys-phy.c
drivers/media/pci/intel/ipu6/ipu6-l-scheduler.c
drivers/media/pci/intel/ipu6/ipu6-ppg.c
drivers/media/pci/intel/ipu6/ipu6-psys-gpc.c
drivers/media/pci/intel/ipu6/ipu6-psys.c
drivers/media/pci/intel/ipu6/ipu6.c
drivers/media/pci/intel/ipu6/ipu6se-fw-resources.c
include/uapi/linux/ipu-isys.h

index 9c1662b842de850351bb06f6bd3c8af9a596041b..35f49eb7b852ca7c8d8caf27cc1656d505f7409d 100644 (file)
@@ -10,6 +10,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
+#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"},
        {}
 };
 
index 1d05b75347a144d1e50ba7c0325887c200c64a47..766fe30116c369a6a4696e461e5b5ed9bcec2188 100644 (file)
@@ -10,6 +10,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fwnode.h>
+#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 (file)
index 0000000..9892bc5
--- /dev/null
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2020 Intel Corporation.
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#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 <bingbu.cao@intel.com>");
+MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
+MODULE_AUTHOR("Xu, Chongyang <chongyang.xu@intel.com>");
+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 (file)
index 0000000..19f1112
--- /dev/null
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2020 Intel Corporation. */
+
+#ifndef _PMIC_DSC1_H_
+#define _PMIC_DSC1_H_
+
+#include <linux/gpio/consumer.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+
+/* 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
index 8ea99271932b06dde668a0ceee08a38c51be07a5..9017ccfc7a551cba4b985f4a7cadcb1ea8efb659 100644 (file)
@@ -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"
index a0ccb70023e5ab00686b2757e655fc41cc1b9f33..608acd574921c555d77a6158502a7cb1bcae1830 100644 (file)
@@ -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/
index 2ee8a9e554b6a084f10313f9a77d92ebc7a88722..ee014a8bea661baea49ab84503995e7d6c8770d6 100644 (file)
 
 #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 @@ out_mutex_unlock:
        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;
index 02c8b46947a1cc132ce00827535af2217ac8eb40..e1d054c3cd07505d34ad681e6aa24429bc5f591f 100644 (file)
 #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 */
index 34fa1fb6b060fd9724d2fd32efc5227b25ee4d84..2e844dd16e6121cc9716499702cc9a2ed0905360 100644 (file)
@@ -11,7 +11,9 @@
 #include <linux/iova.h>
 #include <linux/module.h>
 #include <linux/scatterlist.h>
+#include <linux/version.h>
 #include <linux/vmalloc.h>
+#include <linux/dma-map-ops.h>
 
 #include "ipu-dma.h"
 #include "ipu-bus.h"
index 974c6f59d34dd4996b78884692beb846ab8767ec..307117818a52da506900a0b64d81a68a0c03ef1d 100644 (file)
@@ -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);
index db90680e736d333b052aaae393270e882f34d092..501d5620e7e15b67d04d6c908bd76c8d048191d5 100644 (file)
@@ -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,
index 9aae37af8011f32f4ba74f694dbf20790daad324..99ceb607fedad5f8ff8a410f09ee36f86a3a1114 100644 (file)
@@ -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) {
index 10498dddaf0969c548ca318113b5d60364d353ac..1f379f0464a14d6baf3fb3db6d245a55dff7c26a 100644 (file)
@@ -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);
index a4088b30c144a2fd07c177b2403a332af3a8e1fb..d1c76ee4c3de9336e0ca2ec11ba53fe823d0db57 100644 (file)
@@ -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;
 
index 455b534b41f7cb57a09a77e3f28409e7e3ac1002..6d8701d28843b77253fb3b2c4a029614d6f7a546 100644 (file)
@@ -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 */
 
index 69043915fd436b87eb0a2d1504951dd985de99e7..a193d7ed041cf1b8137f8772054c62c032dd2711 100644 (file)
@@ -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);
index f570d5e08eef8bbd133562f55ed05a0891bb5327..476ef7b5cc2e9caee0c4540df7c964b4961fc624 100644 (file)
@@ -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().
  */
index 5283c85bd57b7f42070ebb4eff8c4c4a14e40906..ba13127d946e35f42496a75653ae4ef01ec466ed 100644 (file)
@@ -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)
index 904884f244b3facb8a0e492ca6cce3e7b57a8040..0efed22ae8b8fb565d17b66a77984bb51bda1b24 100644 (file)
@@ -162,7 +162,7 @@ static int ipu_psys_get_userpages(struct ipu_dma_buf_attach *attach)
        if (!pages)
                goto free_sgt;
 
-       down_read(&current->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(&current->mm->mmap_sem);
+       mmap_read_unlock(current->mm);
 
        attach->pages = pages;
        attach->npages = npages;
@@ -218,7 +218,7 @@ skip_pages:
        return 0;
 
 error_up_read:
-       up_read(&current->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)
index 61ff388f84588b5386f2bd6749a1c5858257bb6f..7a1d7d42c98dc4c33c13af4cd64c3bbf8934746a 100644 (file)
@@ -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
index 10e4d5c686192106034020817324d9fbf90c3165..b3042993298a79eaf34a29aa2e2277ce9a633c21 100644 (file)
@@ -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;
index 84f301c72571a786520d1f2f294d1405e553767d..40d7268615b121bdd931d4c592c95422ddac682b 100644 (file)
@@ -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;
index d845028191e84cd018d2b010a8b2890e2ecfae2c..f2aeade540827582507e928a551aa607852be1cd 100644 (file)
@@ -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)/../
index e91524c8e7f7bc02771d2969991acefae5dc651f..343d75bd4cc671729b71f7a9bfe7db2c42e2db20 100644 (file)
@@ -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
index 8869478703877122542b253e1a6f5c415773ed3b..82ca971cd99638caf826c4c7161323a95bee8650 100644 (file)
                                 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
index 5573e617d2b99e20d8728ae53fab73b8d7b11e11..e44eaf3b580f3206e81eb51ace737fcfe70fed3c 100644 (file)
@@ -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);
index 418dd55c1e3a1d8c8630b3da7850e869089786ab..5a2dd03a85c5b85951d6fe5b02159a2af5e67acf 100644 (file)
@@ -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,
index 6c2885a3d564a0b63e2431d1ff7605963267fc5d..4b646783704dbf9ce5de9d519e6762eb17b28cfe 100644 (file)
@@ -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)
index afd84e5ca814cde611d3e83e6b90e7bbf02245f5..86d895e0640c848c2d58ad3c83dc91994de3808e 100644 (file)
@@ -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);
 
index 227a5ba9ed03359147d2596f4a77de03c5bc9e44..bd8044255efe22133aba5ba99d6d3f1b59d7566e 100644 (file)
@@ -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;
index 82d457fc8d64736a29ce60f37213def004843e16..a1165e718def157accf4adfb434a866b22636d78 100644 (file)
@@ -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));
-
-}
index eed5022b88d3544d3f1c6f9758b5fc90798e118e..3d3cd0c0841fdc7332fd04cca4d72f88ba7f752c 100644 (file)
@@ -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;
index 22b602306b4aa268eb897895c3cad87118423af3..a6860df5db180304c3aa8076ea2e908a30c9dd68 100644 (file)
@@ -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 ||
index 4d8ef61d8449d5771cafac8705bf74bb82aa8d32..3bf35d245a4fc149caed83159b32c17d81d148b9 100644 (file)
@@ -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;
index 10c6366c60c96dde799adf8b48bef11c93adafd7..06560b91948b3c1e41a35efc6f8262d06ab73a95 100644 (file)
@@ -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 @@ not_found:
  * 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);
index a404c2f301d09b48f513a3fc23f26621ec2ad64b..da33bc95262416ec37f10fe902edad446c550fe2 100644 (file)
@@ -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) {
index e94519a34f6bac4f595d254560249a215061fe2b..c0413fbddef6132dbb64ef36fb473e99e7d60045 100644 (file)
@@ -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)
index a0e657704087dee6226dd099d885edd278e300cc..4aabb14328a5225a71b3e298d4eae739ae3bb6f0 100644 (file)
@@ -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)