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)
ipu_bridge_instantiate_vcm(struct device * s)178 static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; }
179 #endif
180
181 #endif
182