brintos

brintos / linux-shallow public Read only

0
0
Text · 36.6 KiB · c4aff2e Raw
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, &ltrdid);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