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