LCOV - code coverage report
Current view: top level - ipu4 - ipu6-isys.c (source / functions) Coverage Total Hit
Test: ipu4.info Lines: 65.3 % 427 279
Test Date: 2026-05-12 04:57:36 Functions: 76.7 % 30 23

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-only
       2              : /*
       3              :  * Copyright (C) 2013--2024 Intel Corporation
       4              :  */
       5              : 
       6              : #include <linux/auxiliary_bus.h>
       7              : #include <linux/bitfield.h>
       8              : #include <linux/bits.h>
       9              : #include <linux/completion.h>
      10              : #include <linux/container_of.h>
      11              : #include <linux/delay.h>
      12              : #include <linux/device.h>
      13              : #include <linux/dma-mapping.h>
      14              : #include <linux/err.h>
      15              : #include <linux/firmware.h>
      16              : #include <linux/io.h>
      17              : #include <linux/irqreturn.h>
      18              : #include <linux/list.h>
      19              : #include <linux/module.h>
      20              : #include <linux/mutex.h>
      21              : #include <linux/pci.h>
      22              : #include <linux/pm_runtime.h>
      23              : #include <linux/pm_qos.h>
      24              : #include <linux/slab.h>
      25              : #include <linux/spinlock.h>
      26              : #include <linux/string.h>
      27              : 
      28              : #include <media/ipu-bridge.h>
      29              : #include <media/media-device.h>
      30              : #include <media/media-entity.h>
      31              : #include <media/v4l2-async.h>
      32              : #include <media/v4l2-device.h>
      33              : #include <media/v4l2-fwnode.h>
      34              : 
      35              : #include "ipu6-bus.h"
      36              : #include "ipu6-cpd.h"
      37              : #include "ipu6-dma.h"
      38              : #include "ipu6-isys.h"
      39              : #include "ipu6-isys-csi2.h"
      40              : #include "ipu6-mmu.h"
      41              : #include "ipu6-platform-buttress-regs.h"
      42              : #include "ipu6-platform-isys-csi2-reg.h"
      43              : #include "ipu6-platform-regs.h"
      44              : 
      45              : #define IPU6_BUTTRESS_FABIC_CONTROL             0x68
      46              : #define GDA_ENABLE_IWAKE_INDEX                  2
      47              : #define GDA_IWAKE_THRESHOLD_INDEX               1
      48              : #define GDA_IRQ_CRITICAL_THRESHOLD_INDEX        0
      49              : #define GDA_MEMOPEN_THRESHOLD_INDEX             3
      50              : #define DEFAULT_DID_RATIO                       90
      51              : #define DEFAULT_IWAKE_THRESHOLD                 0x42
      52              : #define DEFAULT_MEM_OPEN_TIME                   10
      53              : #define ONE_THOUSAND_MICROSECOND                1000
      54              : /* One page is 2KB, 8 x 16 x 16 = 2048B = 2KB */
      55              : #define ISF_DMA_TOP_GDA_PROFERTY_PAGE_SIZE      0x800
      56              : 
      57              : /* LTR & DID value are 10 bit at most */
      58              : #define LTR_DID_VAL_MAX                         1023
      59              : #define LTR_DEFAULT_VALUE                       0x70503c19
      60              : #define FILL_TIME_DEFAULT_VALUE                 0xfff0783c
      61              : #define LTR_DID_PKGC_2R                         20
      62              : #define LTR_SCALE_DEFAULT                       5
      63              : #define LTR_SCALE_1024NS                        2
      64              : #define DID_SCALE_1US                           2
      65              : #define DID_SCALE_32US                          3
      66              : #define REG_PKGC_PMON_CFG                       0xb00
      67              : 
      68              : #define VAL_PKGC_PMON_CFG_RESET                 0x38
      69              : #define VAL_PKGC_PMON_CFG_START                 0x7
      70              : 
      71              : #define IS_PIXEL_BUFFER_PAGES                   0x80
      72              : /*
      73              :  * when iwake mode is disabled, the critical threshold is statically set
      74              :  * to 75% of the IS pixel buffer, criticalThreshold = (128 * 3) / 4
      75              :  */
      76              : #define CRITICAL_THRESHOLD_IWAKE_DISABLE        (IS_PIXEL_BUFFER_PAGES * 3 / 4)
      77              : 
      78              : union fabric_ctrl {
      79              :         struct {
      80              :                 u16 ltr_val   : 10;
      81              :                 u16 ltr_scale : 3;
      82              :                 u16 reserved  : 3;
      83              :                 u16 did_val   : 10;
      84              :                 u16 did_scale : 3;
      85              :                 u16 reserved2 : 1;
      86              :                 u16 keep_power_in_D0   : 1;
      87              :                 u16 keep_power_override : 1;
      88              :         } bits;
      89              :         u32 value;
      90              : };
      91              : 
      92              : enum ltr_did_type {
      93              :         LTR_IWAKE_ON,
      94              :         LTR_IWAKE_OFF,
      95              :         LTR_ISYS_ON,
      96              :         LTR_ISYS_OFF,
      97              :         LTR_ENHANNCE_IWAKE,
      98              :         LTR_TYPE_MAX
      99              : };
     100              : 
     101              : #define ISYS_PM_QOS_VALUE       300
     102              : 
     103              : static int isys_isr_one(struct ipu6_bus_device *adev);
     104              : 
     105              : static int
     106            1 : isys_complete_ext_device_registration(struct ipu6_isys *isys,
     107              :                                       struct v4l2_subdev *sd,
     108              :                                       struct ipu6_isys_csi2_config *csi2)
     109              : {
     110            1 :         struct device *dev = &isys->adev->auxdev.dev;
     111              :         unsigned int i;
     112              :         int ret;
     113              : 
     114            1 :         for (i = 0; i < sd->entity.num_pads; i++) {
     115            1 :                 if (sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
     116              :                         break;
     117              :         }
     118              : 
     119            1 :         if (i == sd->entity.num_pads) {
     120            0 :                 dev_warn(dev, "no src pad in external entity\n");
     121              :                 ret = -ENOENT;
     122            0 :                 goto unregister_subdev;
     123              :         }
     124              : 
     125            1 :         ret = media_create_pad_link(&sd->entity, i,
     126            1 :                                     &isys->csi2[csi2->port].asd.sd.entity,
     127              :                                     0, MEDIA_LNK_FL_ENABLED |
     128              :                                        MEDIA_LNK_FL_IMMUTABLE);
     129            1 :         if (ret) {
     130            0 :                 dev_warn(dev, "can't create link\n");
     131            0 :                 goto unregister_subdev;
     132              :         }
     133              : 
     134            1 :         isys->csi2[csi2->port].nlanes = csi2->nlanes;
     135              : 
     136            1 :         return 0;
     137              : 
     138            0 : unregister_subdev:
     139            0 :         v4l2_device_unregister_subdev(sd);
     140              : 
     141            0 :         return ret;
     142              : }
     143              : 
     144            1 : static void isys_stream_init(struct ipu6_isys *isys)
     145              : {
     146              :         u32 i;
     147              : 
     148            9 :         for (i = 0; i < IPU4_ISYS_MAX_STREAMS; i++) {
     149            8 :                 mutex_init(&isys->streams[i].mutex);
     150              :                 init_completion(&isys->streams[i].stream_open_completion);
     151              :                 init_completion(&isys->streams[i].stream_close_completion);
     152              :                 init_completion(&isys->streams[i].stream_start_completion);
     153              :                 init_completion(&isys->streams[i].stream_stop_completion);
     154            8 :                 INIT_LIST_HEAD(&isys->streams[i].queues);
     155            8 :                 isys->streams[i].isys = isys;
     156            8 :                 isys->streams[i].stream_handle = i;
     157            8 :                 isys->streams[i].vc = INVALID_VC_ID;
     158              :         }
     159            1 : }
     160              : 
     161            0 : static void isys_csi2_unregister_subdevices(struct ipu6_isys *isys)
     162              : {
     163              :         const struct ipu6_isys_internal_csi2_pdata *csi2 =
     164            0 :                 &isys->pdata->ipdata->csi2;
     165              :         unsigned int i;
     166              : 
     167            0 :         for (i = 0; i < csi2->nports; i++)
     168            0 :                 ipu6_isys_csi2_cleanup(&isys->csi2[i]);
     169            0 : }
     170              : 
     171            1 : static int isys_csi2_register_subdevices(struct ipu6_isys *isys)
     172              : {
     173              :         const struct ipu6_isys_internal_csi2_pdata *csi2_pdata =
     174            1 :                 &isys->pdata->ipdata->csi2;
     175            1 :         struct device *dev = &isys->adev->auxdev.dev;
     176              :         unsigned int i;
     177              :         int ret;
     178              : 
     179            1 :         isys->csi2 = devm_kcalloc(dev, csi2_pdata->nports,
     180              :                                   sizeof(*isys->csi2), GFP_KERNEL);
     181            1 :         if (!isys->csi2)
     182              :                 return -ENOMEM;
     183              : 
     184            7 :         for (i = 0; i < csi2_pdata->nports; i++) {
     185            6 :                 ret = ipu6_isys_csi2_init(&isys->csi2[i], isys,
     186            6 :                                           isys->pdata->base +
     187            6 :                                           CSI_REG_PORT_BASE(i), i);
     188            6 :                 if (ret)
     189            0 :                         goto fail;
     190              : 
     191            6 :                 isys->isr_csi2_bits |= IPU4_ISYS_UNISPART_IRQ_CSI2(i);
     192              :         }
     193              : 
     194              :         return 0;
     195              : 
     196              : fail:
     197            0 :         while (i--)
     198            0 :                 ipu6_isys_csi2_cleanup(&isys->csi2[i]);
     199              : 
     200              :         return ret;
     201              : }
     202              : 
     203            1 : static int isys_csi2_create_media_links(struct ipu6_isys *isys)
     204              : {
     205              :         const struct ipu6_isys_internal_csi2_pdata *csi2_pdata =
     206            1 :                 &isys->pdata->ipdata->csi2;
     207            1 :         struct device *dev = &isys->adev->auxdev.dev;
     208              :         unsigned int i, j, k;
     209              :         int ret;
     210              : 
     211            7 :         for (i = 0; i < csi2_pdata->nports; i++) {
     212            6 :                 struct media_entity *sd = &isys->csi2[i].asd.sd.entity;
     213              : 
     214          192 :                 for (j = 0; j < NR_OF_VIDEO_DEVICE; j++) {
     215          186 :                         struct media_entity *v = &isys->av[j].vdev.entity;
     216              :                         u32 flag = MEDIA_LNK_FL_DYNAMIC;
     217              : 
     218          930 :                         for (k = CSI2_PAD_SRC; k < NR_OF_CSI2_PADS; k++) {
     219          744 :                                 ret = media_create_pad_link(sd, k, v, 0, flag);
     220          744 :                                 if (ret) {
     221            0 :                                         dev_err(dev, "CSI2 can't create link\n");
     222            0 :                                         return ret;
     223              :                                 }
     224              :                         }
     225              :                 }
     226              :         }
     227              : 
     228              :         return 0;
     229              : }
     230              : 
     231              : static void isys_unregister_video_devices(struct ipu6_isys *isys)
     232              : {
     233              :         unsigned int i;
     234              : 
     235            0 :         for (i = 0; i < NR_OF_VIDEO_DEVICE; i++)
     236            0 :                 ipu6_isys_video_cleanup(&isys->av[i]);
     237              : }
     238              : 
     239            1 : static int isys_register_video_devices(struct ipu6_isys *isys)
     240              : {
     241              :         unsigned int i;
     242              :         int ret;
     243              : 
     244           32 :         for (i = 0; i < NR_OF_VIDEO_DEVICE; i++) {
     245           31 :                 struct ipu6_isys_video *av = &isys->av[i];
     246              : 
     247           31 :                 snprintf(av->vdev.name, sizeof(av->vdev.name),
     248              :                          IPU6_ISYS_ENTITY_PREFIX " ISYS Capture %u", i);
     249           31 :                 av->isys = isys;
     250           31 :                 av->aq.vbq.buf_struct_size =
     251              :                         sizeof(struct ipu6_isys_video_buffer);
     252              : 
     253           31 :                 ret = ipu6_isys_video_init(av);
     254           31 :                 if (ret)
     255            0 :                         goto fail;
     256              :         }
     257              : 
     258              :         return 0;
     259              : 
     260              : fail:
     261            0 :         while (i--)
     262            0 :                 ipu6_isys_video_cleanup(&isys->av[i]);
     263              : 
     264              :         return ret;
     265              : }
     266              : 
     267            1 : void isys_setup_hw(struct ipu6_isys *isys)
     268              : {
     269            1 :         void __iomem *base = isys->pdata->base;
     270            1 :         const u8 *thd = isys->pdata->ipdata->hw_variant.cdc_fifo_threshold;
     271              :         u32 irqs = 0;
     272              : #ifdef IPU6
     273              :         unsigned int i, nports;
     274              : 
     275              :         nports = isys->pdata->ipdata->csi2.nports;
     276              : 
     277              :         /* Enable irqs for all MIPI ports */
     278              :         for (i = 0; i < nports; i++)
     279              :                 irqs |= IPU6_ISYS_UNISPART_IRQ_CSI2(i);
     280              : 
     281              :         writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_edge);
     282              :         writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_lnp);
     283              :         writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_mask);
     284              :         writel(irqs, base + isys->pdata->ipdata->csi2.ctrl0_irq_enable);
     285              :         writel(GENMASK(19, 0),
     286              :                base + isys->pdata->ipdata->csi2.ctrl0_irq_clear);
     287              : 
     288              :         irqs = ISYS_UNISPART_IRQS;
     289              :         writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_EDGE);
     290              :         writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_LEVEL_NOT_PULSE);
     291              :         writel(GENMASK(28, 0), base + IPU6_REG_ISYS_UNISPART_IRQ_CLEAR);
     292              :         writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_MASK);
     293              :         writel(irqs, base + IPU6_REG_ISYS_UNISPART_IRQ_ENABLE);
     294              : 
     295              :         writel(0, base + IPU6_REG_ISYS_UNISPART_SW_IRQ_REG);
     296              :         writel(0, base + IPU6_REG_ISYS_UNISPART_SW_IRQ_MUX_REG);
     297              : 
     298              :         /* Write CDC FIFO threshold values for isys */
     299              :         for (i = 0; i < isys->pdata->ipdata->hw_variant.cdc_fifos; i++)
     300              :                 writel(thd[i], base + IPU6_REG_ISYS_CDC_THRESHOLD(i));
     301              : #else
     302              :         unsigned int i;
     303              :         /* Enable irqs for all MIPI ports */
     304              :         irqs = IPU4_ISYS_UNISPART_IRQ_CSI2(0) |
     305              :             IPU4_ISYS_UNISPART_IRQ_CSI2(1) |
     306              :             IPU4_ISYS_UNISPART_IRQ_CSI2(2) |
     307              :             IPU4_ISYS_UNISPART_IRQ_CSI2(3) |
     308              :             IPU4_ISYS_UNISPART_IRQ_CSI2(4) | IPU4_ISYS_UNISPART_IRQ_CSI2(5);
     309              : 
     310              :         irqs |= IPU4_ISYS_UNISPART_IRQ_SW;
     311              : 
     312            1 :         writel(irqs, base + IPU4_REG_ISYS_UNISPART_IRQ_EDGE);
     313            1 :         writel(irqs, base + IPU4_REG_ISYS_UNISPART_IRQ_LEVEL_NOT_PULSE);
     314            1 :         writel(irqs, base + IPU4_REG_ISYS_UNISPART_IRQ_CLEAR);
     315            1 :         writel(irqs, base + IPU4_REG_ISYS_UNISPART_IRQ_MASK);
     316            1 :         writel(irqs, base + IPU4_REG_ISYS_UNISPART_IRQ_ENABLE);
     317              : 
     318            1 :         writel(0, base + IPU4_REG_ISYS_UNISPART_SW_IRQ_REG);
     319            1 :         writel(0, base + IPU4_REG_ISYS_UNISPART_SW_IRQ_MUX_REG);
     320              : 
     321              :         /* Write CDC FIFO threshold values for isys */
     322            1 :         for (i = 0; i < isys->pdata->ipdata->hw_variant.cdc_fifos; i++)
     323            0 :                 writel(thd[i], base + IPU4_REG_ISYS_CDC_THRESHOLD(i));
     324              : #endif
     325            1 : }
     326              : 
     327            2 : static void ipu6_isys_csi2_isr(struct ipu6_isys_csi2 *csi2)
     328              : {
     329              :         struct ipu6_isys_stream *stream;
     330              :         unsigned int i;
     331              :         u32 status;
     332              :         int source;
     333              : 
     334              : #ifdef IPU6
     335              :         ipu6_isys_register_errors(csi2);
     336              : 
     337              :         status = readl(csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
     338              :                        CSI_PORT_REG_BASE_IRQ_STATUS_OFFSET);
     339              : 
     340              :         writel(status, csi2->base + CSI_PORT_REG_BASE_IRQ_CSI_SYNC +
     341              :                CSI_PORT_REG_BASE_IRQ_CLEAR_OFFSET);
     342              : #else
     343            2 :         status = readl(csi2->base + CSI2_REG_CSI2PART_IRQ_STATUS);
     344            2 :         writel(status, csi2->base + CSI2_REG_CSI2PART_IRQ_CLEAR);
     345              : 
     346            2 :         if (status & CSI2_CSI2PART_IRQ_CSIRX)
     347            0 :                 ipu4_isys_register_errors(csi2);
     348              : #endif
     349            2 :         source = csi2->asd.source;
     350           10 :         for (i = 0; i < NR_OF_CSI2_VC; i++) {
     351            8 :                 if (status & IPU_CSI_RX_IRQ_FS_VC(i)) {
     352            0 :                         stream = ipu6_isys_query_stream_by_source(csi2->isys,
     353              :                                                                   source, i);
     354            0 :                         if (stream) {
     355              : #ifdef IPU6 // TBD - is this a bug in upstream? 2 x sof_event send?
     356              :                                 ipu6_isys_csi2_sof_event_by_stream(stream);
     357              : #endif
     358            0 :                                 ipu6_isys_put_stream(stream);
     359              :                         }
     360              :                 }
     361              : 
     362            8 :                 if (status & IPU_CSI_RX_IRQ_FE_VC(i)) {
     363            0 :                         stream = ipu6_isys_query_stream_by_source(csi2->isys,
     364              :                                                                   source, i);
     365            0 :                         if (stream) {
     366              : #ifdef IPU6 // TBD - is this a bug in upstream? 2 x eof_event send?
     367              :                                 ipu6_isys_csi2_eof_event_by_stream(stream);
     368              : #endif
     369            0 :                                 ipu6_isys_put_stream(stream);
     370              :                         }
     371              :                 }
     372              :         }
     373            2 : }
     374              : 
     375            5 : static irqreturn_t ipu4_isys_isr(struct ipu6_bus_device *adev)
     376              : {
     377              :         struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
     378            5 :         void __iomem *base = isys->pdata->base;
     379              :         u32 status;
     380              : 
     381              :         spin_lock(&isys->power_lock);
     382            5 :         if (!isys->power) {
     383              :                 spin_unlock(&isys->power_lock);
     384            0 :                 return IRQ_NONE;
     385              :         }
     386              : 
     387            5 :         status = readl(base + IPU4_REG_ISYS_UNISPART_IRQ_STATUS);
     388              :         do {
     389           13 :                 writel(status, base + IPU4_REG_ISYS_UNISPART_IRQ_CLEAR);
     390              : 
     391           13 :                 if (isys->isr_csi2_bits & status) {
     392              :                         unsigned int i;
     393              : 
     394           14 :                         for (i = 0; i < isys->pdata->ipdata->csi2.nports; i++) {
     395           12 :                                 if (IPU4_ISYS_UNISPART_IRQ_CSI2(i) & status)
     396            2 :                                         ipu6_isys_csi2_isr(&isys->csi2[i]);
     397              :                         }
     398              :                 }
     399              : 
     400           13 :                 writel(0, base + IPU4_REG_ISYS_UNISPART_SW_IRQ_REG);
     401              : 
     402              :                 /*
     403              :                  * Handle a single FW event per checking the CSI-2
     404              :                  * receiver SOF status. This is done in order to avoid
     405              :                  * the case where events arrive to the event queue and
     406              :                  * one of them is a SOF event which then could be
     407              :                  * handled before the SOF interrupt. This would pose
     408              :                  * issues in sequence numbering which is based on SOF
     409              :                  * interrupts, always assumed to arrive before FW SOF
     410              :                  * events.
     411              :                  */
     412           13 :                 if (status & IPU4_ISYS_UNISPART_IRQ_SW && !isys_isr_one(adev))
     413              :                         status = IPU4_ISYS_UNISPART_IRQ_SW;
     414              :                 else
     415              :                         status = 0;
     416              : 
     417           13 :                 status |= readl(isys->pdata->base +
     418              :                                     IPU4_REG_ISYS_UNISPART_IRQ_STATUS);
     419           13 :         } while (status & (isys->isr_csi2_bits | IPU4_ISYS_UNISPART_IRQ_SW));
     420              : 
     421              :         spin_unlock(&isys->power_lock);
     422              : 
     423            5 :         return IRQ_HANDLED;
     424              : }
     425              : 
     426            5 : irqreturn_t isys_isr(struct ipu6_bus_device *adev)
     427              : {
     428              : #ifndef IPU6
     429            5 :         return ipu4_isys_isr(adev);
     430              : #else
     431              :         struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
     432              :         void __iomem *base = isys->pdata->base;
     433              :         u32 status_sw, status_csi;
     434              :         u32 ctrl0_status, ctrl0_clear;
     435              : 
     436              :         spin_lock(&isys->power_lock);
     437              :         if (!isys->power) {
     438              :                 spin_unlock(&isys->power_lock);
     439              :                 return IRQ_NONE;
     440              :         }
     441              : 
     442              :         ctrl0_status = isys->pdata->ipdata->csi2.ctrl0_irq_status;
     443              :         ctrl0_clear = isys->pdata->ipdata->csi2.ctrl0_irq_clear;
     444              : 
     445              :         status_csi = readl(isys->pdata->base + ctrl0_status);
     446              :         status_sw = readl(isys->pdata->base +
     447              :                           IPU6_REG_ISYS_UNISPART_IRQ_STATUS);
     448              : 
     449              :         writel(ISYS_UNISPART_IRQS & ~IPU6_ISYS_UNISPART_IRQ_SW,
     450              :                base + IPU6_REG_ISYS_UNISPART_IRQ_MASK);
     451              : 
     452              :         do {
     453              :                 writel(status_csi, isys->pdata->base + ctrl0_clear);
     454              : 
     455              :                 writel(status_sw, isys->pdata->base +
     456              :                        IPU6_REG_ISYS_UNISPART_IRQ_CLEAR);
     457              : 
     458              :                 if (isys->isr_csi2_bits & status_csi) {
     459              :                         unsigned int i;
     460              : 
     461              :                         for (i = 0; i < isys->pdata->ipdata->csi2.nports; i++) {
     462              :                                 /* irq from not enabled port */
     463              :                                 if (!isys->csi2[i].base)
     464              :                                         continue;
     465              :                                 if (status_csi & IPU6_ISYS_UNISPART_IRQ_CSI2(i))
     466              :                                         ipu6_isys_csi2_isr(&isys->csi2[i]);
     467              :                         }
     468              :                 }
     469              : 
     470              :                 writel(0, base + IPU6_REG_ISYS_UNISPART_SW_IRQ_REG);
     471              : 
     472              :                 if (!isys_isr_one(adev))
     473              :                         status_sw = IPU6_ISYS_UNISPART_IRQ_SW;
     474              :                 else
     475              :                         status_sw = 0;
     476              : 
     477              :                 status_csi = readl(isys->pdata->base + ctrl0_status);
     478              :                 status_sw |= readl(isys->pdata->base +
     479              :                                    IPU6_REG_ISYS_UNISPART_IRQ_STATUS);
     480              :         } while ((status_csi & isys->isr_csi2_bits) ||
     481              :                  (status_sw & IPU6_ISYS_UNISPART_IRQ_SW));
     482              : 
     483              :         writel(ISYS_UNISPART_IRQS, base + IPU6_REG_ISYS_UNISPART_IRQ_MASK);
     484              : 
     485              :         spin_unlock(&isys->power_lock);
     486              : 
     487              :         return IRQ_HANDLED;
     488              : #endif
     489              : }
     490              : 
     491              : #ifdef IPU6
     492              : 
     493              : static void get_lut_ltrdid(struct ipu6_isys *isys, struct ltr_did *pltr_did)
     494              : {
     495              :         struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
     496              :         struct ltr_did ltrdid_default;
     497              : 
     498              :         ltrdid_default.lut_ltr.value = LTR_DEFAULT_VALUE;
     499              :         ltrdid_default.lut_fill_time.value = FILL_TIME_DEFAULT_VALUE;
     500              : 
     501              :         if (iwake_watermark->ltrdid.lut_ltr.value)
     502              :                 *pltr_did = iwake_watermark->ltrdid;
     503              :         else
     504              :                 *pltr_did = ltrdid_default;
     505              : }
     506              : 
     507              : static int set_iwake_register(struct ipu6_isys *isys, u32 index, u32 value)
     508              : {
     509              :         struct device *dev = &isys->adev->auxdev.dev;
     510              :         u32 req_id = index;
     511              :         u32 offset = 0;
     512              :         int ret;
     513              : 
     514              :         ret = ipu6_fw_isys_send_proxy_token(isys, req_id, index, offset, value);
     515              :         if (ret)
     516              :                 dev_err(dev, "write %d failed %d", index, ret);
     517              : 
     518              :         return ret;
     519              : }
     520              : 
     521              : /*
     522              :  * When input system is powered up and before enabling any new sensor capture,
     523              :  * or after disabling any sensor capture the following values need to be set:
     524              :  * LTR_value = LTR(usec) from calculation;
     525              :  * LTR_scale = 2;
     526              :  * DID_value = DID(usec) from calculation;
     527              :  * DID_scale = 2;
     528              :  *
     529              :  * When input system is powered down, the LTR and DID values
     530              :  * must be returned to the default values:
     531              :  * LTR_value = 1023;
     532              :  * LTR_scale = 5;
     533              :  * DID_value = 1023;
     534              :  * DID_scale = 2;
     535              :  */
     536              : static void set_iwake_ltrdid(struct ipu6_isys *isys, u16 ltr, u16 did,
     537              :                              enum ltr_did_type use)
     538              : {
     539              :         struct device *dev = &isys->adev->auxdev.dev;
     540              :         u16 ltr_val, ltr_scale = LTR_SCALE_1024NS;
     541              :         u16 did_val, did_scale = DID_SCALE_1US;
     542              :         struct ipu6_device *isp = isys->adev->isp;
     543              :         union fabric_ctrl fc;
     544              : 
     545              :         switch (use) {
     546              :         case LTR_IWAKE_ON:
     547              :                 ltr_val = min_t(u16, ltr, (u16)LTR_DID_VAL_MAX);
     548              :                 did_val = min_t(u16, did, (u16)LTR_DID_VAL_MAX);
     549              :                 ltr_scale = (ltr == LTR_DID_VAL_MAX &&
     550              :                              did == LTR_DID_VAL_MAX) ?
     551              :                         LTR_SCALE_DEFAULT : LTR_SCALE_1024NS;
     552              :                 break;
     553              :         case LTR_ISYS_ON:
     554              :         case LTR_IWAKE_OFF:
     555              :                 ltr_val = LTR_DID_PKGC_2R;
     556              :                 did_val = LTR_DID_PKGC_2R;
     557              :                 break;
     558              :         case LTR_ISYS_OFF:
     559              :                 ltr_val   = LTR_DID_VAL_MAX;
     560              :                 did_val   = LTR_DID_VAL_MAX;
     561              :                 ltr_scale = LTR_SCALE_DEFAULT;
     562              :                 break;
     563              :         case LTR_ENHANNCE_IWAKE:
     564              :                 if (ltr == LTR_DID_VAL_MAX && did == LTR_DID_VAL_MAX) {
     565              :                         ltr_val = LTR_DID_VAL_MAX;
     566              :                         did_val = LTR_DID_VAL_MAX;
     567              :                         ltr_scale = LTR_SCALE_DEFAULT;
     568              :                 } else if (did < ONE_THOUSAND_MICROSECOND) {
     569              :                         ltr_val = ltr;
     570              :                         did_val = did;
     571              :                 } else {
     572              :                         ltr_val = ltr;
     573              :                         /* div 90% value by 32 to account for scale change */
     574              :                         did_val = did / 32;
     575              :                         did_scale = DID_SCALE_32US;
     576              :                 }
     577              :                 break;
     578              :         default:
     579              :                 ltr_val   = LTR_DID_VAL_MAX;
     580              :                 did_val   = LTR_DID_VAL_MAX;
     581              :                 ltr_scale = LTR_SCALE_DEFAULT;
     582              :                 break;
     583              :         }
     584              : 
     585              :         fc.value = readl(isp->base + IPU6_BUTTRESS_FABIC_CONTROL);
     586              :         fc.bits.ltr_val = ltr_val;
     587              :         fc.bits.ltr_scale = ltr_scale;
     588              :         fc.bits.did_val = did_val;
     589              :         fc.bits.did_scale = did_scale;
     590              : 
     591              :         dev_dbg(dev, "ltr: value %u scale %u, did: value %u scale %u\n",
     592              :                 ltr_val, ltr_scale, did_val, did_scale);
     593              :         writel(fc.value, isp->base + IPU6_BUTTRESS_FABIC_CONTROL);
     594              : }
     595              : 
     596              : /*
     597              :  * Driver may clear register GDA_ENABLE_IWAKE before FW configures the
     598              :  * stream for debug purpose. Otherwise driver should not access this register.
     599              :  */
     600              : static void enable_iwake(struct ipu6_isys *isys, bool enable)
     601              : {
     602              :         struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
     603              :         int ret;
     604              : 
     605              :         mutex_lock(&iwake_watermark->mutex);
     606              : 
     607              :         if (iwake_watermark->iwake_enabled == enable) {
     608              :                 mutex_unlock(&iwake_watermark->mutex);
     609              :                 return;
     610              :         }
     611              : 
     612              :         ret = set_iwake_register(isys, GDA_ENABLE_IWAKE_INDEX, enable);
     613              :         if (!ret)
     614              :                 iwake_watermark->iwake_enabled = enable;
     615              : 
     616              :         mutex_unlock(&iwake_watermark->mutex);
     617              : }
     618              : 
     619              : void update_watermark_setting(struct ipu6_isys *isys)
     620              : {
     621              :         struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
     622              :         u32 iwake_threshold, iwake_critical_threshold, page_num;
     623              :         struct device *dev = &isys->adev->auxdev.dev;
     624              :         u32 calc_fill_time_us = 0, ltr = 0, did = 0;
     625              :         struct video_stream_watermark *p_watermark;
     626              :         enum ltr_did_type ltr_did_type;
     627              :         struct list_head *stream_node;
     628              :         u64 isys_pb_datarate_mbs = 0;
     629              :         u32 mem_open_threshold = 0;
     630              :         struct ltr_did ltrdid;
     631              :         u64 threshold_bytes;
     632              :         u32 max_sram_size;
     633              :         u32 shift;
     634              : 
     635              :         shift = isys->pdata->ipdata->sram_gran_shift;
     636              :         max_sram_size = isys->pdata->ipdata->max_sram_size;
     637              : 
     638              :         mutex_lock(&iwake_watermark->mutex);
     639              :         if (iwake_watermark->force_iwake_disable) {
     640              :                 set_iwake_ltrdid(isys, 0, 0, LTR_IWAKE_OFF);
     641              :                 set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX,
     642              :                                    CRITICAL_THRESHOLD_IWAKE_DISABLE);
     643              :                 goto unlock_exit;
     644              :         }
     645              : 
     646              :         if (list_empty(&iwake_watermark->video_list)) {
     647              :                 isys_pb_datarate_mbs = 0;
     648              :         } else {
     649              :                 list_for_each(stream_node, &iwake_watermark->video_list) {
     650              :                         p_watermark = list_entry(stream_node,
     651              :                                                  struct video_stream_watermark,
     652              :                                                  stream_node);
     653              :                         isys_pb_datarate_mbs += p_watermark->stream_data_rate;
     654              :                 }
     655              :         }
     656              :         mutex_unlock(&iwake_watermark->mutex);
     657              : 
     658              :         if (!isys_pb_datarate_mbs) {
     659              :                 enable_iwake(isys, false);
     660              :                 set_iwake_ltrdid(isys, 0, 0, LTR_IWAKE_OFF);
     661              :                 mutex_lock(&iwake_watermark->mutex);
     662              :                 set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX,
     663              :                                    CRITICAL_THRESHOLD_IWAKE_DISABLE);
     664              :                 goto unlock_exit;
     665              :         }
     666              : 
     667              :         enable_iwake(isys, true);
     668              :         calc_fill_time_us = div64_u64(max_sram_size, isys_pb_datarate_mbs);
     669              : 
     670              :         if (isys->pdata->ipdata->enhanced_iwake) {
     671              :                 ltr = isys->pdata->ipdata->ltr;
     672              :                 did = calc_fill_time_us * DEFAULT_DID_RATIO / 100;
     673              :                 ltr_did_type = LTR_ENHANNCE_IWAKE;
     674              :         } else {
     675              :                 get_lut_ltrdid(isys, &ltrdid);
     676              : 
     677              :                 if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th0)
     678              :                         ltr = 0;
     679              :                 else if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th1)
     680              :                         ltr = ltrdid.lut_ltr.bits.val0;
     681              :                 else if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th2)
     682              :                         ltr = ltrdid.lut_ltr.bits.val1;
     683              :                 else if (calc_fill_time_us <= ltrdid.lut_fill_time.bits.th3)
     684              :                         ltr = ltrdid.lut_ltr.bits.val2;
     685              :                 else
     686              :                         ltr = ltrdid.lut_ltr.bits.val3;
     687              : 
     688              :                 did = calc_fill_time_us - ltr;
     689              :                 ltr_did_type = LTR_IWAKE_ON;
     690              :         }
     691              : 
     692              :         set_iwake_ltrdid(isys, ltr, did, ltr_did_type);
     693              : 
     694              :         /* calculate iwake threshold with 2KB granularity pages */
     695              :         threshold_bytes = did * isys_pb_datarate_mbs;
     696              :         iwake_threshold = max_t(u32, 1, threshold_bytes >> shift);
     697              :         iwake_threshold = min_t(u32, iwake_threshold, max_sram_size);
     698              : 
     699              :         mutex_lock(&iwake_watermark->mutex);
     700              :         if (isys->pdata->ipdata->enhanced_iwake) {
     701              :                 set_iwake_register(isys, GDA_IWAKE_THRESHOLD_INDEX,
     702              :                                    DEFAULT_IWAKE_THRESHOLD);
     703              :                 /* calculate number of pages that will be filled in 10 usec */
     704              :                 page_num = (DEFAULT_MEM_OPEN_TIME * isys_pb_datarate_mbs) /
     705              :                         ISF_DMA_TOP_GDA_PROFERTY_PAGE_SIZE;
     706              :                 page_num += ((DEFAULT_MEM_OPEN_TIME * isys_pb_datarate_mbs) %
     707              :                              ISF_DMA_TOP_GDA_PROFERTY_PAGE_SIZE) ? 1 : 0;
     708              :                 mem_open_threshold = isys->pdata->ipdata->memopen_threshold;
     709              :                 mem_open_threshold = max_t(u32, mem_open_threshold, page_num);
     710              :                 dev_dbg(dev, "mem_open_threshold: %u\n", mem_open_threshold);
     711              :                 set_iwake_register(isys, GDA_MEMOPEN_THRESHOLD_INDEX,
     712              :                                    mem_open_threshold);
     713              :         } else {
     714              :                 set_iwake_register(isys, GDA_IWAKE_THRESHOLD_INDEX,
     715              :                                    iwake_threshold);
     716              :         }
     717              : 
     718              :         iwake_critical_threshold = iwake_threshold +
     719              :                 (IS_PIXEL_BUFFER_PAGES - iwake_threshold) / 2;
     720              : 
     721              :         dev_dbg(dev, "threshold: %u critical: %u\n", iwake_threshold,
     722              :                 iwake_critical_threshold);
     723              : 
     724              :         set_iwake_register(isys, GDA_IRQ_CRITICAL_THRESHOLD_INDEX,
     725              :                            iwake_critical_threshold);
     726              : 
     727              :         writel(VAL_PKGC_PMON_CFG_RESET,
     728              :                isys->adev->isp->base + REG_PKGC_PMON_CFG);
     729              :         writel(VAL_PKGC_PMON_CFG_START,
     730              :                isys->adev->isp->base + REG_PKGC_PMON_CFG);
     731              : unlock_exit:
     732              :         mutex_unlock(&iwake_watermark->mutex);
     733              : }
     734              : 
     735              : static void isys_iwake_watermark_init(struct ipu6_isys *isys)
     736              : {
     737              :         struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
     738              : 
     739              :         INIT_LIST_HEAD(&iwake_watermark->video_list);
     740              :         mutex_init(&iwake_watermark->mutex);
     741              : 
     742              :         iwake_watermark->ltrdid.lut_ltr.value = 0;
     743              :         iwake_watermark->isys = isys;
     744              :         iwake_watermark->iwake_enabled = false;
     745              :         iwake_watermark->force_iwake_disable = false;
     746              : }
     747              : 
     748              : static void isys_iwake_watermark_cleanup(struct ipu6_isys *isys)
     749              : {
     750              :         struct isys_iwake_watermark *iwake_watermark = &isys->iwake_watermark;
     751              : 
     752              :         mutex_lock(&iwake_watermark->mutex);
     753              :         list_del(&iwake_watermark->video_list);
     754              :         mutex_unlock(&iwake_watermark->mutex);
     755              : 
     756              :         mutex_destroy(&iwake_watermark->mutex);
     757              : }
     758              : #endif
     759              : 
     760              : #if IS_ENABLED(CONFIG_VIDEO_IPU4_VIRT_SENSOR)
     761              : /* Install the one active route the IPU4 QEMU harness needs so that
     762              :  * media_pipeline_start() stops rejecting STREAMON with -ENOLINK.
     763              :  * Upstream IPU6 relies on userspace (media-ctl / v4l2-ctl) to set
     764              :  * this; the busybox initramfs has no media manager, so we install
     765              :  * the default sink=0/0 -> source=1/0 route on the CSI2 subdev at
     766              :  * sensor-bind time. The same route is already installed into the
     767              :  * subdev's "try" state by ipu6_isys_subdev_init_cfg(); this mirrors
     768              :  * it into the active state.
     769              :  */
     770            1 : static void isys_install_virt_sensor_route(struct v4l2_subdev *csi2_sd)
     771              : {
     772              :         /* Must match virt-sensor's default: 800x800 RGB888_1X24. If the
     773              :          * CSI2 sink format doesn't match the sensor source format,
     774              :          * media_pipeline_start() rejects STREAMON with -ENOLINK.
     775              :          * ipu6_isys_subdev_set_routing()'s internal default is
     776              :          * 4096x3072/SGRBG10 — wrong for the virt-sensor. */
     777            1 :         struct v4l2_mbus_framefmt fmt = {
     778              :                 .width = 800,
     779              :                 .height = 800,
     780              :                 .code = MEDIA_BUS_FMT_RGB888_1X24,
     781              :                 .field = V4L2_FIELD_NONE,
     782              :         };
     783            1 :         struct v4l2_subdev_route route = {
     784              :                 .sink_pad = 0,
     785              :                 .sink_stream = 0,
     786              :                 .source_pad = 1,
     787              :                 .source_stream = 0,
     788              :                 .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
     789              :         };
     790            1 :         struct v4l2_subdev_krouting routing = {
     791              :                 .num_routes = 1,
     792              :                 .routes = &route,
     793              :         };
     794              :         struct v4l2_subdev_state *state;
     795              :         int ret;
     796              : 
     797              :         state = v4l2_subdev_lock_and_get_active_state(csi2_sd);
     798            1 :         if (!state) {
     799            0 :                 dev_warn(csi2_sd->dev,
     800              :                          "virt-sensor: no active state on %s; skipping route install\n",
     801              :                          csi2_sd->name);
     802            0 :                 return;
     803              :         }
     804              : 
     805            1 :         ret = v4l2_subdev_set_routing_with_fmt(csi2_sd, state, &routing, &fmt);
     806              :         v4l2_subdev_unlock_state(state);
     807              : 
     808            1 :         if (ret)
     809            0 :                 dev_warn(csi2_sd->dev,
     810              :                          "virt-sensor: set_routing on %s failed %d\n",
     811              :                          csi2_sd->name, ret);
     812              :         else
     813            1 :                 dev_info(csi2_sd->dev,
     814              :                          "virt-sensor: installed active route on %s (sink=0/0 -> source=1/0, 800x800 RGB888)\n",
     815              :                          csi2_sd->name);
     816              : }
     817              : #endif
     818              : 
     819              : /* The .bound() notifier callback when a match is found */
     820            1 : static int isys_notifier_bound(struct v4l2_async_notifier *notifier,
     821              :                                struct v4l2_subdev *sd,
     822              :                                struct v4l2_async_connection *asc)
     823              : {
     824              :         struct ipu6_isys *isys =
     825            1 :                 container_of(notifier, struct ipu6_isys, notifier);
     826              :         struct sensor_async_sd *s_asd =
     827              :                 container_of(asc, struct sensor_async_sd, asc);
     828              :         int ret;
     829              : 
     830            1 :         if (s_asd->csi2.port >= isys->pdata->ipdata->csi2.nports) {
     831            0 :                 dev_err(&isys->adev->auxdev.dev, "invalid csi2 port %u\n",
     832              :                         s_asd->csi2.port);
     833            0 :                 return -EINVAL;
     834              :         }
     835              : 
     836              : #ifdef IPU6
     837              :         ret = ipu_bridge_instantiate_vcm(sd->dev);
     838              :         if (ret) {
     839              :                 dev_err(&isys->adev->auxdev.dev, "instantiate vcm failed\n");
     840              :                 return ret;
     841              :         }
     842              : #endif
     843              : 
     844            1 :         dev_dbg(&isys->adev->auxdev.dev, "bind %s nlanes is %d port is %d\n",
     845              :                 sd->name, s_asd->csi2.nlanes, s_asd->csi2.port);
     846            1 :         ret = isys_complete_ext_device_registration(isys, sd, &s_asd->csi2);
     847            1 :         if (ret)
     848              :                 return ret;
     849              : 
     850              : #if IS_ENABLED(CONFIG_VIDEO_IPU4_VIRT_SENSOR)
     851            1 :         isys_install_virt_sensor_route(
     852            1 :                 &isys->csi2[s_asd->csi2.port].asd.sd);
     853              : #endif
     854              : 
     855            1 :         return v4l2_device_register_subdev_nodes(&isys->v4l2_dev);
     856              : }
     857              : 
     858            1 : static int isys_notifier_complete(struct v4l2_async_notifier *notifier)
     859              : {
     860              :         struct ipu6_isys *isys =
     861              :                 container_of(notifier, struct ipu6_isys, notifier);
     862              : 
     863            1 :         return v4l2_device_register_subdev_nodes(&isys->v4l2_dev);
     864              : }
     865              : 
     866              : static const struct v4l2_async_notifier_operations isys_async_ops = {
     867              :         .bound = isys_notifier_bound,
     868              :         .complete = isys_notifier_complete,
     869              : };
     870              : 
     871              : #define ISYS_MAX_PORTS 8
     872            1 : static int isys_notifier_init(struct ipu6_isys *isys)
     873              : {
     874            1 :         struct ipu6_device *isp = isys->adev->isp;
     875            1 :         struct device *dev = &isp->pdev->dev;
     876              :         unsigned int i;
     877              :         int ret;
     878              : 
     879            1 :         v4l2_async_nf_init(&isys->notifier, &isys->v4l2_dev);
     880              : 
     881            9 :         for (i = 0; i < ISYS_MAX_PORTS; i++) {
     882            8 :                 struct v4l2_fwnode_endpoint vep = {
     883              :                         .bus_type = V4L2_MBUS_CSI2_DPHY
     884              :                 };
     885              :                 struct sensor_async_sd *s_asd;
     886              :                 struct fwnode_handle *ep;
     887              : 
     888            8 :                 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), i, 0,
     889              :                                                 FWNODE_GRAPH_ENDPOINT_NEXT);
     890            8 :                 if (!ep)
     891            8 :                         continue;
     892              : 
     893            1 :                 ret = v4l2_fwnode_endpoint_parse(ep, &vep);
     894            1 :                 if (ret) {
     895            0 :                         dev_err(dev, "fwnode endpoint parse failed: %d\n", ret);
     896            0 :                         goto err_parse;
     897              :                 }
     898              : 
     899            1 :                 s_asd = v4l2_async_nf_add_fwnode_remote(&isys->notifier, ep,
     900              :                                                         struct sensor_async_sd);
     901            1 :                 if (IS_ERR(s_asd)) {
     902            0 :                         ret = PTR_ERR(s_asd);
     903            0 :                         dev_err(dev, "add remove fwnode failed: %d\n", ret);
     904            0 :                         goto err_parse;
     905              :                 }
     906              : 
     907            1 :                 s_asd->csi2.port = vep.base.port;
     908            1 :                 s_asd->csi2.nlanes = vep.bus.mipi_csi2.num_data_lanes;
     909              : 
     910            1 :                 dev_dbg(dev, "remote endpoint port %d with %d lanes added\n",
     911              :                         s_asd->csi2.port, s_asd->csi2.nlanes);
     912              : 
     913            1 :                 fwnode_handle_put(ep);
     914              : 
     915            1 :                 continue;
     916              : 
     917            0 : err_parse:
     918            0 :                 fwnode_handle_put(ep);
     919            0 :                 return ret;
     920              :         }
     921              : 
     922            1 :         isys->notifier.ops = &isys_async_ops;
     923            1 :         ret = v4l2_async_nf_register(&isys->notifier);
     924            1 :         if (ret) {
     925            0 :                 dev_err(dev, "failed to register async notifier : %d\n", ret);
     926            0 :                 v4l2_async_nf_cleanup(&isys->notifier);
     927              :         }
     928              : 
     929              :         return ret;
     930              : }
     931              : 
     932              : static void isys_notifier_cleanup(struct ipu6_isys *isys)
     933              : {
     934            0 :         v4l2_async_nf_unregister(&isys->notifier);
     935            0 :         v4l2_async_nf_cleanup(&isys->notifier);
     936              : }
     937              : 
     938            1 : static int isys_register_devices(struct ipu6_isys *isys)
     939              : {
     940            1 :         struct device *dev = &isys->adev->auxdev.dev;
     941            1 :         struct pci_dev *pdev = isys->adev->isp->pdev;
     942              :         int ret;
     943              : 
     944            1 :         isys->media_dev.dev = dev;
     945            1 :         media_device_pci_init(&isys->media_dev,
     946              :                               pdev, IPU4_MEDIA_DEV_MODEL_NAME);
     947              : 
     948            1 :         strscpy(isys->v4l2_dev.name, isys->media_dev.model,
     949              :                 sizeof(isys->v4l2_dev.name));
     950              : 
     951            1 :         ret = media_device_register(&isys->media_dev);
     952            1 :         if (ret < 0)
     953            0 :                 goto out_media_device_unregister;
     954              : 
     955            1 :         isys->v4l2_dev.mdev = &isys->media_dev;
     956            1 :         isys->v4l2_dev.ctrl_handler = NULL;
     957              : 
     958            1 :         ret = v4l2_device_register(dev, &isys->v4l2_dev);
     959            1 :         if (ret < 0)
     960            0 :                 goto out_media_device_unregister;
     961              : 
     962            1 :         ret = isys_register_video_devices(isys);
     963            1 :         if (ret)
     964            0 :                 goto out_v4l2_device_unregister;
     965              : 
     966            1 :         ret = isys_csi2_register_subdevices(isys);
     967            1 :         if (ret)
     968            0 :                 goto out_isys_unregister_video_device;
     969              : 
     970            1 :         ret = isys_csi2_create_media_links(isys);
     971            1 :         if (ret)
     972            0 :                 goto out_isys_unregister_subdevices;
     973              : 
     974            1 :         ret = isys_notifier_init(isys);
     975            1 :         if (ret)
     976            0 :                 goto out_isys_unregister_subdevices;
     977              : 
     978              :         return 0;
     979              : 
     980            0 : out_isys_unregister_subdevices:
     981            0 :         isys_csi2_unregister_subdevices(isys);
     982              : 
     983            0 : out_isys_unregister_video_device:
     984              :         isys_unregister_video_devices(isys);
     985              : 
     986            0 : out_v4l2_device_unregister:
     987            0 :         v4l2_device_unregister(&isys->v4l2_dev);
     988              : 
     989            0 : out_media_device_unregister:
     990            0 :         media_device_unregister(&isys->media_dev);
     991            0 :         media_device_cleanup(&isys->media_dev);
     992              : 
     993            0 :         dev_err(dev, "failed to register isys devices\n");
     994              : 
     995            0 :         return ret;
     996              : }
     997              : 
     998            0 : static void isys_unregister_devices(struct ipu6_isys *isys)
     999              : {
    1000              :         isys_unregister_video_devices(isys);
    1001            0 :         isys_csi2_unregister_subdevices(isys);
    1002            0 :         v4l2_device_unregister(&isys->v4l2_dev);
    1003            0 :         media_device_unregister(&isys->media_dev);
    1004            0 :         media_device_cleanup(&isys->media_dev);
    1005            0 : }
    1006              : 
    1007            1 : static int isys_runtime_pm_resume(struct device *dev)
    1008              : {
    1009              :         struct ipu6_bus_device *adev = to_ipu6_bus_device(dev);
    1010              :         struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
    1011            1 :         struct ipu6_device *isp = adev->isp;
    1012              :         unsigned long flags;
    1013              :         int ret;
    1014              : 
    1015            1 :         if (!isys)
    1016              :                 return 0;
    1017              : 
    1018            1 :         ret = ipu6_mmu_hw_init(adev->mmu);
    1019            1 :         if (ret)
    1020              :                 return ret;
    1021              : 
    1022            1 :         cpu_latency_qos_update_request(&isys->pm_qos, ISYS_PM_QOS_VALUE);
    1023              : 
    1024            1 :         ret = ipu6_buttress_start_tsc_sync(isp);
    1025            1 :         if (ret)
    1026              :                 return ret;
    1027              : 
    1028            1 :         spin_lock_irqsave(&isys->power_lock, flags);
    1029            1 :         isys->power = 1;
    1030              :         spin_unlock_irqrestore(&isys->power_lock, flags);
    1031              : 
    1032            1 :         isys_setup_hw(isys);
    1033              : 
    1034              : #ifdef IPU6
    1035              :         set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_ON);
    1036              : #endif
    1037            1 :         return 0;
    1038              : }
    1039              : 
    1040            1 : static int isys_runtime_pm_suspend(struct device *dev)
    1041              : {
    1042              :         struct ipu6_bus_device *adev = to_ipu6_bus_device(dev);
    1043              :         struct ipu6_isys *isys;
    1044              :         unsigned long flags;
    1045              : 
    1046              :         isys = dev_get_drvdata(dev);
    1047            1 :         if (!isys)
    1048              :                 return 0;
    1049              : 
    1050            1 :         spin_lock_irqsave(&isys->power_lock, flags);
    1051            1 :         isys->power = 0;
    1052              :         spin_unlock_irqrestore(&isys->power_lock, flags);
    1053              : 
    1054            1 :         mutex_lock(&isys->mutex);
    1055            1 :         isys->need_reset = false;
    1056            1 :         mutex_unlock(&isys->mutex);
    1057              : 
    1058            1 :         isys->phy_termcal_val = 0;
    1059            1 :         cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
    1060              : #ifdef IPU6
    1061              :         set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_OFF);
    1062              : #endif
    1063              : 
    1064            1 :         ipu6_mmu_hw_cleanup(adev->mmu);
    1065              : 
    1066            1 :         return 0;
    1067              : }
    1068              : 
    1069            0 : static int isys_suspend(struct device *dev)
    1070              : {
    1071              :         struct ipu6_isys *isys = dev_get_drvdata(dev);
    1072              : 
    1073              :         /* If stream is open, refuse to suspend */
    1074            0 :         if (isys->stream_opened)
    1075            0 :                 return -EBUSY;
    1076              : 
    1077              :         return 0;
    1078              : }
    1079              : 
    1080            0 : static int isys_resume(struct device *dev)
    1081              : {
    1082            0 :         return 0;
    1083              : }
    1084              : 
    1085              : static const struct dev_pm_ops isys_pm_ops = {
    1086              :         .runtime_suspend = isys_runtime_pm_suspend,
    1087              :         .runtime_resume = isys_runtime_pm_resume,
    1088              :         .suspend = isys_suspend,
    1089              :         .resume = isys_resume,
    1090              : };
    1091              : 
    1092            0 : static void free_fw_msg_bufs(struct ipu6_isys *isys)
    1093              : {
    1094              :         struct isys_fw_msgs *fwmsg, *safe;
    1095              : 
    1096            0 :         list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head)
    1097            0 :                 ipu6_dma_free(isys->adev, sizeof(struct isys_fw_msgs), fwmsg,
    1098              :                               fwmsg->dma_addr, 0);
    1099              : 
    1100            0 :         list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head)
    1101            0 :                 ipu6_dma_free(isys->adev, sizeof(struct isys_fw_msgs), fwmsg,
    1102              :                               fwmsg->dma_addr, 0);
    1103            0 : }
    1104              : 
    1105            1 : static int alloc_fw_msg_bufs(struct ipu6_isys *isys, int amount)
    1106              : {
    1107              :         struct isys_fw_msgs *addr;
    1108            1 :         dma_addr_t dma_addr;
    1109              :         unsigned long flags;
    1110              :         unsigned int i;
    1111              : 
    1112           21 :         for (i = 0; i < amount; i++) {
    1113           20 :                 addr = ipu6_dma_alloc(isys->adev, sizeof(*addr),
    1114              :                                       &dma_addr, GFP_KERNEL, 0);
    1115           20 :                 if (!addr)
    1116              :                         break;
    1117           20 :                 addr->dma_addr = dma_addr;
    1118              : 
    1119           20 :                 spin_lock_irqsave(&isys->listlock, flags);
    1120           20 :                 list_add(&addr->head, &isys->framebuflist);
    1121              :                 spin_unlock_irqrestore(&isys->listlock, flags);
    1122              :         }
    1123              : 
    1124            1 :         if (i == amount)
    1125              :                 return 0;
    1126              : 
    1127            0 :         spin_lock_irqsave(&isys->listlock, flags);
    1128            0 :         while (!list_empty(&isys->framebuflist)) {
    1129            0 :                 addr = list_first_entry(&isys->framebuflist,
    1130              :                                         struct isys_fw_msgs, head);
    1131              :                 list_del(&addr->head);
    1132              :                 spin_unlock_irqrestore(&isys->listlock, flags);
    1133            0 :                 ipu6_dma_free(isys->adev, sizeof(struct isys_fw_msgs), addr,
    1134              :                               addr->dma_addr, 0);
    1135            0 :                 spin_lock_irqsave(&isys->listlock, flags);
    1136              :         }
    1137              :         spin_unlock_irqrestore(&isys->listlock, flags);
    1138              : 
    1139            0 :         return -ENOMEM;
    1140              : }
    1141              : 
    1142            3 : struct isys_fw_msgs *ipu6_get_fw_msg_buf(struct ipu6_isys_stream *stream)
    1143              : {
    1144            3 :         struct ipu6_isys *isys = stream->isys;
    1145            3 :         struct device *dev = &isys->adev->auxdev.dev;
    1146              :         struct isys_fw_msgs *msg;
    1147              :         unsigned long flags;
    1148              :         int ret;
    1149              : 
    1150            3 :         spin_lock_irqsave(&isys->listlock, flags);
    1151            3 :         if (list_empty(&isys->framebuflist)) {
    1152              :                 spin_unlock_irqrestore(&isys->listlock, flags);
    1153            0 :                 dev_dbg(dev, "Frame list empty\n");
    1154              : 
    1155            0 :                 ret = alloc_fw_msg_bufs(isys, 5);
    1156            0 :                 if (ret < 0)
    1157              :                         return NULL;
    1158              : 
    1159            0 :                 spin_lock_irqsave(&isys->listlock, flags);
    1160            0 :                 if (list_empty(&isys->framebuflist)) {
    1161              :                         spin_unlock_irqrestore(&isys->listlock, flags);
    1162            0 :                         dev_err(dev, "Frame list empty\n");
    1163            0 :                         return NULL;
    1164              :                 }
    1165              :         }
    1166            3 :         msg = list_last_entry(&isys->framebuflist, struct isys_fw_msgs, head);
    1167            3 :         list_move(&msg->head, &isys->framebuflist_fw);
    1168              :         spin_unlock_irqrestore(&isys->listlock, flags);
    1169            3 :         memset(&msg->fw_msg, 0, sizeof(msg->fw_msg));
    1170              : 
    1171            3 :         return msg;
    1172              : }
    1173              : 
    1174            1 : void ipu6_cleanup_fw_msg_bufs(struct ipu6_isys *isys)
    1175              : {
    1176              :         struct isys_fw_msgs *fwmsg, *fwmsg0;
    1177              :         unsigned long flags;
    1178              : 
    1179            1 :         spin_lock_irqsave(&isys->listlock, flags);
    1180            1 :         list_for_each_entry_safe(fwmsg, fwmsg0, &isys->framebuflist_fw, head)
    1181            0 :                 list_move(&fwmsg->head, &isys->framebuflist);
    1182              :         spin_unlock_irqrestore(&isys->listlock, flags);
    1183            1 : }
    1184              : 
    1185            2 : void ipu6_put_fw_msg_buf(struct ipu6_isys *isys, uintptr_t data)
    1186              : {
    1187              :         struct isys_fw_msgs *msg;
    1188              :         unsigned long flags;
    1189            2 :         void *ptr = (void *)data;
    1190              : 
    1191            2 :         if (!ptr)
    1192              :                 return;
    1193              : 
    1194            1 :         spin_lock_irqsave(&isys->listlock, flags);
    1195              :         msg = container_of(ptr, struct isys_fw_msgs, fw_msg.dummy);
    1196            1 :         list_move(&msg->head, &isys->framebuflist);
    1197              :         spin_unlock_irqrestore(&isys->listlock, flags);
    1198              : }
    1199              : 
    1200            1 : static int isys_probe(struct auxiliary_device *auxdev,
    1201              :                       const struct auxiliary_device_id *auxdev_id)
    1202              : {
    1203              :         const struct ipu6_isys_internal_csi2_pdata *csi2_pdata;
    1204              :         struct ipu6_bus_device *adev = auxdev_to_adev(auxdev);
    1205            1 :         struct ipu6_device *isp = adev->isp;
    1206              :         const struct firmware *fw;
    1207              :         struct ipu6_isys *isys;
    1208              :         unsigned int i;
    1209              :         int ret;
    1210              : 
    1211            1 :         if (!isp->bus_ready_to_probe)
    1212              :                 return -EPROBE_DEFER;
    1213              : 
    1214            1 :         isys = devm_kzalloc(&auxdev->dev, sizeof(*isys), GFP_KERNEL);
    1215            1 :         if (!isys)
    1216              :                 return -ENOMEM;
    1217              : 
    1218            1 :         adev->auxdrv_data =
    1219            1 :                 (const struct ipu6_auxdrv_data *)auxdev_id->driver_data;
    1220            1 :         adev->auxdrv = to_auxiliary_drv(auxdev->dev.driver);
    1221            1 :         isys->adev = adev;
    1222            1 :         isys->pdata = adev->pdata;
    1223            1 :         csi2_pdata = &isys->pdata->ipdata->csi2;
    1224              : 
    1225            1 :         isys->csi2 = devm_kcalloc(&auxdev->dev, csi2_pdata->nports,
    1226              :                                   sizeof(*isys->csi2), GFP_KERNEL);
    1227            1 :         if (!isys->csi2)
    1228              :                 return -ENOMEM;
    1229              : 
    1230            1 :         ret = ipu6_mmu_hw_init(adev->mmu);
    1231            1 :         if (ret)
    1232              :                 return ret;
    1233              : 
    1234              : #ifdef IPU6 // Disabled for IPU4
    1235              :         /* initial sensor type */
    1236              :         isys->sensor_type = isys->pdata->ipdata->sensor_type_start;
    1237              : #endif
    1238              : 
    1239            1 :         spin_lock_init(&isys->streams_lock);
    1240            1 :         spin_lock_init(&isys->power_lock);
    1241            1 :         isys->power = 0;
    1242            1 :         isys->phy_termcal_val = 0;
    1243              : 
    1244            1 :         mutex_init(&isys->mutex);
    1245            1 :         mutex_init(&isys->stream_mutex);
    1246              : 
    1247            1 :         spin_lock_init(&isys->listlock);
    1248            1 :         INIT_LIST_HEAD(&isys->framebuflist);
    1249            1 :         INIT_LIST_HEAD(&isys->framebuflist_fw);
    1250              : 
    1251            1 :         isys->icache_prefetch = 0;
    1252              : 
    1253              :         dev_set_drvdata(&auxdev->dev, isys);
    1254              : 
    1255            1 :         isys_stream_init(isys);
    1256              : 
    1257            1 :         if (!isp->secure_mode) {
    1258            0 :                 fw = isp->cpd_fw;
    1259            0 :                 ret = ipu6_buttress_map_fw_image(adev, fw, &adev->fw_sgt);
    1260            0 :                 if (ret)
    1261            0 :                         goto release_firmware;
    1262              : 
    1263            0 :                 ret = ipu6_cpd_create_pkg_dir(adev, isp->cpd_fw->data);
    1264            0 :                 if (ret)
    1265            0 :                         goto remove_shared_buffer;
    1266              :         }
    1267              : 
    1268            1 :         cpu_latency_qos_add_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
    1269              : 
    1270            1 :         ret = alloc_fw_msg_bufs(isys, 20);
    1271            1 :         if (ret < 0)
    1272            0 :                 goto out_remove_pkg_dir_shared_buffer;
    1273              : 
    1274              : #ifdef IPU6 // Disabled for IPU4
    1275              :         isys_iwake_watermark_init(isys);
    1276              : 
    1277              :         if (is_ipu6se(adev->isp->hw_ver))
    1278              :                 isys->phy_set_power = ipu6_isys_jsl_phy_set_power;
    1279              :         else if (is_ipu6ep_mtl(adev->isp->hw_ver))
    1280              :                 isys->phy_set_power = ipu6_isys_dwc_phy_set_power;
    1281              :         else
    1282              :                 isys->phy_set_power = ipu6_isys_mcd_phy_set_power;
    1283              : #endif
    1284              : 
    1285            1 :         ret = isys_register_devices(isys);
    1286            1 :         if (ret)
    1287            0 :                 goto free_fw_msg_bufs;
    1288              : 
    1289            1 :         ipu6_mmu_hw_cleanup(adev->mmu);
    1290              : 
    1291            1 :         return 0;
    1292              : 
    1293              : free_fw_msg_bufs:
    1294            0 :         free_fw_msg_bufs(isys);
    1295            0 : out_remove_pkg_dir_shared_buffer:
    1296            0 :         cpu_latency_qos_remove_request(&isys->pm_qos);
    1297            0 :         if (!isp->secure_mode)
    1298            0 :                 ipu6_cpd_free_pkg_dir(adev);
    1299            0 : remove_shared_buffer:
    1300            0 :         if (!isp->secure_mode)
    1301            0 :                 ipu6_buttress_unmap_fw_image(adev, &adev->fw_sgt);
    1302            0 : release_firmware:
    1303            0 :         if (!isp->secure_mode)
    1304            0 :                 release_firmware(adev->fw);
    1305              : 
    1306              :         for (i = 0; i < IPU4_ISYS_MAX_STREAMS; i++)
    1307              :                 mutex_destroy(&isys->streams[i].mutex);
    1308              : 
    1309              :         mutex_destroy(&isys->mutex);
    1310              :         mutex_destroy(&isys->stream_mutex);
    1311              : 
    1312            0 :         ipu6_mmu_hw_cleanup(adev->mmu);
    1313              : 
    1314            0 :         return ret;
    1315              : }
    1316              : 
    1317            0 : static void isys_remove(struct auxiliary_device *auxdev)
    1318              : {
    1319              :         struct ipu6_bus_device *adev = auxdev_to_adev(auxdev);
    1320              :         struct ipu6_isys *isys = dev_get_drvdata(&auxdev->dev);
    1321            0 :         struct ipu6_device *isp = adev->isp;
    1322              :         unsigned int i;
    1323              : 
    1324            0 :         free_fw_msg_bufs(isys);
    1325              : 
    1326            0 :         isys_unregister_devices(isys);
    1327              :         isys_notifier_cleanup(isys);
    1328              : 
    1329            0 :         cpu_latency_qos_remove_request(&isys->pm_qos);
    1330              : 
    1331            0 :         if (!isp->secure_mode) {
    1332            0 :                 ipu6_cpd_free_pkg_dir(adev);
    1333            0 :                 ipu6_buttress_unmap_fw_image(adev, &adev->fw_sgt);
    1334            0 :                 release_firmware(adev->fw);
    1335              :         }
    1336              : 
    1337              :         for (i = 0; i < IPU4_ISYS_MAX_STREAMS; i++)
    1338              :                 mutex_destroy(&isys->streams[i].mutex);
    1339              : 
    1340              : #ifdef IPU6 // Disabled for IPU4
    1341              :         isys_iwake_watermark_cleanup(isys);
    1342              : #endif
    1343              :         mutex_destroy(&isys->stream_mutex);
    1344              :         mutex_destroy(&isys->mutex);
    1345            0 : }
    1346              : 
    1347              : struct fwmsg {
    1348              :         int type;
    1349              :         char *msg;
    1350              :         bool valid_ts;
    1351              : };
    1352              : 
    1353              : static const struct fwmsg fw_msg[] = {
    1354              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE, "STREAM_OPEN_DONE", 0},
    1355              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_CLOSE_ACK, "STREAM_CLOSE_ACK", 0},
    1356              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_START_ACK, "STREAM_START_ACK", 0},
    1357              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK,
    1358              :          "STREAM_START_AND_CAPTURE_ACK", 0},
    1359              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_STOP_ACK, "STREAM_STOP_ACK", 0},
    1360              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_FLUSH_ACK, "STREAM_FLUSH_ACK", 0},
    1361              :         {IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY, "PIN_DATA_READY", 1},
    1362              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK, "STREAM_CAPTURE_ACK", 0},
    1363              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE,
    1364              :          "STREAM_START_AND_CAPTURE_DONE", 1},
    1365              :         {IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE, "STREAM_CAPTURE_DONE", 1},
    1366              :         {IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF, "FRAME_SOF", 1},
    1367              :         {IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF, "FRAME_EOF", 1},
    1368              :         {IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY, "STATS_READY", 1},
    1369              :         {-1, "UNKNOWN MESSAGE", 0}
    1370              : };
    1371              : 
    1372              : static u32 resp_type_to_index(int type)
    1373              : {
    1374              :         unsigned int i;
    1375              : 
    1376           49 :         for (i = 0; i < ARRAY_SIZE(fw_msg); i++)
    1377           49 :                 if (fw_msg[i].type == type)
    1378              :                         return i;
    1379              : 
    1380              :         return  ARRAY_SIZE(fw_msg) - 1;
    1381              : }
    1382              : 
    1383           13 : static int isys_isr_one(struct ipu6_bus_device *adev)
    1384              : {
    1385              :         struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev);
    1386              :         struct ipu6_fw_isys_resp_info_abi *resp;
    1387              :         struct ipu6_isys_stream *stream;
    1388              :         struct ipu6_isys_csi2 *csi2 = NULL;
    1389              :         u32 index;
    1390              :         u64 ts;
    1391              : 
    1392           13 :         if (!isys->fwcom)
    1393              :                 return 1;
    1394              : 
    1395           13 :         resp = ipu6_fw_isys_get_resp(isys->fwcom, IPU4_BASE_MSG_RECV_QUEUES);
    1396           13 :         if (!resp)
    1397              :                 return 1;
    1398              : 
    1399            8 :         ts = (u64)resp->timestamp[1] << 32 | resp->timestamp[0];
    1400              : 
    1401            8 :         index = resp_type_to_index(resp->type);
    1402           12 :         dev_dbg(&adev->auxdev.dev,
    1403              :                 "FW resp %02d %s, stream %u, ts 0x%16.16llx, pin %d\n",
    1404              :                 resp->type, fw_msg[index].msg, resp->stream_handle,
    1405              :                 fw_msg[index].valid_ts ? ts : 0, resp->pin_id);
    1406              : 
    1407            8 :         if (resp->error_info.error == IPU6_FW_ISYS_ERROR_STREAM_IN_SUSPENSION)
    1408              :                 /* Suspension is kind of special case: not enough buffers */
    1409            0 :                 dev_dbg(&adev->auxdev.dev,
    1410              :                         "FW error resp SUSPENSION, details %d\n",
    1411              :                         resp->error_info.error_details);
    1412            8 :         else if (resp->error_info.error)
    1413            0 :                 dev_dbg(&adev->auxdev.dev,
    1414              :                         "FW error resp error %d, details %d\n",
    1415              :                         resp->error_info.error, resp->error_info.error_details);
    1416              : 
    1417            8 :         if (resp->stream_handle >= IPU4_ISYS_MAX_STREAMS) {
    1418            0 :                 dev_err(&adev->auxdev.dev, "bad stream handle %u\n",
    1419              :                         resp->stream_handle);
    1420            0 :                 goto leave;
    1421              :         }
    1422              : 
    1423            8 :         stream = ipu6_isys_query_stream_by_handle(isys, resp->stream_handle);
    1424            8 :         if (!stream) {
    1425            0 :                 dev_err(&adev->auxdev.dev, "stream of stream_handle %u is unused\n",
    1426              :                         resp->stream_handle);
    1427            0 :                 goto leave;
    1428              :         }
    1429            8 :         stream->error = resp->error_info.error;
    1430              : 
    1431            8 :         csi2 = ipu6_isys_subdev_to_csi2(stream->asd);
    1432              : 
    1433            8 :         switch (resp->type) {
    1434            1 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_OPEN_DONE:
    1435            1 :                 complete(&stream->stream_open_completion);
    1436            1 :                 break;
    1437            1 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_CLOSE_ACK:
    1438            1 :                 complete(&stream->stream_close_completion);
    1439            1 :                 break;
    1440            0 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_ACK:
    1441            0 :                 complete(&stream->stream_start_completion);
    1442            0 :                 break;
    1443            1 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_ACK:
    1444            1 :                 ipu6_put_fw_msg_buf(ipu6_bus_get_drvdata(adev),
    1445            1 :                                     resp->buf_handle);
    1446            1 :                 complete(&stream->stream_start_completion);
    1447            1 :                 break;
    1448            0 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_STOP_ACK:
    1449            0 :                 complete(&stream->stream_stop_completion);
    1450            0 :                 break;
    1451            1 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_FLUSH_ACK:
    1452            1 :                 complete(&stream->stream_stop_completion);
    1453            1 :                 break;
    1454            2 :         case IPU6_FW_ISYS_RESP_TYPE_PIN_DATA_READY:
    1455            2 :                 if (resp->pin_id < IPU6_ISYS_OUTPUT_PINS &&
    1456            2 :                     stream->output_pins_queue[resp->pin_id])
    1457            2 :                         ipu6_isys_queue_buf_ready(stream, resp);
    1458              :                 else
    1459            0 :                         dev_warn(&adev->auxdev.dev,
    1460              :                                  "%d:No queue for pin id %d\n",
    1461              :                                  resp->stream_handle, resp->pin_id);
    1462            2 :                 if (csi2)
    1463            2 :                         ipu4_isys_csi2_error(csi2);
    1464              : 
    1465              :                 break;
    1466            0 :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_ACK:
    1467            0 :                 ipu6_put_fw_msg_buf(ipu6_bus_get_drvdata(adev),
    1468            0 :                                     resp->buf_handle);
    1469            0 :                 break;
    1470              :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE:
    1471              :         case IPU6_FW_ISYS_RESP_TYPE_STREAM_CAPTURE_DONE:
    1472              :                 break;
    1473            2 :         case IPU6_FW_ISYS_RESP_TYPE_FRAME_SOF:
    1474              : 
    1475            2 :                 ipu6_isys_csi2_sof_event_by_stream(stream);
    1476            2 :                 stream->seq[stream->seq_index].sequence =
    1477            2 :                         atomic_read(&stream->sequence) - 1;
    1478            2 :                 stream->seq[stream->seq_index].timestamp = ts;
    1479            2 :                 dev_dbg(&adev->auxdev.dev,
    1480              :                         "sof: handle %d: (index %u), timestamp 0x%16.16llx\n",
    1481              :                         resp->stream_handle,
    1482              :                         stream->seq[stream->seq_index].sequence, ts);
    1483            2 :                 stream->seq_index = (stream->seq_index + 1)
    1484            2 :                         % IPU6_ISYS_MAX_PARALLEL_SOF;
    1485            2 :                 break;
    1486              :         case IPU6_FW_ISYS_RESP_TYPE_FRAME_EOF:
    1487              : #ifdef IPU6 // Disabled for IPU4
    1488              :                 ipu6_isys_csi2_eof_event_by_stream(stream);
    1489              : #endif
    1490            0 :                 dev_dbg(&adev->auxdev.dev,
    1491              :                         "eof: handle %d: (index %u), timestamp 0x%16.16llx\n",
    1492              :                         resp->stream_handle,
    1493              :                         stream->seq[stream->seq_index].sequence, ts);
    1494              :                 break;
    1495              :         case IPU6_FW_ISYS_RESP_TYPE_STATS_DATA_READY:
    1496              :                 break;
    1497            0 :         default:
    1498            0 :                 dev_err(&adev->auxdev.dev, "%d:unknown response type %u\n",
    1499              :                         resp->stream_handle, resp->type);
    1500            0 :                 break;
    1501              :         }
    1502              : 
    1503            8 :         ipu6_isys_put_stream(stream);
    1504            8 : leave:
    1505            8 :         ipu6_fw_isys_put_resp(isys->fwcom, IPU4_BASE_MSG_RECV_QUEUES);
    1506            8 :         return 0;
    1507              : }
    1508              : 
    1509              : static const struct ipu6_auxdrv_data ipu6_isys_auxdrv_data = {
    1510              :         .isr = isys_isr,
    1511              :         .isr_threaded = NULL,
    1512              :         .wake_isr_thread = false,
    1513              : };
    1514              : 
    1515              : static const struct auxiliary_device_id ipu6_isys_id_table[] = {
    1516              :         {
    1517              :                 .name = "intel_ipu6.isys",
    1518              :                 .driver_data = (kernel_ulong_t)&ipu6_isys_auxdrv_data,
    1519              :         },
    1520              :         {
    1521              :                 .name = "intel_ipu4.isys",
    1522              :                 .driver_data = (kernel_ulong_t)&ipu6_isys_auxdrv_data,
    1523              :         },
    1524              :         {},
    1525              : };
    1526              : MODULE_DEVICE_TABLE(auxiliary, ipu6_isys_id_table);
    1527              : 
    1528              : static struct auxiliary_driver isys_driver = {
    1529              :         .name = IPU6_ISYS_NAME,
    1530              :         .probe = isys_probe,
    1531              :         .remove = isys_remove,
    1532              :         .id_table = ipu6_isys_id_table,
    1533              :         .driver = {
    1534              :                 .pm = &isys_pm_ops,
    1535              :         },
    1536              : };
    1537              : 
    1538            1 : module_auxiliary_driver(isys_driver);
    1539              : 
    1540              : MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
    1541              : MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
    1542              : MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
    1543              : MODULE_AUTHOR("Yunliang Ding <yunliang.ding@intel.com>");
    1544              : MODULE_AUTHOR("Hongju Wang <hongju.wang@intel.com>");
    1545              : MODULE_LICENSE("GPL");
    1546              : MODULE_DESCRIPTION("Intel IPU4 input system driver");
    1547              : MODULE_IMPORT_NS(INTEL_IPU6);
    1548              : MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
        

Generated by: LCOV version 2.0-1