diff options
Diffstat (limited to 'drivers/media/pci/intel/ipu3')
-rw-r--r-- | drivers/media/pci/intel/ipu3/Kconfig | 1 | ||||
-rw-r--r-- | drivers/media/pci/intel/ipu3/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/pci/intel/ipu3/cio2-bridge.c | 494 | ||||
-rw-r--r-- | drivers/media/pci/intel/ipu3/cio2-bridge.h | 146 | ||||
-rw-r--r-- | drivers/media/pci/intel/ipu3/ipu3-cio2.c (renamed from drivers/media/pci/intel/ipu3/ipu3-cio2-main.c) | 26 | ||||
-rw-r--r-- | drivers/media/pci/intel/ipu3/ipu3-cio2.h | 6 |
6 files changed, 18 insertions, 658 deletions
diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig index 65b0c1598fbf..0951545eab21 100644 --- a/drivers/media/pci/intel/ipu3/Kconfig +++ b/drivers/media/pci/intel/ipu3/Kconfig @@ -8,6 +8,7 @@ config VIDEO_IPU3_CIO2 select VIDEO_V4L2_SUBDEV_API select V4L2_FWNODE select VIDEOBUF2_DMA_SG + select IPU_BRIDGE if CIO2_BRIDGE help This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile index 933777e6ea8a..98ddd5beafe0 100644 --- a/drivers/media/pci/intel/ipu3/Makefile +++ b/drivers/media/pci/intel/ipu3/Makefile @@ -1,5 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o - -ipu3-cio2-y += ipu3-cio2-main.o -ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c deleted file mode 100644 index 3c2accfe5455..000000000000 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ /dev/null @@ -1,494 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Author: Dan Scally <djrscally@gmail.com> */ - -#include <linux/acpi.h> -#include <linux/device.h> -#include <linux/i2c.h> -#include <linux/pci.h> -#include <linux/property.h> -#include <media/v4l2-fwnode.h> - -#include "cio2-bridge.h" - -/* - * Extend this array with ACPI Hardware IDs of devices known to be working - * plus the number of link-frequencies expected by their drivers, along with - * the frequency values in hertz. This is somewhat opportunistic way of adding - * support for this for now in the hopes of a better source for the information - * (possibly some encoded value in the SSDB buffer that we're unaware of) - * becoming apparent in the future. - * - * Do not add an entry for a sensor that is not actually supported. - */ -static const struct cio2_sensor_config cio2_supported_sensors[] = { - /* Omnivision OV5693 */ - CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000), - /* Omnivision OV8865 */ - CIO2_SENSOR_CONFIG("INT347A", 1, 360000000), - /* Omnivision OV7251 */ - CIO2_SENSOR_CONFIG("INT347E", 1, 319200000), - /* Omnivision OV2680 */ - CIO2_SENSOR_CONFIG("OVTI2680", 0), - /* Omnivision ov8856 */ - CIO2_SENSOR_CONFIG("OVTI8856", 3, 180000000, 360000000, 720000000), - /* Omnivision ov2740 */ - CIO2_SENSOR_CONFIG("INT3474", 1, 360000000), - /* Hynix hi556 */ - CIO2_SENSOR_CONFIG("INT3537", 1, 437000000), - /* Omnivision ov13b10 */ - CIO2_SENSOR_CONFIG("OVTIDB10", 1, 560000000), -}; - -static const struct cio2_property_names prop_names = { - .clock_frequency = "clock-frequency", - .rotation = "rotation", - .orientation = "orientation", - .bus_type = "bus-type", - .data_lanes = "data-lanes", - .remote_endpoint = "remote-endpoint", - .link_frequencies = "link-frequencies", -}; - -static const char * const cio2_vcm_types[] = { - "ad5823", - "dw9714", - "ad5816", - "dw9719", - "dw9718", - "dw9806b", - "wv517s", - "lc898122xa", - "lc898212axb", -}; - -static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id, - void *data, u32 size) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - int ret = 0; - - status = acpi_evaluate_object(adev->handle, id, NULL, &buffer); - if (ACPI_FAILURE(status)) - return -ENODEV; - - obj = buffer.pointer; - if (!obj) { - dev_err(&adev->dev, "Couldn't locate ACPI buffer\n"); - return -ENODEV; - } - - if (obj->type != ACPI_TYPE_BUFFER) { - dev_err(&adev->dev, "Not an ACPI buffer\n"); - ret = -ENODEV; - goto out_free_buff; - } - - if (obj->buffer.length > size) { - dev_err(&adev->dev, "Given buffer is too small\n"); - ret = -EINVAL; - goto out_free_buff; - } - - memcpy(data, obj->buffer.pointer, obj->buffer.length); - -out_free_buff: - kfree(buffer.pointer); - return ret; -} - -static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor) -{ - switch (sensor->ssdb.degree) { - case CIO2_SENSOR_ROTATION_NORMAL: - return 0; - case CIO2_SENSOR_ROTATION_INVERTED: - return 180; - default: - dev_warn(&sensor->adev->dev, - "Unknown rotation %d. Assume 0 degree rotation\n", - sensor->ssdb.degree); - return 0; - } -} - -static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(struct cio2_sensor *sensor) -{ - switch (sensor->pld->panel) { - case ACPI_PLD_PANEL_FRONT: - return V4L2_FWNODE_ORIENTATION_FRONT; - case ACPI_PLD_PANEL_BACK: - return V4L2_FWNODE_ORIENTATION_BACK; - case ACPI_PLD_PANEL_TOP: - case ACPI_PLD_PANEL_LEFT: - case ACPI_PLD_PANEL_RIGHT: - case ACPI_PLD_PANEL_UNKNOWN: - return V4L2_FWNODE_ORIENTATION_EXTERNAL; - default: - dev_warn(&sensor->adev->dev, "Unknown _PLD panel value %d\n", - sensor->pld->panel); - return V4L2_FWNODE_ORIENTATION_EXTERNAL; - } -} - -static void cio2_bridge_create_fwnode_properties( - struct cio2_sensor *sensor, - struct cio2_bridge *bridge, - const struct cio2_sensor_config *cfg) -{ - u32 rotation; - enum v4l2_fwnode_orientation orientation; - - rotation = cio2_bridge_parse_rotation(sensor); - orientation = cio2_bridge_parse_orientation(sensor); - - sensor->prop_names = prop_names; - - sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]); - sensor->remote_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_SENSOR_ENDPOINT]); - - sensor->dev_properties[0] = PROPERTY_ENTRY_U32( - sensor->prop_names.clock_frequency, - sensor->ssdb.mclkspeed); - sensor->dev_properties[1] = PROPERTY_ENTRY_U32( - sensor->prop_names.rotation, - rotation); - sensor->dev_properties[2] = PROPERTY_ENTRY_U32( - sensor->prop_names.orientation, - orientation); - if (sensor->ssdb.vcmtype) { - sensor->vcm_ref[0] = - SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]); - sensor->dev_properties[3] = - PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref); - } - - sensor->ep_properties[0] = PROPERTY_ENTRY_U32( - sensor->prop_names.bus_type, - V4L2_FWNODE_BUS_TYPE_CSI2_DPHY); - sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN( - sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->ssdb.lanes); - sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY( - sensor->prop_names.remote_endpoint, - sensor->local_ref); - - if (cfg->nr_link_freqs > 0) - sensor->ep_properties[3] = PROPERTY_ENTRY_U64_ARRAY_LEN( - sensor->prop_names.link_frequencies, - cfg->link_freqs, - cfg->nr_link_freqs); - - sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN( - sensor->prop_names.data_lanes, - bridge->data_lanes, - sensor->ssdb.lanes); - sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY( - sensor->prop_names.remote_endpoint, - sensor->remote_ref); -} - -static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor) -{ - snprintf(sensor->node_names.remote_port, - sizeof(sensor->node_names.remote_port), - SWNODE_GRAPH_PORT_NAME_FMT, sensor->ssdb.link); - snprintf(sensor->node_names.port, - sizeof(sensor->node_names.port), - SWNODE_GRAPH_PORT_NAME_FMT, 0); /* Always port 0 */ - snprintf(sensor->node_names.endpoint, - sizeof(sensor->node_names.endpoint), - SWNODE_GRAPH_ENDPOINT_NAME_FMT, 0); /* And endpoint 0 */ -} - -static void cio2_bridge_init_swnode_group(struct cio2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - - sensor->group[SWNODE_SENSOR_HID] = &nodes[SWNODE_SENSOR_HID]; - sensor->group[SWNODE_SENSOR_PORT] = &nodes[SWNODE_SENSOR_PORT]; - sensor->group[SWNODE_SENSOR_ENDPOINT] = &nodes[SWNODE_SENSOR_ENDPOINT]; - sensor->group[SWNODE_CIO2_PORT] = &nodes[SWNODE_CIO2_PORT]; - sensor->group[SWNODE_CIO2_ENDPOINT] = &nodes[SWNODE_CIO2_ENDPOINT]; - if (sensor->ssdb.vcmtype) - sensor->group[SWNODE_VCM] = &nodes[SWNODE_VCM]; -} - -static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge, - struct cio2_sensor *sensor) -{ - struct software_node *nodes = sensor->swnodes; - char vcm_name[ACPI_ID_LEN + 4]; - - cio2_bridge_init_swnode_names(sensor); - - nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name, - sensor->dev_properties); - nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port, - &nodes[SWNODE_SENSOR_HID]); - nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT( - sensor->node_names.endpoint, - &nodes[SWNODE_SENSOR_PORT], - sensor->ep_properties); - nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port, - &bridge->cio2_hid_node); - nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT( - sensor->node_names.endpoint, - &nodes[SWNODE_CIO2_PORT], - sensor->cio2_properties); - if (sensor->ssdb.vcmtype) { - /* append ssdb.link to distinguish VCM nodes with same HID */ - snprintf(vcm_name, sizeof(vcm_name), "%s-%u", - cio2_vcm_types[sensor->ssdb.vcmtype - 1], - sensor->ssdb.link); - nodes[SWNODE_VCM] = NODE_VCM(vcm_name); - } - - cio2_bridge_init_swnode_group(sensor); -} - -static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor) -{ - struct i2c_board_info board_info = { }; - char name[16]; - - if (!sensor->ssdb.vcmtype) - return; - - snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev)); - board_info.dev_name = name; - strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1], - ARRAY_SIZE(board_info.type)); - board_info.swnode = &sensor->swnodes[SWNODE_VCM]; - - sensor->vcm_i2c_client = - i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev), - 1, &board_info); - if (IS_ERR(sensor->vcm_i2c_client)) { - dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n", - PTR_ERR(sensor->vcm_i2c_client)); - sensor->vcm_i2c_client = NULL; - } -} - -static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge) -{ - struct cio2_sensor *sensor; - unsigned int i; - - for (i = 0; i < bridge->n_sensors; i++) { - sensor = &bridge->sensors[i]; - software_node_unregister_node_group(sensor->group); - ACPI_FREE(sensor->pld); - acpi_dev_put(sensor->adev); - i2c_unregister_device(sensor->vcm_i2c_client); - } -} - -static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg, - struct cio2_bridge *bridge, - struct pci_dev *cio2) -{ - struct fwnode_handle *fwnode, *primary; - struct cio2_sensor *sensor; - struct acpi_device *adev; - acpi_status status; - int ret; - - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; - - if (bridge->n_sensors >= CIO2_NUM_PORTS) { - acpi_dev_put(adev); - dev_err(&cio2->dev, "Exceeded available CIO2 ports\n"); - return -EINVAL; - } - - sensor = &bridge->sensors[bridge->n_sensors]; - - ret = cio2_bridge_read_acpi_buffer(adev, "SSDB", - &sensor->ssdb, - sizeof(sensor->ssdb)); - if (ret) - goto err_put_adev; - - snprintf(sensor->name, sizeof(sensor->name), "%s-%u", - cfg->hid, sensor->ssdb.link); - - if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) { - dev_warn(&adev->dev, "Unknown VCM type %d\n", - sensor->ssdb.vcmtype); - sensor->ssdb.vcmtype = 0; - } - - status = acpi_get_physical_device_location(adev->handle, &sensor->pld); - if (ACPI_FAILURE(status)) { - ret = -ENODEV; - goto err_put_adev; - } - - if (sensor->ssdb.lanes > CIO2_MAX_LANES) { - dev_err(&adev->dev, - "Number of lanes in SSDB is invalid\n"); - ret = -EINVAL; - goto err_free_pld; - } - - cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); - cio2_bridge_create_connection_swnodes(bridge, sensor); - - ret = software_node_register_node_group(sensor->group); - if (ret) - goto err_free_pld; - - fwnode = software_node_fwnode(&sensor->swnodes[ - SWNODE_SENSOR_HID]); - if (!fwnode) { - ret = -ENODEV; - goto err_free_swnodes; - } - - sensor->adev = acpi_dev_get(adev); - - primary = acpi_fwnode_handle(adev); - primary->secondary = fwnode; - - cio2_bridge_instantiate_vcm_i2c_client(sensor); - - dev_info(&cio2->dev, "Found supported sensor %s\n", - acpi_dev_name(adev)); - - bridge->n_sensors++; - } - - return 0; - -err_free_swnodes: - software_node_unregister_node_group(sensor->group); -err_free_pld: - ACPI_FREE(sensor->pld); -err_put_adev: - acpi_dev_put(adev); - return ret; -} - -static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge, - struct pci_dev *cio2) -{ - unsigned int i; - int ret; - - for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) { - const struct cio2_sensor_config *cfg = - &cio2_supported_sensors[i]; - - ret = cio2_bridge_connect_sensor(cfg, bridge, cio2); - if (ret) - goto err_unregister_sensors; - } - - return 0; - -err_unregister_sensors: - cio2_bridge_unregister_sensors(bridge); - return ret; -} - -/* - * The VCM cannot be probed until the PMIC is completely setup. We cannot rely - * on -EPROBE_DEFER for this, since the consumer<->supplier relations between - * the VCM and regulators/clks are not described in ACPI, instead they are - * passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work - * for the clks/regulators the VCM i2c-clients must not be instantiated until - * the PMIC is fully setup. - * - * The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the - * acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does - * for the sensors. - */ -static int cio2_bridge_sensors_are_ready(void) -{ - struct acpi_device *adev; - bool ready = true; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) { - const struct cio2_sensor_config *cfg = - &cio2_supported_sensors[i]; - - for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) - continue; - - if (!acpi_dev_ready_for_enumeration(adev)) - ready = false; - } - } - - return ready; -} - -int cio2_bridge_init(struct pci_dev *cio2) -{ - struct device *dev = &cio2->dev; - struct fwnode_handle *fwnode; - struct cio2_bridge *bridge; - unsigned int i; - int ret; - - if (!cio2_bridge_sensors_are_ready()) - return -EPROBE_DEFER; - - bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); - if (!bridge) - return -ENOMEM; - - strscpy(bridge->cio2_node_name, CIO2_HID, - sizeof(bridge->cio2_node_name)); - bridge->cio2_hid_node.name = bridge->cio2_node_name; - - ret = software_node_register(&bridge->cio2_hid_node); - if (ret < 0) { - dev_err(dev, "Failed to register the CIO2 HID node\n"); - goto err_free_bridge; - } - - /* - * Map the lane arrangement, which is fixed for the IPU3 (meaning we - * only need one, rather than one per sensor). We include it as a - * member of the struct cio2_bridge rather than a global variable so - * that it survives if the module is unloaded along with the rest of - * the struct. - */ - for (i = 0; i < CIO2_MAX_LANES; i++) - bridge->data_lanes[i] = i + 1; - - ret = cio2_bridge_connect_sensors(bridge, cio2); - if (ret || bridge->n_sensors == 0) - goto err_unregister_cio2; - - dev_info(dev, "Connected %d cameras\n", bridge->n_sensors); - - fwnode = software_node_fwnode(&bridge->cio2_hid_node); - if (!fwnode) { - dev_err(dev, "Error getting fwnode from cio2 software_node\n"); - ret = -ENODEV; - goto err_unregister_sensors; - } - - set_secondary_fwnode(dev, fwnode); - - return 0; - -err_unregister_sensors: - cio2_bridge_unregister_sensors(bridge); -err_unregister_cio2: - software_node_unregister(&bridge->cio2_hid_node); -err_free_bridge: - kfree(bridge); - - return ret; -} diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h deleted file mode 100644 index b76ed8a641e2..000000000000 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.h +++ /dev/null @@ -1,146 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Author: Dan Scally <djrscally@gmail.com> */ -#ifndef __CIO2_BRIDGE_H -#define __CIO2_BRIDGE_H - -#include <linux/property.h> -#include <linux/types.h> - -#include "ipu3-cio2.h" - -struct i2c_client; - -#define CIO2_HID "INT343E" -#define CIO2_MAX_LANES 4 -#define MAX_NUM_LINK_FREQS 3 - -/* Values are educated guesses as we don't have a spec */ -#define CIO2_SENSOR_ROTATION_NORMAL 0 -#define CIO2_SENSOR_ROTATION_INVERTED 1 - -#define CIO2_SENSOR_CONFIG(_HID, _NR, ...) \ - (const struct cio2_sensor_config) { \ - .hid = _HID, \ - .nr_link_freqs = _NR, \ - .link_freqs = { __VA_ARGS__ } \ - } - -#define NODE_SENSOR(_HID, _PROPS) \ - (const struct software_node) { \ - .name = _HID, \ - .properties = _PROPS, \ - } - -#define NODE_PORT(_PORT, _SENSOR_NODE) \ - (const struct software_node) { \ - .name = _PORT, \ - .parent = _SENSOR_NODE, \ - } - -#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ - (const struct software_node) { \ - .name = _EP, \ - .parent = _PORT, \ - .properties = _PROPS, \ - } - -#define NODE_VCM(_TYPE) \ - (const struct software_node) { \ - .name = _TYPE, \ - } - -enum cio2_sensor_swnodes { - SWNODE_SENSOR_HID, - SWNODE_SENSOR_PORT, - SWNODE_SENSOR_ENDPOINT, - SWNODE_CIO2_PORT, - SWNODE_CIO2_ENDPOINT, - /* Must be last because it is optional / maybe empty */ - SWNODE_VCM, - SWNODE_COUNT -}; - -/* Data representation as it is in ACPI SSDB buffer */ -struct cio2_sensor_ssdb { - u8 version; - u8 sku; - u8 guid_csi2[16]; - u8 devfunction; - u8 bus; - u32 dphylinkenfuses; - u32 clockdiv; - u8 link; - u8 lanes; - u32 csiparams[10]; - u32 maxlanespeed; - u8 sensorcalibfileidx; - u8 sensorcalibfileidxInMBZ[3]; - u8 romtype; - u8 vcmtype; - u8 platforminfo; - u8 platformsubinfo; - u8 flash; - u8 privacyled; - u8 degree; - u8 mipilinkdefined; - u32 mclkspeed; - u8 controllogicid; - u8 reserved1[3]; - u8 mclkport; - u8 reserved2[13]; -} __packed; - -struct cio2_property_names { - char clock_frequency[16]; - char rotation[9]; - char orientation[12]; - char bus_type[9]; - char data_lanes[11]; - char remote_endpoint[16]; - char link_frequencies[17]; -}; - -struct cio2_node_names { - char port[7]; - char endpoint[11]; - char remote_port[7]; -}; - -struct cio2_sensor_config { - const char *hid; - const u8 nr_link_freqs; - const u64 link_freqs[MAX_NUM_LINK_FREQS]; -}; - -struct cio2_sensor { - /* append ssdb.link(u8) in "-%u" format as suffix of HID */ - char name[ACPI_ID_LEN + 4]; - struct acpi_device *adev; - struct i2c_client *vcm_i2c_client; - - /* SWNODE_COUNT + 1 for terminating NULL */ - const struct software_node *group[SWNODE_COUNT + 1]; - struct software_node swnodes[SWNODE_COUNT]; - struct cio2_node_names node_names; - - struct cio2_sensor_ssdb ssdb; - struct acpi_pld_info *pld; - - struct cio2_property_names prop_names; - struct property_entry ep_properties[5]; - struct property_entry dev_properties[5]; - struct property_entry cio2_properties[3]; - struct software_node_ref_args local_ref[1]; - struct software_node_ref_args remote_ref[1]; - struct software_node_ref_args vcm_ref[1]; -}; - -struct cio2_bridge { - char cio2_node_name[ACPI_ID_LEN]; - struct software_node cio2_hid_node; - u32 data_lanes[4]; - unsigned int n_sensors; - struct cio2_sensor sensors[CIO2_NUM_PORTS]; -}; - -#endif diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 34984a7474ed..5dd69a251b6a 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -22,6 +22,8 @@ #include <linux/pm_runtime.h> #include <linux/property.h> #include <linux/vmalloc.h> + +#include <media/ipu-bridge.h> #include <media/v4l2-ctrls.h> #include <media/v4l2-device.h> #include <media/v4l2-event.h> @@ -354,7 +356,7 @@ static int cio2_hw_init(struct cio2_device *cio2, struct cio2_queue *q) void __iomem *const base = cio2->base; u8 lanes, csi2bus = q->csi2.port; u8 sensor_vc = SENSOR_VIR_CH_DFLT; - struct cio2_csi2_timing timing; + struct cio2_csi2_timing timing = { 0 }; int i, r; fmt = cio2_find_format(NULL, &q->subdev_fmt.code); @@ -1371,7 +1373,7 @@ static const struct v4l2_subdev_ops cio2_subdev_ops = { /******* V4L2 sub-device asynchronous registration callbacks***********/ struct sensor_async_subdev { - struct v4l2_async_subdev asd; + struct v4l2_async_connection asd; struct csi2_bus_info csi2; }; @@ -1381,15 +1383,20 @@ struct sensor_async_subdev { /* The .bound() notifier callback when a match is found */ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct cio2_device *cio2 = to_cio2_device(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); struct cio2_queue *q; + int ret; if (cio2->queue[s_asd->csi2.port].sensor) return -EBUSY; + ret = ipu_bridge_instantiate_vcm(sd->dev); + if (ret) + return ret; + q = &cio2->queue[s_asd->csi2.port]; q->csi2 = s_asd->csi2; @@ -1402,7 +1409,7 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier, /* The .unbind callback */ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, - struct v4l2_async_subdev *asd) + struct v4l2_async_connection *asd) { struct cio2_device *cio2 = to_cio2_device(notifier); struct sensor_async_subdev *s_asd = to_sensor_asd(asd); @@ -1416,11 +1423,11 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) struct cio2_device *cio2 = to_cio2_device(notifier); struct device *dev = &cio2->pci_dev->dev; struct sensor_async_subdev *s_asd; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct cio2_queue *q; int ret; - list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) { + list_for_each_entry(asd, &cio2->notifier.done_list, asc_entry) { s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; @@ -1499,7 +1506,7 @@ err_parse: * suspend. */ cio2->notifier.ops = &cio2_async_ops; - ret = v4l2_async_nf_register(&cio2->v4l2_dev, &cio2->notifier); + ret = v4l2_async_nf_register(&cio2->notifier); if (ret) dev_err(dev, "failed to register async notifier : %d\n", ret); @@ -1724,7 +1731,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, return -EINVAL; } - r = cio2_bridge_init(pci_dev); + r = ipu_bridge_init(dev, ipu_bridge_parse_ssdb); if (r) return r; } @@ -1794,7 +1801,7 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, if (r) goto fail_v4l2_device_unregister; - v4l2_async_nf_init(&cio2->notifier); + v4l2_async_nf_init(&cio2->notifier, &cio2->v4l2_dev); /* Register notifier for subdevices we care */ r = cio2_parse_firmware(cio2); @@ -2057,3 +2064,4 @@ MODULE_AUTHOR("Yuning Pu <yuning.pu@intel.com>"); MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("IPU3 CIO2 driver"); +MODULE_IMPORT_NS(INTEL_IPU_BRIDGE); diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h index 3a1f394e05aa..d731ce8adbe3 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h @@ -459,10 +459,4 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq) return container_of(vq, struct cio2_queue, vbq); } -#if IS_ENABLED(CONFIG_CIO2_BRIDGE) -int cio2_bridge_init(struct pci_dev *cio2); -#else -static inline int cio2_bridge_init(struct pci_dev *cio2) { return 0; } -#endif - #endif |