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 /* Flags for struct ipu_sensor_config */ 21 /* The sensor's CSI-2 transmitter needs a non-continuous clock */ 22 #define IPU_BR_FL_CSI2_CLK_NONCONTINUOUS BIT(0) 23 24 /* 25 * Sensor config specific to one or more IPUs, identified by their PCI product 26 * IDs, with flags describing what the sensor needs there. Entries for one HID 27 * must be adjacent in ipu_supported_sensors[], with the IPU-specific ones 28 * before the generic one. 29 */ 30 #define IPU_SENSOR_CONFIG_MATCH_FL(_HID, _IDS, _FLAGS, _NR, ...) \ 31 (const struct ipu_sensor_config) { \ 32 .hid = _HID, \ 33 .pci_ids = _IDS, \ 34 .flags = _FLAGS, \ 35 .nr_link_freqs = _NR, \ 36 .link_freqs = { __VA_ARGS__ } \ 37 } 38 39 #define IPU_SENSOR_CONFIG(_HID, _NR, ...) \ 40 IPU_SENSOR_CONFIG_MATCH_FL(_HID, NULL, 0, _NR, __VA_ARGS__) 41 42 #define NODE_SENSOR(_HID, _PROPS) \ 43 (const struct software_node) { \ 44 .name = _HID, \ 45 .properties = _PROPS, \ 46 } 47 48 #define NODE_PORT(_PORT, _SENSOR_NODE) \ 49 (const struct software_node) { \ 50 .name = _PORT, \ 51 .parent = _SENSOR_NODE, \ 52 } 53 54 #define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ 55 (const struct software_node) { \ 56 .name = _EP, \ 57 .parent = _PORT, \ 58 .properties = _PROPS, \ 59 } 60 61 #define NODE_VCM(_TYPE) \ 62 (const struct software_node) { \ 63 .name = _TYPE, \ 64 } 65 66 enum ipu_sensor_swnodes { 67 SWNODE_SENSOR_HID, 68 SWNODE_SENSOR_PORT, 69 SWNODE_SENSOR_ENDPOINT, 70 SWNODE_IPU_PORT, 71 SWNODE_IPU_ENDPOINT, 72 /* below are optional / maybe empty */ 73 SWNODE_IVSC_HID, 74 SWNODE_IVSC_SENSOR_PORT, 75 SWNODE_IVSC_SENSOR_ENDPOINT, 76 SWNODE_IVSC_IPU_PORT, 77 SWNODE_IVSC_IPU_ENDPOINT, 78 SWNODE_VCM, 79 SWNODE_COUNT 80 }; 81 82 enum ipu_bridge_ep_props { 83 IPU_BRIDGE_EP_BUS_TYPE, 84 IPU_BRIDGE_EP_DATA_LANES, 85 IPU_BRIDGE_EP_REMOTE_EP, 86 IPU_BRIDGE_EP_LINK_FREQUENCIES, 87 IPU_BRIDGE_EP_CLOCK_NONCONTINUOUS, 88 IPU_BRIDGE_EP_NUM_OF, 89 IPU_BRIDGE_EP_NUM_ENTRIES 90 }; 91 92 /* 93 * Get the index of the next property in a property array, with a given maximum 94 * value. 95 */ 96 #define IPU_BRIDGE_NEXT_PROPERTY(index, max) \ 97 (WARN_ON((index) > IPU_BRIDGE_##max) ? \ 98 IPU_BRIDGE_##max : (index)++) 99 100 /* Data representation as it is in ACPI SSDB buffer */ 101 struct ipu_sensor_ssdb { 102 u8 version; 103 u8 sku; 104 u8 guid_csi2[16]; 105 u8 devfunction; 106 u8 bus; 107 u32 dphylinkenfuses; 108 u32 clockdiv; 109 u8 link; 110 u8 lanes; 111 u32 csiparams[10]; 112 u32 maxlanespeed; 113 u8 sensorcalibfileidx; 114 u8 sensorcalibfileidxInMBZ[3]; 115 u8 romtype; 116 u8 vcmtype; 117 u8 platforminfo; 118 u8 platformsubinfo; 119 u8 flash; 120 u8 privacyled; 121 u8 degree; 122 u8 mipilinkdefined; 123 u32 mclkspeed; 124 u8 controllogicid; 125 u8 reserved1[3]; 126 u8 mclkport; 127 u8 reserved2[13]; 128 } __packed; 129 130 struct ipu_property_names { 131 char clock_frequency[16]; 132 char rotation[9]; 133 char orientation[12]; 134 char bus_type[9]; 135 char data_lanes[11]; 136 char remote_endpoint[16]; 137 char link_frequencies[17]; 138 char clock_noncontinuous[20]; 139 }; 140 141 struct ipu_node_names { 142 char port[7]; 143 char ivsc_sensor_port[7]; 144 char ivsc_ipu_port[7]; 145 char endpoint[11]; 146 char remote_port[9]; 147 char vcm[16]; 148 }; 149 150 struct ipu_sensor_config { 151 const char *hid; 152 /* Zero-terminated list of IPU PCI product IDs, NULL for any IPU */ 153 const u16 *pci_ids; 154 const u32 flags; 155 const u8 nr_link_freqs; 156 const u64 link_freqs[MAX_NUM_LINK_FREQS]; 157 }; 158 159 struct ipu_sensor { 160 /* append ssdb.link(u8) in "-%u" format as suffix of HID */ 161 char name[ACPI_ID_LEN + 4]; 162 struct acpi_device *adev; 163 164 struct device *csi_dev; 165 struct acpi_device *ivsc_adev; 166 char ivsc_name[ACPI_ID_LEN + 4]; 167 168 /* SWNODE_COUNT + 1 for terminating NULL */ 169 const struct software_node *group[SWNODE_COUNT + 1]; 170 struct software_node swnodes[SWNODE_COUNT]; 171 struct ipu_node_names node_names; 172 173 u8 link; 174 u8 lanes; 175 u32 mclkspeed; 176 u32 rotation; 177 enum v4l2_fwnode_orientation orientation; 178 const char *vcm_type; 179 180 struct ipu_property_names prop_names; 181 struct property_entry ep_properties[IPU_BRIDGE_EP_NUM_ENTRIES]; 182 struct property_entry dev_properties[5]; 183 struct property_entry ipu_properties[3]; 184 struct property_entry ivsc_properties[1]; 185 struct property_entry ivsc_sensor_ep_properties[4]; 186 struct property_entry ivsc_ipu_ep_properties[4]; 187 188 struct software_node_ref_args local_ref[1]; 189 struct software_node_ref_args remote_ref[1]; 190 struct software_node_ref_args vcm_ref[1]; 191 struct software_node_ref_args ivsc_sensor_ref[1]; 192 struct software_node_ref_args ivsc_ipu_ref[1]; 193 }; 194 195 typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev, 196 struct ipu_sensor *sensor); 197 198 struct ipu_bridge { 199 struct device *dev; 200 /* PCI product ID of the IPU, 0 if it is not a PCI device */ 201 u16 pci_id; 202 ipu_parse_sensor_fwnode_t parse_sensor_fwnode; 203 char ipu_node_name[ACPI_ID_LEN]; 204 struct software_node ipu_hid_node; 205 u32 data_lanes[4]; 206 unsigned int n_sensors; 207 struct ipu_sensor sensors[IPU_MAX_PORTS]; 208 }; 209 210 #if IS_ENABLED(CONFIG_IPU_BRIDGE) 211 struct pci_dev *ipu_bridge_get_ipu6(void); 212 int ipu_bridge_init(struct device *dev, 213 ipu_parse_sensor_fwnode_t parse_sensor_fwnode); 214 int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor); 215 int ipu_bridge_instantiate_vcm(struct device *sensor); 216 #else 217 static inline struct pci_dev *ipu_bridge_get_ipu6(void) { return NULL; } 218 /* Use a define to avoid the @parse_sensor_fwnode argument getting evaluated */ 219 #define ipu_bridge_init(dev, parse_sensor_fwnode) (0) 220 static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; } 221 #endif 222 223 #endif 224