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