Lines Matching +full:dsd +full:- +full:path

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) in parse_csi2_resource()
75 csi2_res = &res->data.csi2_serial_bus; in parse_csi2_resource()
77 if (csi2_res->type != ACPI_RESOURCE_SERIAL_TYPE_CSI2) in parse_csi2_resource()
80 csi2_res_src = &csi2_res->resource_source; in parse_csi2_resource()
81 if (ACPI_FAILURE(acpi_get_handle(NULL, csi2_res_src->string_ptr, in parse_csi2_resource()
83 acpi_handle_debug(crwd->handle, in parse_csi2_resource()
87 csi2_res_src_length = csi2_res_src->string_length; in parse_csi2_resource()
89 acpi_handle_debug(crwd->handle, in parse_csi2_resource()
99 conn->csi2_data = *csi2_res; in parse_csi2_resource()
100 strscpy(conn->remote_name, csi2_res_src->string_ptr, csi2_res_src_length); in parse_csi2_resource()
101 conn->csi2_data.resource_source.string_ptr = conn->remote_name; in parse_csi2_resource()
102 conn->remote_handle = remote_handle; in parse_csi2_resource()
104 list_add(&conn->entry, &crwd->connections); in parse_csi2_resource()
118 csi2->handle = handle; in acpi_mipi_add_crs_csi2()
119 INIT_LIST_HEAD(&csi2->connections); in acpi_mipi_add_crs_csi2()
120 csi2->port_count = 1; in acpi_mipi_add_crs_csi2()
127 list_add(&csi2->entry, list); in acpi_mipi_add_crs_csi2()
148 list_del(&conn->entry); in csi_csr2_release_connections()
155 list_del(&csi2->entry); in acpi_mipi_del_crs_csi2()
156 acpi_detach_data(csi2->handle, acpi_mipi_data_tag); in acpi_mipi_del_crs_csi2()
157 kfree(csi2->swnodes); in acpi_mipi_del_crs_csi2()
158 csi_csr2_release_connections(&csi2->connections); in acpi_mipi_del_crs_csi2()
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 in acpi_mipi_check_crs_csi2()
186 * Create a _CRS CSI-2 entry to store the extracted connection in acpi_mipi_check_crs_csi2()
195 list_replace(&crwd.connections, &csi2->connections); in acpi_mipi_check_crs_csi2()
198 #define NO_CSI2_PORT (UINT_MAX - 1)
202 size_t port_count = csi2->port_count; in alloc_crs_csi2_swnodes()
212 if (check_mul_overflow(sizeof(*swnodes->ports) + in alloc_crs_csi2_swnodes()
213 sizeof(*swnodes->nodes) * 2 + in alloc_crs_csi2_swnodes()
214 sizeof(*swnodes->nodeptrs) * 2, in alloc_crs_csi2_swnodes()
217 sizeof(*swnodes->nodes) + in alloc_crs_csi2_swnodes()
218 sizeof(*swnodes->nodeptrs) * 2, in alloc_crs_csi2_swnodes()
220 acpi_handle_info(csi2->handle, in alloc_crs_csi2_swnodes()
221 "too many _CRS CSI-2 resource handles (%zu)", in alloc_crs_csi2_swnodes()
230 swnodes->ports = (struct acpi_device_software_node_port *)(swnodes + 1); in alloc_crs_csi2_swnodes()
231 swnodes->nodes = (struct software_node *)(swnodes->ports + port_count); in alloc_crs_csi2_swnodes()
232 swnodes->nodeptrs = (const struct software_node **)(swnodes->nodes + 1 + in alloc_crs_csi2_swnodes()
234 swnodes->num_ports = port_count; in alloc_crs_csi2_swnodes()
237 swnodes->nodeptrs[i] = &swnodes->nodes[i]; in alloc_crs_csi2_swnodes()
239 swnodes->nodeptrs[i] = NULL; in alloc_crs_csi2_swnodes()
242 swnodes->ports[i].port_nr = NO_CSI2_PORT; in alloc_crs_csi2_swnodes()
244 csi2->swnodes = swnodes; in alloc_crs_csi2_swnodes()
255 for (i = 0; i < swnodes->num_ports; i++) { in next_csi2_port_index()
256 struct acpi_device_software_node_port *port = &swnodes->ports[i]; in next_csi2_port_index()
258 if (port->port_nr == port_nr) in next_csi2_port_index()
261 if (port->port_nr == NO_CSI2_PORT) { in next_csi2_port_index()
262 port->port_nr = port_nr; in next_csi2_port_index()
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); in extract_crs_csi2_conn_info()
287 * If the previous steps have failed to make room for a _CRS CSI-2 in extract_crs_csi2_conn_info()
293 remote_swnodes = remote_csi2->swnodes; in extract_crs_csi2_conn_info()
297 switch (conn->csi2_data.phy_type) { in extract_crs_csi2_conn_info()
307 acpi_handle_info(local_handle, "unknown CSI-2 PHY type %u\n", in extract_crs_csi2_conn_info()
308 conn->csi2_data.phy_type); in extract_crs_csi2_conn_info()
313 conn->csi2_data.local_port_instance); in extract_crs_csi2_conn_info()
314 if (WARN_ON_ONCE(local_index >= local_swnodes->num_ports)) in extract_crs_csi2_conn_info()
318 conn->csi2_data.resource_source.index); in extract_crs_csi2_conn_info()
319 if (WARN_ON_ONCE(remote_index >= remote_swnodes->num_ports)) in extract_crs_csi2_conn_info()
322 local_port = &local_swnodes->ports[local_index]; in extract_crs_csi2_conn_info()
323 local_node = &local_swnodes->nodes[ACPI_DEVICE_SWNODE_EP(local_index)]; in extract_crs_csi2_conn_info()
324 local_port->crs_csi2_local = true; in extract_crs_csi2_conn_info()
326 remote_port = &remote_swnodes->ports[remote_index]; in extract_crs_csi2_conn_info()
327 remote_node = &remote_swnodes->nodes[ACPI_DEVICE_SWNODE_EP(remote_index)]; in extract_crs_csi2_conn_info()
329 local_port->remote_ep[0] = SOFTWARE_NODE_REFERENCE(remote_node); in extract_crs_csi2_conn_info()
330 remote_port->remote_ep[0] = SOFTWARE_NODE_REFERENCE(local_node); in extract_crs_csi2_conn_info()
332 local_port->ep_props[ACPI_DEVICE_SWNODE_EP_REMOTE_EP] = in extract_crs_csi2_conn_info()
333 PROPERTY_ENTRY_REF_ARRAY("remote-endpoint", in extract_crs_csi2_conn_info()
334 local_port->remote_ep); in extract_crs_csi2_conn_info()
336 local_port->ep_props[ACPI_DEVICE_SWNODE_EP_BUS_TYPE] = in extract_crs_csi2_conn_info()
337 PROPERTY_ENTRY_U32("bus-type", bus_type); in extract_crs_csi2_conn_info()
339 local_port->ep_props[ACPI_DEVICE_SWNODE_EP_REG] = in extract_crs_csi2_conn_info()
342 local_port->port_props[ACPI_DEVICE_SWNODE_PORT_REG] = in extract_crs_csi2_conn_info()
343 PROPERTY_ENTRY_U32("reg", conn->csi2_data.local_port_instance); in extract_crs_csi2_conn_info()
345 if (GRAPH_PORT_NAME(local_port->port_name, in extract_crs_csi2_conn_info()
346 conn->csi2_data.local_port_instance)) in extract_crs_csi2_conn_info()
348 conn->csi2_data.local_port_instance); in extract_crs_csi2_conn_info()
350 remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_REMOTE_EP] = in extract_crs_csi2_conn_info()
351 PROPERTY_ENTRY_REF_ARRAY("remote-endpoint", in extract_crs_csi2_conn_info()
352 remote_port->remote_ep); in extract_crs_csi2_conn_info()
354 remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_BUS_TYPE] = in extract_crs_csi2_conn_info()
355 PROPERTY_ENTRY_U32("bus-type", bus_type); in extract_crs_csi2_conn_info()
357 remote_port->ep_props[ACPI_DEVICE_SWNODE_EP_REG] = in extract_crs_csi2_conn_info()
360 remote_port->port_props[ACPI_DEVICE_SWNODE_PORT_REG] = in extract_crs_csi2_conn_info()
361 PROPERTY_ENTRY_U32("reg", conn->csi2_data.resource_source.index); in extract_crs_csi2_conn_info()
363 if (GRAPH_PORT_NAME(remote_port->port_name, in extract_crs_csi2_conn_info()
364 conn->csi2_data.resource_source.index)) in extract_crs_csi2_conn_info()
366 conn->csi2_data.resource_source.index); in extract_crs_csi2_conn_info()
371 struct acpi_device_software_nodes *local_swnodes = csi2->swnodes; in prepare_crs_csi2_swnodes()
372 acpi_handle local_handle = csi2->handle; in prepare_crs_csi2_swnodes()
379 list_for_each_entry(conn, &csi2->connections, entry) in prepare_crs_csi2_swnodes()
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. */ in acpi_mipi_scan_crs_csi2()
402 list_for_each_entry(conn, &csi2->connections, entry) { in acpi_mipi_scan_crs_csi2()
405 csi2->port_count++; in acpi_mipi_scan_crs_csi2()
407 remote_csi2 = acpi_mipi_get_crs_csi2(conn->remote_handle); in acpi_mipi_scan_crs_csi2()
409 remote_csi2->port_count++; in acpi_mipi_scan_crs_csi2()
413 * The remote endpoint has no _CRS CSI-2 list entry yet, in acpi_mipi_scan_crs_csi2()
416 acpi_mipi_add_crs_csi2(conn->remote_handle, &aux_list); in acpi_mipi_scan_crs_csi2()
422 * Allocate software nodes for representing the CSI-2 information. in acpi_mipi_scan_crs_csi2()
432 * Set up software node properties using data from _CRS CSI-2 resource in acpi_mipi_scan_crs_csi2()
456 ret = fwnode_property_count_u64(port_fwnode, "mipi-img-link-frequencies"); in init_csi2_port_local()
468 "mipi-img-link-frequencies", in init_csi2_port_local()
469 port->link_frequencies, in init_csi2_port_local()
477 port->ep_props[NEXT_PROPERTY(index, EP_LINK_FREQUENCIES)] = in init_csi2_port_local()
478 PROPERTY_ENTRY_U64_ARRAY_LEN("link-frequencies", in init_csi2_port_local()
479 port->link_frequencies, in init_csi2_port_local()
495 if (GRAPH_PORT_NAME(port->port_name, port->port_nr)) in init_csi2_port()
498 swnodes->nodes[ACPI_DEVICE_SWNODE_PORT(port_index)] = in init_csi2_port()
499 SOFTWARE_NODE(port->port_name, port->port_props, in init_csi2_port()
500 &swnodes->nodes[ACPI_DEVICE_SWNODE_ROOT]); in init_csi2_port()
502 ret = fwnode_property_read_u8(port_fwnode, "mipi-img-clock-lane", val); in init_csi2_port()
504 port->ep_props[NEXT_PROPERTY(ep_prop_index, EP_CLOCK_LANES)] = in init_csi2_port()
505 PROPERTY_ENTRY_U32("clock-lanes", val[0]); in init_csi2_port()
507 ret = fwnode_property_count_u8(port_fwnode, "mipi-img-data-lanes"); in init_csi2_port()
518 "mipi-img-data-lanes", in init_csi2_port()
524 port->data_lanes[i] = val[i]; in init_csi2_port()
526 port->ep_props[NEXT_PROPERTY(ep_prop_index, EP_DATA_LANES)] = in init_csi2_port()
527 PROPERTY_ENTRY_U32_ARRAY_LEN("data-lanes", in init_csi2_port()
528 port->data_lanes, in init_csi2_port()
533 ret = fwnode_property_count_u8(port_fwnode, "mipi-img-lane-polarities"); in init_csi2_port()
557 fwnode_property_read_u8_array(port_fwnode, "mipi-img-lane-polarities", in init_csi2_port()
564 port->lane_polarities[i] = test_bit(i, &mask); in init_csi2_port()
566 port->ep_props[NEXT_PROPERTY(ep_prop_index, EP_LANE_POLARITIES)] = in init_csi2_port()
567 PROPERTY_ENTRY_U32_ARRAY_LEN("lane-polarities", in init_csi2_port()
568 port->lane_polarities, in init_csi2_port()
572 swnodes->nodes[ACPI_DEVICE_SWNODE_EP(port_index)] = in init_csi2_port()
573 SOFTWARE_NODE("endpoint@0", swnodes->ports[port_index].ep_props, in init_csi2_port()
574 &swnodes->nodes[ACPI_DEVICE_SWNODE_PORT(port_index)]); in init_csi2_port()
576 if (port->crs_csi2_local) in init_csi2_port()
580 #define MIPI_IMG_PORT_PREFIX "mipi-img-port-"
597 struct acpi_device_software_nodes *swnodes = csi2->swnodes; in init_crs_csi2_swnodes()
598 acpi_handle handle = csi2->handle; in init_crs_csi2_swnodes()
629 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_ROTATION)] = in init_crs_csi2_swnodes()
631 pld->rotation * 45U); in init_crs_csi2_swnodes()
636 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-clock-frequency", &val)) in init_crs_csi2_swnodes()
637 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_CLOCK_FREQUENCY)] = in init_crs_csi2_swnodes()
638 PROPERTY_ENTRY_U32("clock-frequency", val); in init_crs_csi2_swnodes()
640 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-led-max-current", &val)) in init_crs_csi2_swnodes()
641 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_LED_MAX_MICROAMP)] = in init_crs_csi2_swnodes()
642 PROPERTY_ENTRY_U32("led-max-microamp", val); in init_crs_csi2_swnodes()
644 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-flash-max-current", &val)) in init_crs_csi2_swnodes()
645 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_FLASH_MAX_MICROAMP)] = in init_crs_csi2_swnodes()
646 PROPERTY_ENTRY_U32("flash-max-microamp", val); in init_crs_csi2_swnodes()
648 if (!fwnode_property_read_u32(adev_fwnode, "mipi-img-flash-max-timeout-us", &val)) in init_crs_csi2_swnodes()
649 swnodes->dev_props[NEXT_PROPERTY(prop_index, DEV_FLASH_MAX_TIMEOUT_US)] = in init_crs_csi2_swnodes()
650 PROPERTY_ENTRY_U32("flash-max-timeout-us", val); in init_crs_csi2_swnodes()
654 acpi_handle_info(handle, "Unable to get the path name\n"); in init_crs_csi2_swnodes()
658 swnodes->nodes[ACPI_DEVICE_SWNODE_ROOT] = in init_crs_csi2_swnodes()
659 SOFTWARE_NODE(buffer.pointer, swnodes->dev_props, NULL); in init_crs_csi2_swnodes()
661 for (i = 0; i < swnodes->num_ports; i++) { in init_crs_csi2_swnodes()
662 struct acpi_device_software_node_port *port = &swnodes->ports[i]; in init_crs_csi2_swnodes()
667 * properties for providing CSI-2 port parameters that can be in init_crs_csi2_swnodes()
672 port_fwnode = get_mipi_port_handle(adev_fwnode, port->port_nr); in init_crs_csi2_swnodes()
676 port->port_nr); in init_crs_csi2_swnodes()
685 ret = software_node_register_node_group(swnodes->nodeptrs); in init_crs_csi2_swnodes()
692 adev->swnodes = swnodes; in init_crs_csi2_swnodes()
693 adev_fwnode->secondary = software_node_fwnode(swnodes->nodes); in init_crs_csi2_swnodes()
699 csi2->swnodes = NULL; in init_crs_csi2_swnodes()
703 * acpi_mipi_init_crs_csi2_swnodes - Initialize _CRS CSI-2 software nodes
706 * of CSI-2 software nodes for all ACPI device objects that have been already
718 * acpi_mipi_crs_csi2_cleanup - Free _CRS CSI-2 temporary data
730 #include <asm/intel-family.h>
755 * acpi_graph_ignore_port - Tell whether a port node should be ignored
760 * ipu-bridge). This is currently used to ignore bad port nodes related to IPU6
766 const char *path = NULL, *orig_path; in acpi_graph_ignore_port() local
784 path = strnext(orig_path, "IPU"); in acpi_graph_ignore_port()
785 if (!path) in acpi_graph_ignore_port()
786 path = strnext(orig_path, "LNK"); in acpi_graph_ignore_port()
787 if (!path) in acpi_graph_ignore_port()
790 if (!(isdigit(path[0]) && path[1] == '.')) in acpi_graph_ignore_port()
794 path = strnext(path, "PRT"); in acpi_graph_ignore_port()
795 if (path && isdigit(path[0]) && !path[1]) { in acpi_graph_ignore_port()