| /* SPDX-License-Identifier: GPL-2.0-only */ | |
| /* | |
| * Copyright (c) 2026 Intel Corporation | |
| */ | |
| #ifndef _ICVS_H | |
| #define _ICVS_H | |
| #include <linux/bits.h> | |
| #include <linux/completion.h> | |
| #include <linux/mutex.h> | |
| #include <linux/workqueue.h> | |
| #include <linux/types.h> | |
| #include <linux/wait.h> | |
| #include <media/media-entity.h> | |
| #include <media/v4l2-ctrls.h> | |
| #include <media/v4l2-subdev.h> | |
| /* | |
| * PCI device IDs for all IPU generations that co-exist with the CVS bridge. | |
| * IPU7 (0x645d) is shared by MTL and LNL; IPU7P5 (0xb05d) is shared by | |
| * ARL and PTL. These are not yet in the shared ipu6-pci-table so they are | |
| * listed here alongside the IPU6 family for probe-time IPU discovery. | |
| */ | |
| struct gpio_desc; | |
| struct i2c_client; | |
| /* | |
| * GPIO resource counts (ACPI enumerated). | |
| * | |
| * 4-GPIO configuration has a wake IRQ and supports asynchronous messaging. | |
| * 2-GPIO configuration has no IRQ, so communication is synchronous only. | |
| */ | |
| #define ICVS_GPIO_ASYNC 4 | |
| #define ICVS_GPIO_SYNC 2 | |
| /* Firmware response prefix (optional, for protocol revision 2.x or newer) */ | |
| #define ICVS_PREFIX_VAL 0xCAFEB0BA | |
| /* | |
| * CSI bridge sub-device definitions | |
| */ | |
| /** | |
| * enum icvs_csi_cmd_id - Low-level CSI bridge command identifiers | |
| * | |
| * These numeric IDs are part of the legacy CSI-side protocol not mapped | |
| * directly to the higher level firmware opcodes in enum icvs_command. Only | |
| * a minimal subset is presently issued/handled by the driver. Others are | |
| * reserved for future expansion of the CSI bridge feature set. | |
| * | |
| * @ICVS_CSI_SET_OWNER: Set CSI sensor ownership between host and CVS | |
| * @ICVS_CSI_SET_CONF: Apply CSI link configuration parameters | |
| * @ICVS_CSI_PRIVACY_NOTIF: Notify host of a privacy state transition | |
| */ | |
| enum icvs_csi_cmd_id { | |
| ICVS_CSI_SET_OWNER = 0, | |
| ICVS_CSI_SET_CONF = 2, | |
| ICVS_CSI_PRIVACY_NOTIF = 6, | |
| }; | |
| /** | |
| * enum icvs_csi_link_owner - CSI-2 link / sensor ownership | |
| * | |
| * Ownership reflects which endpoint currently controls the attached image | |
| * sensor over the CSI-2 link. Transitions may gate streaming or reconfigure | |
| * link parameters. The host requests ownership changes via protocol opcodes | |
| * and may need to assert GPIO signals on platforms without full capability. | |
| * | |
| * @ICVS_CSI_LINK_HOST: Host (Linux) owns the sensor and may start streaming | |
| * @ICVS_CSI_LINK_CVS: CVS firmware owns the sensor (host must not stream) | |
| */ | |
| enum icvs_csi_link_owner { | |
| ICVS_CSI_LINK_HOST, | |
| ICVS_CSI_LINK_CVS, | |
| }; | |
| /** | |
| * enum icvs_csi_privacy_status - Reported privacy state | |
| * | |
| * Reflects user privacy (e.g. camera LED assertion and stream gating). The | |
| * MAX value is a sentinel used for bounds checking and is not a real state. | |
| * | |
| * @ICVS_CSI_PRIVACY_OFF: Privacy not asserted (LED off, streaming permitted) | |
| * @ICVS_CSI_PRIVACY_ON: Privacy asserted (LED on and/or stream gated) | |
| * @ICVS_CSI_PRIVACY_MAX: Sentinel; not a valid operational value | |
| */ | |
| enum icvs_csi_privacy_status { | |
| ICVS_CSI_PRIVACY_OFF, | |
| ICVS_CSI_PRIVACY_ON, | |
| ICVS_CSI_PRIVACY_MAX | |
| }; | |
| /** | |
| * enum icvs_csi_pads - Media pads exposed by the CVS sub-device | |
| * | |
| * The bridge presents a single sink (from the remote sensor) and a single | |
| * source (toward the rest of the media graph / consumers). NUM_PADS is used | |
| * for sizing arrays and iteration; it is not a real pad index. | |
| * | |
| * @ICVS_CSI_PAD_SINK: Sink pad receiving frames from remote sensor | |
| * @ICVS_CSI_PAD_SOURCE: Source pad emitting frames to downstream entities | |
| * @ICVS_CSI_NUM_PADS: Count sentinel (array size / iteration bound) | |
| */ | |
| enum icvs_csi_pads { | |
| ICVS_CSI_PAD_SINK, | |
| ICVS_CSI_PAD_SOURCE, | |
| ICVS_CSI_NUM_PADS | |
| }; | |
| /* | |
| * Core driver structures and functions used by both I2C and platform modes | |
| */ | |
| /** | |
| * DOC: CVS device quirk flags | |
| * | |
| * These bit flag macros describe per-device behavioral adjustments applied | |
| * after VID/PID matching (see cvs_i2c_check() and cvs_apply_quirks()). They | |
| * allow the driver to selectively alter logic paths for firmware / hardware | |
| * variants without introducing hard-coded conditionals at each call site. | |
| * | |
| * @ICVS_NO_MIPI_CONFIG: Device firmware performs its own MIPI link setup; | |
| * skip sending HOST_SET_MIPI_CONFIG. | |
| * @ICVS_SKIP_FW_RESET: Skip issuing a post firmware-update reset sequence. | |
| * @ICVS_NO_CAPS: Device firmware does not support GET_DEV_CAPABILITY; | |
| * skip capability query and treat caps as unsupported. | |
| * @ICVS_FW_BUF_SIZE_256: Firmware expects chunk transfer buffer size of 256 | |
| * bytes (override defaults if they differ). | |
| * @ICVS_FW_HEADER_SIZE_256: Firmware header size fixed at 256 bytes offset | |
| * for start of payload data. | |
| * @ICVS_HOST_SENSOR_PWR_CTRL: Host must control sensor power sequencing. | |
| * @ICVS_HOST_PRIV_CTRL: Host owns privacy LED gating. | |
| * @ICVS_HOST_VISION_SENSING: Host enables vision sensing capability bit | |
| * @ICVS_NO_FW_UPDATE: Device does not support firmware update. | |
| */ | |
| #define ICVS_NO_MIPI_CONFIG BIT(0) | |
| #define ICVS_SKIP_FW_RESET BIT(1) | |
| #define ICVS_NO_CAPS BIT(2) | |
| #define ICVS_FW_BUF_SIZE_256 BIT(3) | |
| #define ICVS_FW_HEADER_SIZE_256 BIT(4) | |
| #define ICVS_HOST_SENSOR_PWR_CTRL BIT(5) | |
| #define ICVS_HOST_PRIV_CTRL BIT(6) | |
| #define ICVS_HOST_VISION_SENSING BIT(7) | |
| #define ICVS_NO_FW_UPDATE BIT(8) | |
| /** | |
| * struct icvs_device_quirk - Device-specific quirk entry | |
| * @vid: Vendor ID | |
| * @pid: Product ID | |
| * @quirks: Quirk flags for this device | |
| */ | |
| struct icvs_device_quirk { | |
| u16 vid; | |
| u16 pid; | |
| unsigned long quirks; | |
| }; | |
| /** | |
| * struct icvs_dt_config - Data type configuration for a virtual channel | |
| * @pixel_width: Pixel width in pixels | |
| * @pixel_height: Pixel height in pixels | |
| * @data_type: MIPI CSI-2 data type (RAW10, RAW12, etc.) | |
| * @reserved: Reserved for future use | |
| */ | |
| struct icvs_dt_config { | |
| u16 pixel_width; | |
| u16 pixel_height; | |
| u8 data_type; | |
| u8 reserved[3]; | |
| }; | |
| /** | |
| * struct icvs_vc_config - Virtual channel configuration | |
| * @vc: Virtual channel index (0-31) | |
| * @dt_count: Number of data types configured | |
| * @dt_configs: Array of data type configurations (up to 4) | |
| * @reserved: Reserved for future use | |
| */ | |
| struct icvs_vc_config { | |
| u8 vc; | |
| u8 dt_count; | |
| struct icvs_dt_config dt_configs[4]; | |
| u8 reserved[6]; | |
| }; | |
| /** | |
| * struct icvs_link_cfg - Host to CVS CSI link configuration | |
| * @fps: Frames per second | |
| * @nr_of_lanes: Number of CSI-2 data lanes used | |
| * @phy_mode: 0 = DPHY, 1 = CPHY | |
| * @vc_count: Number of virtual channels enabled | |
| * @vc_configs: Per-VC configuration | |
| * @link_freq: Link frequency in Hz | |
| * @reserved: Reserved for future use | |
| */ | |
| struct icvs_link_cfg { | |
| u8 fps; | |
| u8 nr_of_lanes; | |
| u8 phy_mode; | |
| u8 vc_count; | |
| struct icvs_vc_config vc_configs[4]; | |
| u32 link_freq; | |
| u8 reserved[8]; | |
| }; | |
| /** | |
| * struct icvs_fw_version - Firmware version tuple | |
| * @major: Major version | |
| * @minor: Minor version | |
| * @hotfix: Hotfix/patch level | |
| * @build: Build number | |
| */ | |
| struct icvs_fw_version { | |
| u32 major; | |
| u32 minor; | |
| u32 hotfix; | |
| u32 build; | |
| }; | |
| /** | |
| * struct icvs_vid_pid - Device vendor/product IDs | |
| * @v_id: Vendor ID | |
| * @p_id: Product ID | |
| */ | |
| struct icvs_vid_pid { | |
| u16 v_id; | |
| u16 p_id; | |
| }; | |
| /** | |
| * struct icvs_mipi_data_packet - Encapsulated MIPI link configuration packet | |
| * @cmd_id: Command identifier | |
| * @size: Payload size (bytes) | |
| * @crc: Checksum over payload | |
| * @conf: CSI link configuration | |
| * @reserved: Reserved for future use | |
| */ | |
| struct icvs_mipi_data_packet { | |
| __be16 cmd_id; | |
| u32 size; | |
| u32 crc; | |
| struct icvs_link_cfg conf; | |
| u8 reserved[70]; | |
| } __packed; | |
| /** | |
| * struct icvs_mipi_read_packet - Read-back MIPI configuration | |
| * @size: Payload size | |
| * @crc: Payload checksum | |
| * @conf: CSI link configuration | |
| */ | |
| struct icvs_mipi_read_packet { | |
| u32 size; | |
| u32 crc; | |
| struct icvs_link_cfg conf; | |
| }; | |
| /* Host identifier bitfield masks */ | |
| #define ICVS_HOST_ID_RGBCAMERA_PWRUP BIT(31) | |
| #define ICVS_HOST_ID_PRIVACY_LED BIT(30) | |
| #define ICVS_HOST_ID_DEVICE_POWER GENMASK(29, 28) | |
| #define ICVS_HOST_ID_VISION_SENSING BIT(27) | |
| /* Device state bitfield masks (u8) */ | |
| #define ICVS_DEV_STATE_PRIVACY BIT(0) | |
| #define ICVS_DEV_STATE_ON BIT(1) | |
| #define ICVS_DEV_STATE_SENSOR_OWNER BIT(2) | |
| #define ICVS_DEV_STATE_DOWNLOAD BIT(4) | |
| #define ICVS_DEV_STATE_ERROR BIT(6) | |
| #define ICVS_DEV_STATE_BUSY BIT(7) | |
| /* Device capability bitfield masks (u16) */ | |
| #define ICVS_CAP_HOST_MIPI_REQUIRED BIT(15) | |
| #define ICVS_CAP_FW_ANTIROLLBACK BIT(14) | |
| #define ICVS_CAP_PRIVACY2VISIONDRIVER BIT(13) | |
| #define ICVS_CAP_FWUPDATE_RESET_HOST BIT(12) | |
| #define ICVS_CAP_NO_CAMERA_FWUPDATE BIT(11) | |
| #define ICVS_CAP_POWER_DOMAIN_SUPPORT BIT(10) | |
| #define ICVS_CAP_FW_FLASHED_IN_PLACE BIT(9) | |
| #define ICVS_CAP_IO_CONTEXT_HOT BIT(8) | |
| /** | |
| * struct icvs_dev_capabilities - Protocol capabilities reported by device | |
| * @protocol_version_major: Major protocol version | |
| * @protocol_version_minor: Minor protocol version | |
| * @capability: Capability bitfield - use ICVS_CAP_* masks | |
| * @max_packet_time: Max packet processing time (ms) | |
| * @max_post_dl_time: Max post-download time (s) | |
| */ | |
| struct icvs_dev_capabilities { | |
| u8 protocol_version_major; | |
| u8 protocol_version_minor; | |
| u16 capability; | |
| u16 max_packet_time; | |
| u16 max_post_dl_time; | |
| }; | |
| /** | |
| * struct icvs_cmd - Generic command container | |
| * @cmd_id: Command identifier | |
| * @param: Parameter union providing multiple variants | |
| * @param.param: Raw parameter | |
| * @param.host_id: Host identifier (ICVS_SET_DEV_HOST_ID) - use | |
| * ICVS_HOST_ID_* masks | |
| * @param.conf: CSI link configuration (ICVS_HOST_SET_MIPI_CONFIG) | |
| */ | |
| struct icvs_cmd { | |
| __be16 cmd_id; | |
| union { | |
| u32 param; | |
| u32 host_id; | |
| struct icvs_link_cfg conf; | |
| } param; | |
| } __packed; | |
| /** | |
| * struct icvs_resp - Firmware response container | |
| * @status: Internal status code | |
| * @cmd_id: Original command identifier | |
| * @resp: Response union containing variant payload | |
| * @resp.state: Device state response (u8, use ICVS_DEV_STATE_* masks) | |
| * @resp.cap: Capability response | |
| * @resp.conf: Link configuration response | |
| * @resp.mipi_read: Raw link config read-back | |
| * @resp.vid_pid: Vendor/product identifiers | |
| * @resp.fw_version: Firmware version tuple | |
| */ | |
| struct icvs_resp { | |
| u32 status; | |
| __be16 cmd_id; | |
| union { | |
| u8 state; | |
| struct icvs_dev_capabilities cap; | |
| struct icvs_link_cfg conf; | |
| struct icvs_mipi_read_packet mipi_read; | |
| struct icvs_vid_pid vid_pid; | |
| struct icvs_fw_version fw_version; | |
| } resp; | |
| }; | |
| /** | |
| * enum icvs_resources - Device capability / resource category | |
| * | |
| * Categorizes hardware resource availability which influences protocol | |
| * features (e.g. reset control, wake IRQ, GPIO mediated ownership). Light | |
| * capability devices expose a reduced set of control GPIOs; full capability | |
| * devices provide all optional signals and features. NOTSUP represents an | |
| * unsupported or uninitialized state. | |
| * | |
| * @ICVS_NOTSUP: Capability not supported / not yet determined | |
| * @ICVS_LIGHTCAP: Light capability (limited GPIO / no dedicated wake IRQ) | |
| * @ICVS_FULLCAP: Full capability (reset GPIO, wake IRQ, extended protocol) | |
| */ | |
| enum icvs_resources { | |
| ICVS_NOTSUP, | |
| ICVS_LIGHTCAP, | |
| ICVS_FULLCAP, | |
| }; | |
| /** | |
| * enum icvs_command - Protocol command opcodes (firmware space 0x0800+) | |
| * @ICVS_GET_DEV_STATE: Query current device state bitfield | |
| * @ICVS_GET_DEV_FW_VERSION: Retrieve firmware version tuple | |
| * @ICVS_GET_DEV_VID_PID: Read vendor / product identifiers | |
| * @ICVS_GET_DEV_ERR_CODE: Fetch last error code (if any) | |
| * @ICVS_GET_DEV_CAPABILITY: Read protocol capability structure | |
| * @ICVS_SET_DEV_HOST_ID: Set host identity / ownership bits | |
| * @ICVS_GET_DEV_HOST_ID: Read back host identity | |
| * @ICVS_FW_LOADER_START: Begin firmware download sequence | |
| * @ICVS_FW_LOADER_DATA: Stream a chunk of firmware payload | |
| * @ICVS_FW_LOADER_END: End firmware download / trigger flash | |
| * @ICVS_HOST_GET_MIPI_CONFIG: Request current MIPI CSI link configuration | |
| * @ICVS_HOST_SET_MIPI_CONFIG: Apply new MIPI CSI link configuration | |
| * @ICVS_HOST_SENSOR_OWNER: Toggle CSI sensor ownership (GPIO assist) | |
| */ | |
| enum icvs_command { | |
| ICVS_GET_DEV_STATE = 0x0800, | |
| ICVS_GET_DEV_FW_VERSION = 0x0801, | |
| ICVS_GET_DEV_VID_PID = 0x0802, | |
| ICVS_GET_DEV_ERR_CODE = 0x0803, | |
| ICVS_GET_DEV_CAPABILITY = 0x0804, | |
| ICVS_SET_DEV_HOST_ID = 0x0805, | |
| ICVS_GET_DEV_HOST_ID = 0x0806, | |
| ICVS_FW_LOADER_START = 0x0820, | |
| ICVS_FW_LOADER_DATA = 0x0821, | |
| ICVS_FW_LOADER_END = 0x0822, | |
| ICVS_HOST_GET_MIPI_CONFIG = 0x082F, | |
| ICVS_HOST_SET_MIPI_CONFIG = 0x0830, | |
| ICVS_HOST_SENSOR_OWNER = 0x0831, | |
| }; | |
| /** | |
| * enum icvs_state - Device state bitfield flags | |
| * | |
| * These flags correspond to bits in the device state byte returned via | |
| * GET_DEV_STATE and decoded in union icvs_dev_state. Multiple bits may be | |
| * asserted simultaneously. Reserved bits are omitted. | |
| * | |
| * @ICVS_DEVICE_OFF_STATE: Raw zero value; device is powered off or | |
| * not yet ready | |
| * @ICVS_DEVICE_PRIVACY_ON: Privacy mode active (LED asserted and/or | |
| * stream gated) | |
| * @ICVS_DEVICE_ON_STATE: Device powered and responsive to protocol commands | |
| * @ICVS_DEVICE_SENSOR_OWNER: CVS currently owns the attached CSI sensor | |
| * @ICVS_DEVICE_DWNLD_STATE: Firmware download / flash operation in progress | |
| * @ICVS_DEVICE_ERROR_STATE: Device has reported an error (query | |
| * ICVS_GET_DEV_ERR_CODE) | |
| * @ICVS_DEVICE_BUSY_STATE: Device is busy processing a prior command | |
| */ | |
| enum icvs_state { | |
| ICVS_DEVICE_OFF_STATE = 0x00, | |
| ICVS_DEVICE_PRIVACY_ON = BIT(0), | |
| ICVS_DEVICE_ON_STATE = BIT(1), | |
| ICVS_DEVICE_SENSOR_OWNER = BIT(2), | |
| ICVS_DEVICE_DWNLD_STATE = BIT(4), | |
| ICVS_DEVICE_ERROR_STATE = BIT(6), | |
| ICVS_DEVICE_BUSY_STATE = BIT(7), | |
| }; | |
| /** | |
| * struct icvs - Core CVS device context | |
| * @i2c_client: I2C client (NULL in platform-only mode) | |
| * @work: Delayed work for polling device state / completion | |
| * @wq_resp: Last response container populated by workqueue | |
| * @cmd_completion: Completion for command waiters | |
| * @lock: Mutex protecting command submission & shared state | |
| * @subdev: V4L2 sub-device representing the CSI bridge entity | |
| * @remote: Remote media pad connected to upstream camera sensor | |
| * @notifier: Async notifier for remote sensor discovery | |
| * @ctrl_handler: V4L2 control handler | |
| * @freq_ctrl: (future) frequency control pointer | |
| * @pads: Local media pads (sink/source) | |
| * @nr_of_lanes: Active CSI-2 lane count | |
| * @ipu_link: PM runtime device link (IPU consumer, CVS supplier) | |
| * @res: Resource capability (light/full) | |
| * @caps: Reported device protocol capabilities | |
| * @prefix: Firmware response prefix present | |
| * @quirks: Device-specific quirk flags | |
| * @rst: Reset GPIO (full capability only) | |
| * @req: Request GPIO (ownership signaling) | |
| * @resp: Response GPIO (ownership signaling) | |
| * @irq: Wake IRQ (full capability) | |
| * @hostwake_event: Waitqueue for wake events | |
| * @hostwake_event_arg: Wake event flag | |
| */ | |
| struct icvs { | |
| struct i2c_client *i2c_client; | |
| struct delayed_work work; | |
| struct icvs_resp wq_resp; | |
| struct completion cmd_completion; | |
| struct mutex lock; /* Protects command execution and device state */ | |
| struct v4l2_subdev subdev; | |
| struct media_pad *remote; | |
| struct v4l2_async_notifier notifier; | |
| struct v4l2_ctrl_handler ctrl_handler; | |
| struct v4l2_ctrl *freq_ctrl; | |
| struct media_pad pads[ICVS_CSI_NUM_PADS]; | |
| u32 nr_of_lanes; | |
| struct device_link *ipu_link; | |
| enum icvs_resources res; | |
| struct icvs_dev_capabilities caps; | |
| bool prefix; | |
| unsigned long quirks; | |
| struct gpio_desc *rst; | |
| struct gpio_desc *req; | |
| struct gpio_desc *resp; | |
| int irq; | |
| wait_queue_head_t hostwake_event; | |
| bool hostwake_event_arg; | |
| }; | |
| /** | |
| * cvs_dev - Helper returning the struct device for a CVS context | |
| * @ctx: CVS context | |
| * | |
| * Avoids repeating transport conditional logic at each call site when | |
| * acquiring the device pointer for logging or PM operations. | |
| * | |
| * Return: Device pointer (never NULL if @ctx is valid). | |
| */ | |
| static inline struct device *cvs_dev(struct icvs *ctx) | |
| { | |
| return ctx->i2c_client ? &ctx->i2c_client->dev : ctx->subdev.dev; | |
| } | |
| /* Cross-unit interfaces */ | |
| int cvs_send(struct icvs *ctx, struct icvs_cmd *cmd, size_t len); | |
| int cvs_set_link_owner(struct icvs *ctx, enum icvs_csi_link_owner owner); | |
| int cvs_csi_init(struct icvs *ctx, struct device *dev, struct i2c_client *i2c); | |
| void cvs_csi_remove(struct icvs *ctx); | |
| #endif /* _ICVS_H */ |