1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
|
/* 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
* @link_freq: Current link frequency (Hz)
* @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;
u64 link_freq;
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 */
|