Lines Matching +full:csi +full:- +full:bridge
1 // SPDX-License-Identifier: GPL-2.0-only
7 * Support MIPI DisCo for Imaging by parsing ACPI _CRS CSI-2 records defined in
8 * Section 6.4.3.8.2.4 "Camera Serial Interface (CSI-2) Connection Resource
12 * The implementation looks for the information in the ACPI namespace (CSI-2
14 * Documentation/firmware-guide/acpi/dsd/graph.rst to represent the CSI-2
16 * extracted from the _CRS CSI-2 resource descriptors and the MIPI DisCo
18 * with CSI-2 connections.
31 #include <media/v4l2-fwnode.h>
41 /* Connection data extracted from one _CRS CSI-2 resource descriptor. */
49 /* Data extracted from _CRS CSI-2 resource descriptors for one device. */
72 if (res->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
75 csi2_res = &res->data.csi2_serial_bus;
77 if (csi2_res->type != ACPI_RESOURCE_SERIAL_TYPE_CSI2)
80 csi2_res_src = &csi2_res->resource_source;
81 if (ACPI_FAILURE(acpi_get_handle(NULL, csi2_res_src->string_ptr,
83 acpi_handle_debug(crwd->handle,
87 csi2_res_src_length = csi2_res_src->string_length;
89 acpi_handle_debug(crwd->handle,
99 conn->csi2_data = *csi2_res;
100 strscpy(conn->remote_name, csi2_res_src->string_ptr, csi2_res_src_length);
101 conn->csi2_data.resource_source.string_ptr = conn->remote_name;
102 conn->remote_handle = remote_handle;
104 list_add(&conn->entry, &crwd->connections);
118 csi2->handle = handle;
119 INIT_LIST_HEAD(&csi2->connections);
120 csi2->port_count = 1;
127 list_add(&csi2->entry, list);
148 list_del(&conn->entry);
155 list_del(&csi2->entry);
156 acpi_detach_data(csi2->handle, acpi_mipi_data_tag);
157 kfree(csi2->swnodes);
158 csi_csr2_release_connections(&csi2->connections);
163 * acpi_mipi_check_crs_csi2 - Look for CSI-2 resources in _CRS
166 * Find all CSI-2 resource descriptors in the given device's _CRS
178 * Avoid allocating _CRS CSI-2 objects for devices without any CSI-2
186 * Create a _CRS CSI-2 entry to store the extracted connection
195 list_replace(&crwd.connections, &csi2->connections);
198 #define NO_CSI2_PORT (UINT_MAX - 1)
202 size_t port_count = csi2->port_count;
212 if (check_mul_overflow(sizeof(*swnodes->ports) +
213 sizeof(*swnodes->nodes) * 2 +
214 sizeof(*swnodes->nodeptrs) * 2,
217 sizeof(*swnodes->nodes) +
218 sizeof(*swnodes->nodeptrs) * 2,
220 acpi_handle_info(csi2->handle,
221 "too many _CRS CSI-2 resource handles (%zu)",
230 swnodes->ports = (struct acpi_device_software_node_port *)(swnodes + 1);
231 swnodes->nodes = (struct software_node *)(swnodes->ports + port_count);
232 swnodes->nodeptrs = (const struct software_node **)(swnodes->nodes + 1 +
234 swnodes->num_ports = port_count;
237 swnodes->nodeptrs[i] = &swnodes->nodes[i];
239 swnodes->nodeptrs[i] = NULL;
242 swnodes->ports[i].port_nr = NO_CSI2_PORT;
244 csi2->swnodes = swnodes;
255 for (i = 0; i < swnodes->num_ports; i++) {
256 struct acpi_device_software_node_port *port = &swnodes->ports[i];
258 if (port->port_nr == port_nr)
261 if (port->port_nr == NO_CSI2_PORT) {
262 port->port_nr = port_nr;
270 /* Print graph port name into a buffer, return non-zero on failure. */
279 struct crs_csi2 *remote_csi2 = acpi_mipi_get_crs_csi2(conn->remote_handle);
287 * If the previous steps have failed to make room for a _CRS CSI-2
293 remote_swnodes = remote_csi2->swnodes;
297 switch (conn->csi2_data.phy_type) {
307 acpi_handle_info(local_handle, "unknown CSI-2 PHY type %u\n",
308 conn->csi2_data.phy_type);
313 conn->csi2_data.local_port_instance);
314 if (WARN_ON_ONCE(local_index >= local_swnodes->num_ports))
318 conn->csi2_data.resource_source.index);
319 if (WARN_ON_ONCE(remote_index >= remote_swnodes->num_ports))
322 local_port = &local_swnodes->ports[local_index];
323 local_node = &local_swnodes->nodes[ACPI_DEVICE_SWNODE_EP(local_index)];
324 local_port->crs_csi2_local = true;
326 remote_port = &remote_swnodes->ports[remote_index];
327 remote_node = &remote_swnodes->nodes[ACPI_DEVICE_SWNODE_EP(remote_index)];
329 local_port->remote_ep[0] = SOFTWARE_NODE_REFERENCE(remote_node);
330 remote_port->remote_ep[0] = SOFTWARE_NODE_REFERENCE(local_node);
332 local_port->ep_props[ACPI_DEVICE_SWNODE_EP_REMOTE_EP] =
333 PROPERTY_ENTRY_REF_ARRAY("remote-endpoint",
334 local_port->remote_ep);
336 local_port->ep_props[ACPI_DEVICE_SWNODE_EP_BUS_TYPE] =
337 PROPERTY_ENTRY_U32("bus-type", bus_type);
339 local_port->ep_props[ACPI_DEVICE_SWNODE_EP_REG] =
342 local_port->port_props[ACPI_DEVICE_SWNODE_PORT_REG] =
343 PROPERTY_ENTRY_U32("reg", conn->csi2_data.local_port_instance);
345 if (GRAPH_PORT_NAME(local_port->port_name,
346 conn->csi2_data.local_port_instance))
348 conn->csi2_data.local_port_instance);
350 remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_REMOTE_EP] =
351 PROPERTY_ENTRY_REF_ARRAY("remote-endpoint",
352 remote_port->remote_ep);
354 remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_BUS_TYPE] =
355 PROPERTY_ENTRY_U32("bus-type", bus_type);
357 remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_REG] =
360 remote_port->port_props[ACPI_DEVICE_SWNODE_PORT_REG] =
361 PROPERTY_ENTRY_U32("reg", conn->csi2_data.resource_source.index);
363 if (GRAPH_PORT_NAME(remote_port->port_name,
364 conn->csi2_data.resource_source.index))
366 conn->csi2_data.resource_source.index);
371 struct acpi_device_software_nodes *local_swnodes = csi2->swnodes;
372 acpi_handle local_handle = csi2->handle;
379 list_for_each_entry(conn, &csi2->connections, entry)
384 * acpi_mipi_scan_crs_csi2 - Create ACPI _CRS CSI-2 software nodes
398 /* Count references to each ACPI handle in the CSI-2 connection graph. */
402 list_for_each_entry(conn, &csi2->connections, entry) {
405 csi2->port_count++;
407 remote_csi2 = acpi_mipi_get_crs_csi2(conn->remote_handle);
409 remote_csi2->port_count++;
413 * The remote endpoint has no _CRS CSI-2 list entry yet,
416 acpi_mipi_add_crs_csi2(conn->remote_handle, &aux_list);
422 * Allocate software nodes for representing the CSI-2 information.
432 * Set up software node properties using data from _CRS CSI-2 resource
456 ret = fwnode_property_count_u64(port_fwnode, "mipi-img-link-frequencies");
468 "mipi-img-link-frequencies",
469 port->link_frequencies,
477 port->ep_props[NEXT_PROPERTY(index, EP_LINK_FREQUENCIES)] =
478 PROPERTY_ENTRY_U64_ARRAY_LEN("link-frequencies",
479 port->link_frequencies,
495 if (GRAPH_PORT_NAME(port->port_name, port->port_nr))
498 swnodes->nodes[ACPI_DEVICE_SWNODE_PORT(port_index)] =
499 SOFTWARE_NODE(port->port_name, port->port_props,
500 &swnodes->nodes[ACPI_DEVICE_SWNODE_ROOT]);
502 ret = fwnode_property_read_u8(port_fwnode, "mipi-img-clock-lane", val);
504 port->ep_props[NEXT_PROPERTY(ep_prop_index, EP_CLOCK_LANES)] =
505 PROPERTY_ENTRY_U32("clock-lanes", val[0]);
507 ret = fwnode_property_count_u8(port_fwnode, "mipi-img-data-lanes");
518 "mipi-img-data-lanes",
524 port->data_lanes[i] = val[i];
526 port->ep_props[NEXT_PROPERTY(ep_prop_index, EP_DATA_LANES)] =
527 PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes",
528 port->data_lanes,
533 ret = fwnode_property_count_u8(port_fwnode, "mipi-img-lane-polarities");
557 fwnode_property_read_u8_array(port_fwnode, "mipi-img-lane-polarities",
564 port->lane_polarities[i] = test_bit(i, &mask);
566 port->ep_props[NEXT_PROPERTY(ep_prop_index, EP_LANE_POLARITIES)] =
567 PROPERTY_ENTRY_U32_ARRAY_LEN("lane-polarities",
568 port->lane_polarities,
572 swnodes->nodes[ACPI_DEVICE_SWNODE_EP(port_index)] =
573 SOFTWARE_NODE("endpoint@0", swnodes->ports[port_index].ep_props,
574 &swnodes->nodes[ACPI_DEVICE_SWNODE_PORT(port_index)]);
576 if (port->crs_csi2_local)
580 #define MIPI_IMG_PORT_PREFIX "mipi-img-port-"
597 struct acpi_device_software_nodes *swnodes = csi2->swnodes;
598 acpi_handle handle = csi2->handle;
628 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_ROTATION)] =
630 pld->rotation * 45U);
635 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-clock-frequency", &val))
636 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_CLOCK_FREQUENCY)] =
637 PROPERTY_ENTRY_U32("clock-frequency", val);
639 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-led-max-current", &val))
640 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_LED_MAX_MICROAMP)] =
641 PROPERTY_ENTRY_U32("led-max-microamp", val);
643 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-flash-max-current", &val))
644 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_FLASH_MAX_MICROAMP)] =
645 PROPERTY_ENTRY_U32("flash-max-microamp", val);
647 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-flash-max-timeout-us", &val))
648 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_FLASH_MAX_TIMEOUT_US)] =
649 PROPERTY_ENTRY_U32("flash-max-timeout-us", val);
657 swnodes->nodes[ACPI_DEVICE_SWNODE_ROOT] =
658 SOFTWARE_NODE(buffer.pointer, swnodes->dev_props, NULL);
660 for (i = 0; i < swnodes->num_ports; i++) {
661 struct acpi_device_software_node_port *port = &swnodes->ports[i];
666 * properties for providing CSI-2 port parameters that can be
671 port_fwnode = get_mipi_port_handle(adev_fwnode, port->port_nr);
675 port->port_nr);
684 ret = software_node_register_node_group(swnodes->nodeptrs);
691 adev->swnodes = swnodes;
692 adev_fwnode->secondary = software_node_fwnode(swnodes->nodes);
698 csi2->swnodes = NULL;
702 * acpi_mipi_init_crs_csi2_swnodes - Initialize _CRS CSI-2 software nodes
705 * of CSI-2 software nodes for all ACPI device objects that have been already
717 * acpi_mipi_crs_csi2_cleanup - Free _CRS CSI-2 temporary data
729 #include <asm/intel-family.h>
754 * acpi_graph_ignore_port - Tell whether a port node should be ignored
759 * ipu-bridge). This is currently used to ignore bad port nodes related to IPU6