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[7];
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