xref: /linux/include/media/ipu-bridge.h (revision a20c843c9bc40ab8703a2b17fcbc69532baca692)
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/mod_devicetable.h>
7 #include <linux/property.h>
8 #include <linux/types.h>
9 #include <media/v4l2-fwnode.h>
10 
11 #define IPU_HID				"INT343E"
12 #define IPU_MAX_LANES				4
13 #define IPU_MAX_PORTS				4
14 #define MAX_NUM_LINK_FREQS			3
15 
16 /* Values are educated guesses as we don't have a spec */
17 #define IPU_SENSOR_ROTATION_NORMAL		0
18 #define IPU_SENSOR_ROTATION_INVERTED		1
19 
20 /* Flags for struct ipu_sensor_config */
21 /* The sensor's CSI-2 transmitter needs a non-continuous clock */
22 #define IPU_BR_FL_CSI2_CLK_NONCONTINUOUS	BIT(0)
23 
24 /*
25  * Sensor config specific to one or more IPUs, identified by their PCI product
26  * IDs, with flags describing what the sensor needs there. Entries for one HID
27  * must be adjacent in ipu_supported_sensors[], with the IPU-specific ones
28  * before the generic one.
29  */
30 #define IPU_SENSOR_CONFIG_MATCH_FL(_HID, _IDS, _FLAGS, _NR, ...)	\
31 	(const struct ipu_sensor_config) {				\
32 		.hid = _HID,						\
33 		.pci_ids = _IDS,					\
34 		.flags = _FLAGS,					\
35 		.nr_link_freqs = _NR,					\
36 		.link_freqs = { __VA_ARGS__ }				\
37 	}
38 
39 #define IPU_SENSOR_CONFIG(_HID, _NR, ...)				\
40 	IPU_SENSOR_CONFIG_MATCH_FL(_HID, NULL, 0, _NR, __VA_ARGS__)
41 
42 #define NODE_SENSOR(_HID, _PROPS)		\
43 	(const struct software_node) {		\
44 		.name = _HID,			\
45 		.properties = _PROPS,		\
46 	}
47 
48 #define NODE_PORT(_PORT, _SENSOR_NODE)		\
49 	(const struct software_node) {		\
50 		.name = _PORT,			\
51 		.parent = _SENSOR_NODE,		\
52 	}
53 
54 #define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
55 	(const struct software_node) {		\
56 		.name = _EP,			\
57 		.parent = _PORT,		\
58 		.properties = _PROPS,		\
59 	}
60 
61 #define NODE_VCM(_TYPE)				\
62 	(const struct software_node) {		\
63 		.name = _TYPE,			\
64 	}
65 
66 enum ipu_sensor_swnodes {
67 	SWNODE_SENSOR_HID,
68 	SWNODE_SENSOR_PORT,
69 	SWNODE_SENSOR_ENDPOINT,
70 	SWNODE_IPU_PORT,
71 	SWNODE_IPU_ENDPOINT,
72 	/* below are optional / maybe empty */
73 	SWNODE_IVSC_HID,
74 	SWNODE_IVSC_SENSOR_PORT,
75 	SWNODE_IVSC_SENSOR_ENDPOINT,
76 	SWNODE_IVSC_IPU_PORT,
77 	SWNODE_IVSC_IPU_ENDPOINT,
78 	SWNODE_VCM,
79 	SWNODE_COUNT
80 };
81 
82 enum ipu_bridge_ep_props {
83 	IPU_BRIDGE_EP_BUS_TYPE,
84 	IPU_BRIDGE_EP_DATA_LANES,
85 	IPU_BRIDGE_EP_REMOTE_EP,
86 	IPU_BRIDGE_EP_LINK_FREQUENCIES,
87 	IPU_BRIDGE_EP_CLOCK_NONCONTINUOUS,
88 	IPU_BRIDGE_EP_NUM_OF,
89 	IPU_BRIDGE_EP_NUM_ENTRIES
90 };
91 
92 /*
93  * Get the index of the next property in a property array, with a given maximum
94  * value.
95  */
96 #define IPU_BRIDGE_NEXT_PROPERTY(index, max)		\
97 	(WARN_ON((index) > IPU_BRIDGE_##max) ?		\
98 	 IPU_BRIDGE_##max : (index)++)
99 
100 /* Data representation as it is in ACPI SSDB buffer */
101 struct ipu_sensor_ssdb {
102 	u8 version;
103 	u8 sku;
104 	u8 guid_csi2[16];
105 	u8 devfunction;
106 	u8 bus;
107 	u32 dphylinkenfuses;
108 	u32 clockdiv;
109 	u8 link;
110 	u8 lanes;
111 	u32 csiparams[10];
112 	u32 maxlanespeed;
113 	u8 sensorcalibfileidx;
114 	u8 sensorcalibfileidxInMBZ[3];
115 	u8 romtype;
116 	u8 vcmtype;
117 	u8 platforminfo;
118 	u8 platformsubinfo;
119 	u8 flash;
120 	u8 privacyled;
121 	u8 degree;
122 	u8 mipilinkdefined;
123 	u32 mclkspeed;
124 	u8 controllogicid;
125 	u8 reserved1[3];
126 	u8 mclkport;
127 	u8 reserved2[13];
128 } __packed;
129 
130 struct ipu_property_names {
131 	char clock_frequency[16];
132 	char rotation[9];
133 	char orientation[12];
134 	char bus_type[9];
135 	char data_lanes[11];
136 	char remote_endpoint[16];
137 	char link_frequencies[17];
138 	char clock_noncontinuous[20];
139 };
140 
141 struct ipu_node_names {
142 	char port[7];
143 	char ivsc_sensor_port[7];
144 	char ivsc_ipu_port[7];
145 	char endpoint[11];
146 	char remote_port[9];
147 	char vcm[16];
148 };
149 
150 struct ipu_sensor_config {
151 	const char *hid;
152 	/* Zero-terminated list of IPU PCI product IDs, NULL for any IPU */
153 	const u16 *pci_ids;
154 	const u32 flags;
155 	const u8 nr_link_freqs;
156 	const u64 link_freqs[MAX_NUM_LINK_FREQS];
157 };
158 
159 struct ipu_sensor {
160 	/* append ssdb.link(u8) in "-%u" format as suffix of HID */
161 	char name[ACPI_ID_LEN + 4];
162 	struct acpi_device *adev;
163 
164 	struct device *csi_dev;
165 	struct acpi_device *ivsc_adev;
166 	char ivsc_name[ACPI_ID_LEN + 4];
167 
168 	/* SWNODE_COUNT + 1 for terminating NULL */
169 	const struct software_node *group[SWNODE_COUNT + 1];
170 	struct software_node swnodes[SWNODE_COUNT];
171 	struct ipu_node_names node_names;
172 
173 	u8 link;
174 	u8 lanes;
175 	u32 mclkspeed;
176 	u32 rotation;
177 	enum v4l2_fwnode_orientation orientation;
178 	const char *vcm_type;
179 
180 	struct ipu_property_names prop_names;
181 	struct property_entry ep_properties[IPU_BRIDGE_EP_NUM_ENTRIES];
182 	struct property_entry dev_properties[5];
183 	struct property_entry ipu_properties[3];
184 	struct property_entry ivsc_properties[1];
185 	struct property_entry ivsc_sensor_ep_properties[4];
186 	struct property_entry ivsc_ipu_ep_properties[4];
187 
188 	struct software_node_ref_args local_ref[1];
189 	struct software_node_ref_args remote_ref[1];
190 	struct software_node_ref_args vcm_ref[1];
191 	struct software_node_ref_args ivsc_sensor_ref[1];
192 	struct software_node_ref_args ivsc_ipu_ref[1];
193 };
194 
195 typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev,
196 					 struct ipu_sensor *sensor);
197 
198 struct ipu_bridge {
199 	struct device *dev;
200 	/* PCI product ID of the IPU, 0 if it is not a PCI device */
201 	u16 pci_id;
202 	ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
203 	char ipu_node_name[ACPI_ID_LEN];
204 	struct software_node ipu_hid_node;
205 	u32 data_lanes[4];
206 	unsigned int n_sensors;
207 	struct ipu_sensor sensors[IPU_MAX_PORTS];
208 };
209 
210 #if IS_ENABLED(CONFIG_IPU_BRIDGE)
211 struct pci_dev *ipu_bridge_get_ipu6(void);
212 int ipu_bridge_init(struct device *dev,
213 		    ipu_parse_sensor_fwnode_t parse_sensor_fwnode);
214 int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor);
215 int ipu_bridge_instantiate_vcm(struct device *sensor);
216 #else
217 static inline struct pci_dev *ipu_bridge_get_ipu6(void) { return NULL; }
218 /* Use a define to avoid the @parse_sensor_fwnode argument getting evaluated */
219 #define ipu_bridge_init(dev, parse_sensor_fwnode)	(0)
220 static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; }
221 #endif
222 
223 #endif
224