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 | |
50 | enum 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 */ |
67 | struct 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 | |
96 | struct 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 | |
106 | struct 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 | |
115 | struct ipu_sensor_config { |
116 | const char *hid; |
117 | const u8 nr_link_freqs; |
118 | const u64 link_freqs[MAX_NUM_LINK_FREQS]; |
119 | }; |
120 | |
121 | struct 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 | |
157 | typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev, |
158 | struct ipu_sensor *sensor); |
159 | |
160 | struct 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) |
171 | int ipu_bridge_init(struct device *dev, |
172 | ipu_parse_sensor_fwnode_t parse_sensor_fwnode); |
173 | int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor); |
174 | int 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) |
178 | static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; } |
179 | #endif |
180 | |
181 | #endif |
182 | |