1/* SPDX-License-Identifier: GPL-2.0 */
2/* Author: Dan Scally <djrscally@gmail.com> */
3#ifndef __IPU_BRIDGE_H
4#define __IPU_BRIDGE_H
5
6#include <linux/property.h>
7#include <linux/types.h>
8#include <media/v4l2-fwnode.h>
9
10#define IPU_HID				"INT343E"
11#define IPU_MAX_LANES				4
12#define IPU_MAX_PORTS				4
13#define MAX_NUM_LINK_FREQS			3
14
15/* Values are educated guesses as we don't have a spec */
16#define IPU_SENSOR_ROTATION_NORMAL		0
17#define IPU_SENSOR_ROTATION_INVERTED		1
18
19#define IPU_SENSOR_CONFIG(_HID, _NR, ...)	\
20	(const struct ipu_sensor_config) {	\
21		.hid = _HID,			\
22		.nr_link_freqs = _NR,		\
23		.link_freqs = { __VA_ARGS__ }	\
24	}
25
26#define NODE_SENSOR(_HID, _PROPS)		\
27	(const struct software_node) {		\
28		.name = _HID,			\
29		.properties = _PROPS,		\
30	}
31
32#define NODE_PORT(_PORT, _SENSOR_NODE)		\
33	(const struct software_node) {		\
34		.name = _PORT,			\
35		.parent = _SENSOR_NODE,		\
36	}
37
38#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
39	(const struct software_node) {		\
40		.name = _EP,			\
41		.parent = _PORT,		\
42		.properties = _PROPS,		\
43	}
44
45#define NODE_VCM(_TYPE)				\
46	(const struct software_node) {		\
47		.name = _TYPE,			\
48	}
49
50enum ipu_sensor_swnodes {
51	SWNODE_SENSOR_HID,
52	SWNODE_SENSOR_PORT,
53	SWNODE_SENSOR_ENDPOINT,
54	SWNODE_IPU_PORT,
55	SWNODE_IPU_ENDPOINT,
56	/* below are optional / maybe empty */
57	SWNODE_IVSC_HID,
58	SWNODE_IVSC_SENSOR_PORT,
59	SWNODE_IVSC_SENSOR_ENDPOINT,
60	SWNODE_IVSC_IPU_PORT,
61	SWNODE_IVSC_IPU_ENDPOINT,
62	SWNODE_VCM,
63	SWNODE_COUNT
64};
65
66/* Data representation as it is in ACPI SSDB buffer */
67struct ipu_sensor_ssdb {
68	u8 version;
69	u8 sku;
70	u8 guid_csi2[16];
71	u8 devfunction;
72	u8 bus;
73	u32 dphylinkenfuses;
74	u32 clockdiv;
75	u8 link;
76	u8 lanes;
77	u32 csiparams[10];
78	u32 maxlanespeed;
79	u8 sensorcalibfileidx;
80	u8 sensorcalibfileidxInMBZ[3];
81	u8 romtype;
82	u8 vcmtype;
83	u8 platforminfo;
84	u8 platformsubinfo;
85	u8 flash;
86	u8 privacyled;
87	u8 degree;
88	u8 mipilinkdefined;
89	u32 mclkspeed;
90	u8 controllogicid;
91	u8 reserved1[3];
92	u8 mclkport;
93	u8 reserved2[13];
94} __packed;
95
96struct ipu_property_names {
97	char clock_frequency[16];
98	char rotation[9];
99	char orientation[12];
100	char bus_type[9];
101	char data_lanes[11];
102	char remote_endpoint[16];
103	char link_frequencies[17];
104};
105
106struct ipu_node_names {
107	char port[7];
108	char ivsc_sensor_port[7];
109	char ivsc_ipu_port[7];
110	char endpoint[11];
111	char remote_port[9];
112	char vcm[16];
113};
114
115struct ipu_sensor_config {
116	const char *hid;
117	const u8 nr_link_freqs;
118	const u64 link_freqs[MAX_NUM_LINK_FREQS];
119};
120
121struct ipu_sensor {
122	/* append ssdb.link(u8) in "-%u" format as suffix of HID */
123	char name[ACPI_ID_LEN + 4];
124	struct acpi_device *adev;
125
126	struct device *csi_dev;
127	struct acpi_device *ivsc_adev;
128	char ivsc_name[ACPI_ID_LEN + 4];
129
130	/* SWNODE_COUNT + 1 for terminating NULL */
131	const struct software_node *group[SWNODE_COUNT + 1];
132	struct software_node swnodes[SWNODE_COUNT];
133	struct ipu_node_names node_names;
134
135	u8 link;
136	u8 lanes;
137	u32 mclkspeed;
138	u32 rotation;
139	enum v4l2_fwnode_orientation orientation;
140	const char *vcm_type;
141
142	struct ipu_property_names prop_names;
143	struct property_entry ep_properties[5];
144	struct property_entry dev_properties[5];
145	struct property_entry ipu_properties[3];
146	struct property_entry ivsc_properties[1];
147	struct property_entry ivsc_sensor_ep_properties[4];
148	struct property_entry ivsc_ipu_ep_properties[4];
149
150	struct software_node_ref_args local_ref[1];
151	struct software_node_ref_args remote_ref[1];
152	struct software_node_ref_args vcm_ref[1];
153	struct software_node_ref_args ivsc_sensor_ref[1];
154	struct software_node_ref_args ivsc_ipu_ref[1];
155};
156
157typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev,
158					 struct ipu_sensor *sensor);
159
160struct ipu_bridge {
161	struct device *dev;
162	ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
163	char ipu_node_name[ACPI_ID_LEN];
164	struct software_node ipu_hid_node;
165	u32 data_lanes[4];
166	unsigned int n_sensors;
167	struct ipu_sensor sensors[IPU_MAX_PORTS];
168};
169
170#if IS_ENABLED(CONFIG_IPU_BRIDGE)
171int ipu_bridge_init(struct device *dev,
172		    ipu_parse_sensor_fwnode_t parse_sensor_fwnode);
173int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor);
174int ipu_bridge_instantiate_vcm(struct device *sensor);
175#else
176/* Use a define to avoid the @parse_sensor_fwnode argument getting evaluated */
177#define ipu_bridge_init(dev, parse_sensor_fwnode)	(0)
178static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; }
179#endif
180
181#endif
182