Lines Matching +full:csi +full:- +full:bridge

1 // SPDX-License-Identifier: GPL-2.0
15 #include <media/ipu-bridge.h>
16 #include <media/v4l2-fwnode.h>
18 #define ADEV_DEV(adev) ACPI_PTR(&((adev)->dev))
21 * 92335fcf-3203-4472-af93-7b4453ac29da
23 * Used to build MEI CSI device name to lookup MEI CSI device by
39 * plus the number of link-frequencies expected by their drivers, along with
66 /* Hynix Hi-556 */
89 .clock_frequency = "clock-frequency",
92 .bus_type = "bus-type",
93 .data_lanes = "data-lanes",
94 .remote_endpoint = "remote-endpoint",
95 .link_frequencies = "link-frequencies",
131 for_each_acpi_dev_match(ivsc_adev, acpi_id->id, NULL, -1) in ipu_bridge_get_ivsc_acpi_dev()
134 if (consumer->handle == handle) { in ipu_bridge_get_ivsc_acpi_dev()
170 snprintf(name, sizeof(name), "%s-%pUl", dev_name(dev), &uuid); in ipu_bridge_get_ivsc_csi_dev()
193 dev_err(ADEV_DEV(adev), "Failed to find MEI CSI dev\n"); in ipu_bridge_check_ivsc_dev()
194 return -ENODEV; in ipu_bridge_check_ivsc_dev()
197 sensor->csi_dev = csi_dev; in ipu_bridge_check_ivsc_dev()
198 sensor->ivsc_adev = adev; in ipu_bridge_check_ivsc_dev()
212 status = acpi_evaluate_object(ACPI_PTR(adev->handle), in ipu_bridge_read_acpi_buffer()
215 return -ENODEV; in ipu_bridge_read_acpi_buffer()
220 return -ENODEV; in ipu_bridge_read_acpi_buffer()
223 if (obj->type != ACPI_TYPE_BUFFER) { in ipu_bridge_read_acpi_buffer()
225 ret = -ENODEV; in ipu_bridge_read_acpi_buffer()
229 if (obj->buffer.length > size) { in ipu_bridge_read_acpi_buffer()
231 ret = -EINVAL; in ipu_bridge_read_acpi_buffer()
235 memcpy(data, obj->buffer.pointer, obj->buffer.length); in ipu_bridge_read_acpi_buffer()
245 switch (ssdb->degree) { in ipu_bridge_parse_rotation()
253 ssdb->degree); in ipu_bridge_parse_rotation()
265 status = acpi_get_physical_device_location(adev->handle, &pld); in ipu_bridge_parse_orientation()
272 switch (pld->panel) { in ipu_bridge_parse_orientation()
287 pld->panel); in ipu_bridge_parse_orientation()
312 return -EINVAL; in ipu_bridge_parse_ssdb()
315 sensor->link = ssdb.link; in ipu_bridge_parse_ssdb()
316 sensor->lanes = ssdb.lanes; in ipu_bridge_parse_ssdb()
317 sensor->mclkspeed = ssdb.mclkspeed; in ipu_bridge_parse_ssdb()
318 sensor->rotation = ipu_bridge_parse_rotation(adev, &ssdb); in ipu_bridge_parse_ssdb()
319 sensor->orientation = ipu_bridge_parse_orientation(adev); in ipu_bridge_parse_ssdb()
322 sensor->vcm_type = ipu_vcm_types[ssdb.vcmtype - 1]; in ipu_bridge_parse_ssdb()
330 struct ipu_bridge *bridge, in ipu_bridge_create_fwnode_properties() argument
333 struct ipu_property_names *names = &sensor->prop_names; in ipu_bridge_create_fwnode_properties()
334 struct software_node *nodes = sensor->swnodes; in ipu_bridge_create_fwnode_properties()
336 sensor->prop_names = prop_names; in ipu_bridge_create_fwnode_properties()
338 if (sensor->csi_dev) { in ipu_bridge_create_fwnode_properties()
339 sensor->local_ref[0] = in ipu_bridge_create_fwnode_properties()
341 sensor->remote_ref[0] = in ipu_bridge_create_fwnode_properties()
343 sensor->ivsc_sensor_ref[0] = in ipu_bridge_create_fwnode_properties()
345 sensor->ivsc_ipu_ref[0] = in ipu_bridge_create_fwnode_properties()
348 sensor->ivsc_sensor_ep_properties[0] = in ipu_bridge_create_fwnode_properties()
349 PROPERTY_ENTRY_U32(names->bus_type, in ipu_bridge_create_fwnode_properties()
351 sensor->ivsc_sensor_ep_properties[1] = in ipu_bridge_create_fwnode_properties()
352 PROPERTY_ENTRY_U32_ARRAY_LEN(names->data_lanes, in ipu_bridge_create_fwnode_properties()
353 bridge->data_lanes, in ipu_bridge_create_fwnode_properties()
354 sensor->lanes); in ipu_bridge_create_fwnode_properties()
355 sensor->ivsc_sensor_ep_properties[2] = in ipu_bridge_create_fwnode_properties()
356 PROPERTY_ENTRY_REF_ARRAY(names->remote_endpoint, in ipu_bridge_create_fwnode_properties()
357 sensor->ivsc_sensor_ref); in ipu_bridge_create_fwnode_properties()
359 sensor->ivsc_ipu_ep_properties[0] = in ipu_bridge_create_fwnode_properties()
360 PROPERTY_ENTRY_U32(names->bus_type, in ipu_bridge_create_fwnode_properties()
362 sensor->ivsc_ipu_ep_properties[1] = in ipu_bridge_create_fwnode_properties()
363 PROPERTY_ENTRY_U32_ARRAY_LEN(names->data_lanes, in ipu_bridge_create_fwnode_properties()
364 bridge->data_lanes, in ipu_bridge_create_fwnode_properties()
365 sensor->lanes); in ipu_bridge_create_fwnode_properties()
366 sensor->ivsc_ipu_ep_properties[2] = in ipu_bridge_create_fwnode_properties()
367 PROPERTY_ENTRY_REF_ARRAY(names->remote_endpoint, in ipu_bridge_create_fwnode_properties()
368 sensor->ivsc_ipu_ref); in ipu_bridge_create_fwnode_properties()
370 sensor->local_ref[0] = in ipu_bridge_create_fwnode_properties()
372 sensor->remote_ref[0] = in ipu_bridge_create_fwnode_properties()
376 sensor->dev_properties[0] = PROPERTY_ENTRY_U32( in ipu_bridge_create_fwnode_properties()
377 sensor->prop_names.clock_frequency, in ipu_bridge_create_fwnode_properties()
378 sensor->mclkspeed); in ipu_bridge_create_fwnode_properties()
379 sensor->dev_properties[1] = PROPERTY_ENTRY_U32( in ipu_bridge_create_fwnode_properties()
380 sensor->prop_names.rotation, in ipu_bridge_create_fwnode_properties()
381 sensor->rotation); in ipu_bridge_create_fwnode_properties()
382 sensor->dev_properties[2] = PROPERTY_ENTRY_U32( in ipu_bridge_create_fwnode_properties()
383 sensor->prop_names.orientation, in ipu_bridge_create_fwnode_properties()
384 sensor->orientation); in ipu_bridge_create_fwnode_properties()
385 if (sensor->vcm_type) { in ipu_bridge_create_fwnode_properties()
386 sensor->vcm_ref[0] = in ipu_bridge_create_fwnode_properties()
387 SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); in ipu_bridge_create_fwnode_properties()
388 sensor->dev_properties[3] = in ipu_bridge_create_fwnode_properties()
389 PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); in ipu_bridge_create_fwnode_properties()
392 sensor->ep_properties[0] = PROPERTY_ENTRY_U32( in ipu_bridge_create_fwnode_properties()
393 sensor->prop_names.bus_type, in ipu_bridge_create_fwnode_properties()
395 sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN( in ipu_bridge_create_fwnode_properties()
396 sensor->prop_names.data_lanes, in ipu_bridge_create_fwnode_properties()
397 bridge->data_lanes, sensor->lanes); in ipu_bridge_create_fwnode_properties()
398 sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY( in ipu_bridge_create_fwnode_properties()
399 sensor->prop_names.remote_endpoint, in ipu_bridge_create_fwnode_properties()
400 sensor->local_ref); in ipu_bridge_create_fwnode_properties()
402 if (cfg->nr_link_freqs > 0) in ipu_bridge_create_fwnode_properties()
403 sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN( in ipu_bridge_create_fwnode_properties()
404 sensor->prop_names.link_frequencies, in ipu_bridge_create_fwnode_properties()
405 cfg->link_freqs, in ipu_bridge_create_fwnode_properties()
406 cfg->nr_link_freqs); in ipu_bridge_create_fwnode_properties()
408 sensor->ipu_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN( in ipu_bridge_create_fwnode_properties()
409 sensor->prop_names.data_lanes, in ipu_bridge_create_fwnode_properties()
410 bridge->data_lanes, sensor->lanes); in ipu_bridge_create_fwnode_properties()
411 sensor->ipu_properties[1] = PROPERTY_ENTRY_REF_ARRAY( in ipu_bridge_create_fwnode_properties()
412 sensor->prop_names.remote_endpoint, in ipu_bridge_create_fwnode_properties()
413 sensor->remote_ref); in ipu_bridge_create_fwnode_properties()
418 snprintf(sensor->node_names.remote_port, in ipu_bridge_init_swnode_names()
419 sizeof(sensor->node_names.remote_port), in ipu_bridge_init_swnode_names()
420 SWNODE_GRAPH_PORT_NAME_FMT, sensor->link); in ipu_bridge_init_swnode_names()
421 snprintf(sensor->node_names.port, in ipu_bridge_init_swnode_names()
422 sizeof(sensor->node_names.port), in ipu_bridge_init_swnode_names()
424 snprintf(sensor->node_names.endpoint, in ipu_bridge_init_swnode_names()
425 sizeof(sensor->node_names.endpoint), in ipu_bridge_init_swnode_names()
427 if (sensor->vcm_type) { in ipu_bridge_init_swnode_names()
429 snprintf(sensor->node_names.vcm, sizeof(sensor->node_names.vcm), in ipu_bridge_init_swnode_names()
430 "%s-%u", sensor->vcm_type, sensor->link); in ipu_bridge_init_swnode_names()
433 if (sensor->csi_dev) { in ipu_bridge_init_swnode_names()
434 snprintf(sensor->node_names.ivsc_sensor_port, in ipu_bridge_init_swnode_names()
435 sizeof(sensor->node_names.ivsc_sensor_port), in ipu_bridge_init_swnode_names()
437 snprintf(sensor->node_names.ivsc_ipu_port, in ipu_bridge_init_swnode_names()
438 sizeof(sensor->node_names.ivsc_ipu_port), in ipu_bridge_init_swnode_names()
445 struct software_node *nodes = sensor->swnodes; in ipu_bridge_init_swnode_group()
447 sensor->group[SWNODE_SENSOR_HID] = &nodes[SWNODE_SENSOR_HID]; in ipu_bridge_init_swnode_group()
448 sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; in ipu_bridge_init_swnode_group()
449 sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; in ipu_bridge_init_swnode_group()
450 sensor->group[SWNODE_IPU_PORT] = &nodes[SWNODE_IPU_PORT]; in ipu_bridge_init_swnode_group()
451 sensor->group[SWNODE_IPU_ENDPOINT] = &nodes[SWNODE_IPU_ENDPOINT]; in ipu_bridge_init_swnode_group()
452 if (sensor->vcm_type) in ipu_bridge_init_swnode_group()
453 sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; in ipu_bridge_init_swnode_group()
455 if (sensor->csi_dev) { in ipu_bridge_init_swnode_group()
456 sensor->group[SWNODE_IVSC_HID] = in ipu_bridge_init_swnode_group()
458 sensor->group[SWNODE_IVSC_SENSOR_PORT] = in ipu_bridge_init_swnode_group()
460 sensor->group[SWNODE_IVSC_SENSOR_ENDPOINT] = in ipu_bridge_init_swnode_group()
462 sensor->group[SWNODE_IVSC_IPU_PORT] = in ipu_bridge_init_swnode_group()
464 sensor->group[SWNODE_IVSC_IPU_ENDPOINT] = in ipu_bridge_init_swnode_group()
467 if (sensor->vcm_type) in ipu_bridge_init_swnode_group()
468 sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; in ipu_bridge_init_swnode_group()
470 if (sensor->vcm_type) in ipu_bridge_init_swnode_group()
471 sensor->group[SWNODE_IVSC_HID] = &nodes[SWNODE_VCM]; in ipu_bridge_init_swnode_group()
475 static void ipu_bridge_create_connection_swnodes(struct ipu_bridge *bridge, in ipu_bridge_create_connection_swnodes() argument
478 struct ipu_node_names *names = &sensor->node_names; in ipu_bridge_create_connection_swnodes()
479 struct software_node *nodes = sensor->swnodes; in ipu_bridge_create_connection_swnodes()
483 nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name, in ipu_bridge_create_connection_swnodes()
484 sensor->dev_properties); in ipu_bridge_create_connection_swnodes()
485 nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, in ipu_bridge_create_connection_swnodes()
488 sensor->node_names.endpoint, in ipu_bridge_create_connection_swnodes()
490 sensor->ep_properties); in ipu_bridge_create_connection_swnodes()
491 nodes[SWNODE_IPU_PORT] = NODE_PORT(sensor->node_names.remote_port, in ipu_bridge_create_connection_swnodes()
492 &bridge->ipu_hid_node); in ipu_bridge_create_connection_swnodes()
494 sensor->node_names.endpoint, in ipu_bridge_create_connection_swnodes()
496 sensor->ipu_properties); in ipu_bridge_create_connection_swnodes()
498 if (sensor->csi_dev) { in ipu_bridge_create_connection_swnodes()
502 device_hid = acpi_device_hid(sensor->ivsc_adev); in ipu_bridge_create_connection_swnodes()
505 snprintf(sensor->ivsc_name, sizeof(sensor->ivsc_name), "%s-%u", in ipu_bridge_create_connection_swnodes()
506 device_hid, sensor->link); in ipu_bridge_create_connection_swnodes()
508 nodes[SWNODE_IVSC_HID] = NODE_SENSOR(sensor->ivsc_name, in ipu_bridge_create_connection_swnodes()
509 sensor->ivsc_properties); in ipu_bridge_create_connection_swnodes()
511 NODE_PORT(names->ivsc_sensor_port, in ipu_bridge_create_connection_swnodes()
514 NODE_ENDPOINT(names->endpoint, in ipu_bridge_create_connection_swnodes()
516 sensor->ivsc_sensor_ep_properties); in ipu_bridge_create_connection_swnodes()
518 NODE_PORT(names->ivsc_ipu_port, in ipu_bridge_create_connection_swnodes()
521 NODE_ENDPOINT(names->endpoint, in ipu_bridge_create_connection_swnodes()
523 sensor->ivsc_ipu_ep_properties); in ipu_bridge_create_connection_swnodes()
526 nodes[SWNODE_VCM] = NODE_VCM(sensor->node_names.vcm); in ipu_bridge_create_connection_swnodes()
533 * a deadlock on taking list_lock from v4l2-async twice.
547 struct acpi_device *adev = ACPI_COMPANION(data->sensor); in ipu_bridge_instantiate_vcm_work()
554 * make sure the sensor is powered-up during probe. in ipu_bridge_instantiate_vcm_work()
556 ret = pm_runtime_get_sync(data->sensor); in ipu_bridge_instantiate_vcm_work()
558 dev_err(data->sensor, "Error %d runtime-resuming sensor, cannot instantiate VCM\n", in ipu_bridge_instantiate_vcm_work()
565 * even after a rmmod, just like the software-nodes. in ipu_bridge_instantiate_vcm_work()
568 1, &data->board_info); in ipu_bridge_instantiate_vcm_work()
570 dev_err(data->sensor, "Error instantiating VCM client: %ld\n", in ipu_bridge_instantiate_vcm_work()
575 device_link_add(&vcm_client->dev, data->sensor, DL_FLAG_PM_RUNTIME); in ipu_bridge_instantiate_vcm_work()
577 dev_info(data->sensor, "Instantiated %s VCM\n", data->board_info.type); in ipu_bridge_instantiate_vcm_work()
578 put_fwnode = false; /* Ownership has passed to the i2c-client */ in ipu_bridge_instantiate_vcm_work()
581 pm_runtime_put(data->sensor); in ipu_bridge_instantiate_vcm_work()
582 put_device(data->sensor); in ipu_bridge_instantiate_vcm_work()
584 fwnode_handle_put(data->board_info.fwnode); in ipu_bridge_instantiate_vcm_work()
600 vcm_fwnode = fwnode_find_reference(dev_fwnode(sensor), "lens-focus", 0); in ipu_bridge_instantiate_vcm()
608 put_device(&vcm_client->dev); in ipu_bridge_instantiate_vcm()
615 return -ENOMEM; in ipu_bridge_instantiate_vcm()
618 INIT_WORK(&data->work, ipu_bridge_instantiate_vcm_work); in ipu_bridge_instantiate_vcm()
619 data->sensor = get_device(sensor); in ipu_bridge_instantiate_vcm()
620 snprintf(data->name, sizeof(data->name), "%s-VCM", in ipu_bridge_instantiate_vcm()
622 data->board_info.dev_name = data->name; in ipu_bridge_instantiate_vcm()
623 data->board_info.fwnode = vcm_fwnode; in ipu_bridge_instantiate_vcm()
624 snprintf(data->board_info.type, sizeof(data->board_info.type), in ipu_bridge_instantiate_vcm()
626 /* Strip "-<link>" postfix */ in ipu_bridge_instantiate_vcm()
627 sep = strchrnul(data->board_info.type, '-'); in ipu_bridge_instantiate_vcm()
630 queue_work(system_long_wq, &data->work); in ipu_bridge_instantiate_vcm()
640 if (!sensor->csi_dev) in ipu_bridge_instantiate_ivsc()
643 fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_IVSC_HID]); in ipu_bridge_instantiate_ivsc()
645 return -ENODEV; in ipu_bridge_instantiate_ivsc()
647 set_secondary_fwnode(sensor->csi_dev, fwnode); in ipu_bridge_instantiate_ivsc()
652 static void ipu_bridge_unregister_sensors(struct ipu_bridge *bridge) in ipu_bridge_unregister_sensors() argument
657 for (i = 0; i < bridge->n_sensors; i++) { in ipu_bridge_unregister_sensors()
658 sensor = &bridge->sensors[i]; in ipu_bridge_unregister_sensors()
659 software_node_unregister_node_group(sensor->group); in ipu_bridge_unregister_sensors()
660 acpi_dev_put(sensor->adev); in ipu_bridge_unregister_sensors()
661 put_device(sensor->csi_dev); in ipu_bridge_unregister_sensors()
662 acpi_dev_put(sensor->ivsc_adev); in ipu_bridge_unregister_sensors()
667 struct ipu_bridge *bridge) argument
675 for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
679 if (!ACPI_PTR(adev->status.enabled))
682 if (bridge->n_sensors >= IPU_MAX_PORTS) {
684 dev_err(bridge->dev, "Exceeded available IPU ports\n");
685 return -EINVAL;
688 sensor = &bridge->sensors[bridge->n_sensors];
690 ret = bridge->parse_sensor_fwnode(adev, sensor);
694 snprintf(sensor->name, sizeof(sensor->name), "%s-%u",
695 cfg->hid, sensor->link);
701 ipu_bridge_create_fwnode_properties(sensor, bridge, cfg);
702 ipu_bridge_create_connection_swnodes(bridge, sensor);
704 ret = software_node_register_node_group(sensor->group);
708 fwnode = software_node_fwnode(&sensor->swnodes[
711 ret = -ENODEV;
715 sensor->adev = ACPI_PTR(acpi_dev_get(adev));
718 primary->secondary = fwnode;
724 dev_info(bridge->dev, "Found supported sensor %s\n",
727 bridge->n_sensors++;
733 software_node_unregister_node_group(sensor->group);
735 put_device(sensor->csi_dev);
736 acpi_dev_put(sensor->ivsc_adev);
742 static int ipu_bridge_connect_sensors(struct ipu_bridge *bridge) argument
751 ret = ipu_bridge_connect_sensor(cfg, bridge);
759 ipu_bridge_unregister_sensors(bridge);
775 for_each_acpi_dev_match(sensor_adev, cfg->hid, NULL, -1) {
780 if (!ACPI_PTR(sensor_adev->status.enabled))
804 return -EINVAL;
812 return ipu_bridge_check_fwnode_graph(fwnode->secondary);
821 struct ipu_bridge *bridge; local
831 return -EPROBE_DEFER;
833 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
834 if (!bridge)
835 return -ENOMEM;
837 strscpy(bridge->ipu_node_name, IPU_HID,
838 sizeof(bridge->ipu_node_name));
839 bridge->ipu_hid_node.name = bridge->ipu_node_name;
840 bridge->dev = dev;
841 bridge->parse_sensor_fwnode = parse_sensor_fwnode;
843 ret = software_node_register(&bridge->ipu_hid_node);
857 bridge->data_lanes[i] = i + 1;
859 ret = ipu_bridge_connect_sensors(bridge);
860 if (ret || bridge->n_sensors == 0)
863 dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
865 fwnode = software_node_fwnode(&bridge->ipu_hid_node);
868 ret = -ENODEV;
877 ipu_bridge_unregister_sensors(bridge);
879 software_node_unregister(&bridge->ipu_hid_node);
881 kfree(bridge);
888 MODULE_DESCRIPTION("Intel IPU Sensors Bridge driver");