ceda2a801948129c7778709344926ac340be0292
[platform/kernel/linux-rpi.git] / include / media / ipu-bridge.h
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         /* Must be last because it is optional / maybe empty */
57         SWNODE_VCM,
58         SWNODE_COUNT
59 };
60
61 /* Data representation as it is in ACPI SSDB buffer */
62 struct ipu_sensor_ssdb {
63         u8 version;
64         u8 sku;
65         u8 guid_csi2[16];
66         u8 devfunction;
67         u8 bus;
68         u32 dphylinkenfuses;
69         u32 clockdiv;
70         u8 link;
71         u8 lanes;
72         u32 csiparams[10];
73         u32 maxlanespeed;
74         u8 sensorcalibfileidx;
75         u8 sensorcalibfileidxInMBZ[3];
76         u8 romtype;
77         u8 vcmtype;
78         u8 platforminfo;
79         u8 platformsubinfo;
80         u8 flash;
81         u8 privacyled;
82         u8 degree;
83         u8 mipilinkdefined;
84         u32 mclkspeed;
85         u8 controllogicid;
86         u8 reserved1[3];
87         u8 mclkport;
88         u8 reserved2[13];
89 } __packed;
90
91 struct ipu_property_names {
92         char clock_frequency[16];
93         char rotation[9];
94         char orientation[12];
95         char bus_type[9];
96         char data_lanes[11];
97         char remote_endpoint[16];
98         char link_frequencies[17];
99 };
100
101 struct ipu_node_names {
102         char port[7];
103         char endpoint[11];
104         char remote_port[7];
105         char vcm[16];
106 };
107
108 struct ipu_sensor_config {
109         const char *hid;
110         const u8 nr_link_freqs;
111         const u64 link_freqs[MAX_NUM_LINK_FREQS];
112 };
113
114 struct ipu_sensor {
115         /* append ssdb.link(u8) in "-%u" format as suffix of HID */
116         char name[ACPI_ID_LEN + 4];
117         struct acpi_device *adev;
118
119         /* SWNODE_COUNT + 1 for terminating NULL */
120         const struct software_node *group[SWNODE_COUNT + 1];
121         struct software_node swnodes[SWNODE_COUNT];
122         struct ipu_node_names node_names;
123
124         u8 link;
125         u8 lanes;
126         u32 mclkspeed;
127         u32 rotation;
128         enum v4l2_fwnode_orientation orientation;
129         const char *vcm_type;
130
131         struct ipu_property_names prop_names;
132         struct property_entry ep_properties[5];
133         struct property_entry dev_properties[5];
134         struct property_entry ipu_properties[3];
135         struct software_node_ref_args local_ref[1];
136         struct software_node_ref_args remote_ref[1];
137         struct software_node_ref_args vcm_ref[1];
138 };
139
140 typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev,
141                                          struct ipu_sensor *sensor);
142
143 struct ipu_bridge {
144         struct device *dev;
145         ipu_parse_sensor_fwnode_t parse_sensor_fwnode;
146         char ipu_node_name[ACPI_ID_LEN];
147         struct software_node ipu_hid_node;
148         u32 data_lanes[4];
149         unsigned int n_sensors;
150         struct ipu_sensor sensors[IPU_MAX_PORTS];
151 };
152
153 #if IS_ENABLED(CONFIG_IPU_BRIDGE)
154 int ipu_bridge_init(struct device *dev,
155                     ipu_parse_sensor_fwnode_t parse_sensor_fwnode);
156 int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor);
157 int ipu_bridge_instantiate_vcm(struct device *sensor);
158 #else
159 /* Use a define to avoid the @parse_sensor_fwnode argument getting evaluated */
160 #define ipu_bridge_init(dev, parse_sensor_fwnode)       (0)
161 static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; }
162 #endif
163
164 #endif