diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-07 13:11:40 +0000 |
commit | 8b0a8165cdad0f4133837d753649ef4682e42c3b (patch) | |
tree | 5c58f869f31ddb1f7bd6e8bdea269b680b36c5b6 /drivers/media/pci/intel | |
parent | Releasing progress-linux version 6.8.12-1~progress7.99u1. (diff) | |
download | linux-8b0a8165cdad0f4133837d753649ef4682e42c3b.tar.xz linux-8b0a8165cdad0f4133837d753649ef4682e42c3b.zip |
Merging upstream version 6.9.7.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/media/pci/intel')
-rw-r--r-- | drivers/media/pci/intel/ipu-bridge.c | 92 | ||||
-rw-r--r-- | drivers/media/pci/intel/ipu3/ipu3-cio2.c | 53 | ||||
-rw-r--r-- | drivers/media/pci/intel/ivsc/mei_csi.c | 83 |
3 files changed, 94 insertions, 134 deletions
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c index f980e3125a..61750cc98d 100644 --- a/drivers/media/pci/intel/ipu-bridge.c +++ b/drivers/media/pci/intel/ipu-bridge.c @@ -2,6 +2,7 @@ /* Author: Dan Scally <djrscally@gmail.com> */ #include <linux/acpi.h> +#include <linux/cleanup.h> #include <linux/device.h> #include <linux/i2c.h> #include <linux/mei_cl_bus.h> @@ -14,6 +15,8 @@ #include <media/ipu-bridge.h> #include <media/v4l2-fwnode.h> +#define ADEV_DEV(adev) ACPI_PTR(&((adev)->dev)) + /* * 92335fcf-3203-4472-af93-7b4453ac29da * @@ -60,6 +63,8 @@ static const struct ipu_sensor_config ipu_supported_sensors[] = { IPU_SENSOR_CONFIG("OVTIDB10", 1, 560000000), /* GalaxyCore GC0310 */ IPU_SENSOR_CONFIG("INT0310", 0), + /* Omnivision ov01a10 */ + IPU_SENSOR_CONFIG("OVTI01A0", 1, 400000000), }; static const struct ipu_property_names prop_names = { @@ -84,6 +89,7 @@ static const char * const ipu_vcm_types[] = { "lc898212axb", }; +#if IS_ENABLED(CONFIG_ACPI) /* * Used to figure out IVSC acpi device by ipu_bridge_get_ivsc_acpi_dev() * instead of device and driver match to probe IVSC device. @@ -97,13 +103,13 @@ static const struct acpi_device_id ivsc_acpi_ids[] = { static struct acpi_device *ipu_bridge_get_ivsc_acpi_dev(struct acpi_device *adev) { - acpi_handle handle = acpi_device_handle(adev); - struct acpi_device *consumer, *ivsc_adev; unsigned int i; for (i = 0; i < ARRAY_SIZE(ivsc_acpi_ids); i++) { const struct acpi_device_id *acpi_id = &ivsc_acpi_ids[i]; + struct acpi_device *consumer, *ivsc_adev; + acpi_handle handle = acpi_device_handle(adev); for_each_acpi_dev_match(ivsc_adev, acpi_id->id, NULL, -1) /* camera sensor depends on IVSC in DSDT if exist */ for_each_acpi_consumer_dev(ivsc_adev, consumer) @@ -115,6 +121,12 @@ static struct acpi_device *ipu_bridge_get_ivsc_acpi_dev(struct acpi_device *adev return NULL; } +#else +static struct acpi_device *ipu_bridge_get_ivsc_acpi_dev(struct acpi_device *adev) +{ + return NULL; +} +#endif static int ipu_bridge_match_ivsc_dev(struct device *dev, const void *adev) { @@ -160,7 +172,7 @@ static int ipu_bridge_check_ivsc_dev(struct ipu_sensor *sensor, csi_dev = ipu_bridge_get_ivsc_csi_dev(adev); if (!csi_dev) { acpi_dev_put(adev); - dev_err(&adev->dev, "Failed to find MEI CSI dev\n"); + dev_err(ADEV_DEV(adev), "Failed to find MEI CSI dev\n"); return -ENODEV; } @@ -179,24 +191,25 @@ static int ipu_bridge_read_acpi_buffer(struct acpi_device *adev, char *id, acpi_status status; int ret = 0; - status = acpi_evaluate_object(adev->handle, id, NULL, &buffer); + status = acpi_evaluate_object(ACPI_PTR(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"); + dev_err(ADEV_DEV(adev), "Couldn't locate ACPI buffer\n"); return -ENODEV; } if (obj->type != ACPI_TYPE_BUFFER) { - dev_err(&adev->dev, "Not an ACPI buffer\n"); + dev_err(ADEV_DEV(adev), "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"); + dev_err(ADEV_DEV(adev), "Given buffer is too small\n"); ret = -EINVAL; goto out_free_buff; } @@ -217,7 +230,7 @@ static u32 ipu_bridge_parse_rotation(struct acpi_device *adev, case IPU_SENSOR_ROTATION_INVERTED: return 180; default: - dev_warn(&adev->dev, + dev_warn(ADEV_DEV(adev), "Unknown rotation %d. Assume 0 degree rotation\n", ssdb->degree); return 0; @@ -227,12 +240,14 @@ static u32 ipu_bridge_parse_rotation(struct acpi_device *adev, static enum v4l2_fwnode_orientation ipu_bridge_parse_orientation(struct acpi_device *adev) { enum v4l2_fwnode_orientation orientation; - struct acpi_pld_info *pld; - acpi_status status; + struct acpi_pld_info *pld = NULL; + acpi_status status = AE_ERROR; +#if IS_ENABLED(CONFIG_ACPI) status = acpi_get_physical_device_location(adev->handle, &pld); +#endif if (ACPI_FAILURE(status)) { - dev_warn(&adev->dev, "_PLD call failed, using default orientation\n"); + dev_warn(ADEV_DEV(adev), "_PLD call failed, using default orientation\n"); return V4L2_FWNODE_ORIENTATION_EXTERNAL; } @@ -250,7 +265,8 @@ static enum v4l2_fwnode_orientation ipu_bridge_parse_orientation(struct acpi_dev orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; break; default: - dev_warn(&adev->dev, "Unknown _PLD panel val %d\n", pld->panel); + dev_warn(ADEV_DEV(adev), "Unknown _PLD panel val %d\n", + pld->panel); orientation = V4L2_FWNODE_ORIENTATION_EXTERNAL; break; } @@ -269,12 +285,12 @@ int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor) return ret; if (ssdb.vcmtype > ARRAY_SIZE(ipu_vcm_types)) { - dev_warn(&adev->dev, "Unknown VCM type %d\n", ssdb.vcmtype); + dev_warn(ADEV_DEV(adev), "Unknown VCM type %d\n", ssdb.vcmtype); ssdb.vcmtype = 0; } if (ssdb.lanes > IPU_MAX_LANES) { - dev_err(&adev->dev, "Number of lanes in SSDB is invalid\n"); + dev_err(ADEV_DEV(adev), "Number of lanes in SSDB is invalid\n"); return -EINVAL; } @@ -462,8 +478,14 @@ static void ipu_bridge_create_connection_swnodes(struct ipu_bridge *bridge, sensor->ipu_properties); if (sensor->csi_dev) { + const char *device_hid = ""; + +#if IS_ENABLED(CONFIG_ACPI) + device_hid = acpi_device_hid(sensor->ivsc_adev); +#endif + snprintf(sensor->ivsc_name, sizeof(sensor->ivsc_name), "%s-%u", - acpi_device_hid(sensor->ivsc_adev), sensor->link); + device_hid, sensor->link); nodes[SWNODE_IVSC_HID] = NODE_SENSOR(sensor->ivsc_name, sensor->ivsc_properties); @@ -628,11 +650,15 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg, { struct fwnode_handle *fwnode, *primary; struct ipu_sensor *sensor; - struct acpi_device *adev; + struct acpi_device *adev = NULL; int ret; +#if IS_ENABLED(CONFIG_ACPI) for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { - if (!adev->status.enabled) +#else + while (true) { +#endif + if (!ACPI_PTR(adev->status.enabled)) continue; if (bridge->n_sensors >= IPU_MAX_PORTS) { @@ -668,7 +694,7 @@ static int ipu_bridge_connect_sensor(const struct ipu_sensor_config *cfg, goto err_free_swnodes; } - sensor->adev = acpi_dev_get(adev); + sensor->adev = ACPI_PTR(acpi_dev_get(adev)); primary = acpi_fwnode_handle(adev); primary->secondary = fwnode; @@ -724,11 +750,16 @@ static int ipu_bridge_ivsc_is_ready(void) unsigned int i; for (i = 0; i < ARRAY_SIZE(ipu_supported_sensors); i++) { +#if IS_ENABLED(CONFIG_ACPI) const struct ipu_sensor_config *cfg = &ipu_supported_sensors[i]; for_each_acpi_dev_match(sensor_adev, cfg->hid, NULL, -1) { - if (!sensor_adev->status.enabled) +#else + while (true) { + sensor_adev = NULL; +#endif + if (!ACPI_PTR(sensor_adev->status.enabled)) continue; adev = ipu_bridge_get_ivsc_acpi_dev(sensor_adev); @@ -747,6 +778,24 @@ static int ipu_bridge_ivsc_is_ready(void) return ready; } +static int ipu_bridge_check_fwnode_graph(struct fwnode_handle *fwnode) +{ + struct fwnode_handle *endpoint; + + if (IS_ERR_OR_NULL(fwnode)) + return -EINVAL; + + endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (endpoint) { + fwnode_handle_put(endpoint); + return 0; + } + + return ipu_bridge_check_fwnode_graph(fwnode->secondary); +} + +static DEFINE_MUTEX(ipu_bridge_mutex); + int ipu_bridge_init(struct device *dev, ipu_parse_sensor_fwnode_t parse_sensor_fwnode) { @@ -755,6 +804,11 @@ int ipu_bridge_init(struct device *dev, unsigned int i; int ret; + guard(mutex)(&ipu_bridge_mutex); + + if (!ipu_bridge_check_fwnode_graph(dev_fwnode(dev))) + return 0; + if (!ipu_bridge_ivsc_is_ready()) return -EPROBE_DEFER; diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index d5478779b3..00090e7f5f 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -28,6 +28,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-event.h> #include <media/v4l2-fwnode.h> +#include <media/v4l2-mc.h> #include <media/v4l2-ioctl.h> #include <media/videobuf2-dma-sg.h> @@ -1407,7 +1408,6 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier, 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_connection *asd; struct cio2_queue *q; @@ -1417,23 +1417,10 @@ static int cio2_notifier_complete(struct v4l2_async_notifier *notifier) s_asd = to_sensor_asd(asd); q = &cio2->queue[s_asd->csi2.port]; - ret = media_entity_get_fwnode_pad(&q->sensor->entity, - s_asd->asd.match.fwnode, - MEDIA_PAD_FL_SOURCE); - if (ret < 0) { - dev_err(dev, "no pad for endpoint %pfw (%d)\n", - s_asd->asd.match.fwnode, ret); - return ret; - } - - ret = media_create_pad_link(&q->sensor->entity, ret, - &q->subdev.entity, CIO2_PAD_SINK, - 0); - if (ret) { - dev_err(dev, "failed to create link for %s (endpoint %pfw, error %d)\n", - q->sensor->name, s_asd->asd.match.fwnode, ret); + ret = v4l2_create_fwnode_links_to_pad(asd->sd, + &q->subdev_pads[CIO2_PAD_SINK], 0); + if (ret) return ret; - } } return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev); @@ -1572,6 +1559,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q) v4l2_subdev_init(subdev, &cio2_subdev_ops); subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; subdev->owner = THIS_MODULE; + subdev->dev = dev; snprintf(subdev->name, sizeof(subdev->name), CIO2_ENTITY_NAME " %td", q - cio2->queue); subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; @@ -1679,29 +1667,12 @@ static void cio2_queues_exit(struct cio2_device *cio2) cio2_queue_exit(cio2, &cio2->queue[i]); } -static int cio2_check_fwnode_graph(struct fwnode_handle *fwnode) -{ - struct fwnode_handle *endpoint; - - if (IS_ERR_OR_NULL(fwnode)) - return -EINVAL; - - endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); - if (endpoint) { - fwnode_handle_put(endpoint); - return 0; - } - - return cio2_check_fwnode_graph(fwnode->secondary); -} - /**************** PCI interface ****************/ static int cio2_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { struct device *dev = &pci_dev->dev; - struct fwnode_handle *fwnode = dev_fwnode(dev); struct cio2_device *cio2; int r; @@ -1710,17 +1681,9 @@ static int cio2_pci_probe(struct pci_dev *pci_dev, * if the device has no endpoints then we can try to build those as * software_nodes parsed from SSDB. */ - r = cio2_check_fwnode_graph(fwnode); - if (r) { - if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary)) { - dev_err(dev, "fwnode graph has no endpoints connected\n"); - return -EINVAL; - } - - r = ipu_bridge_init(dev, ipu_bridge_parse_ssdb); - if (r) - return r; - } + r = ipu_bridge_init(dev, ipu_bridge_parse_ssdb); + if (r) + return r; cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL); if (!cio2) diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c index 3c74d06a27..55e0c60c42 100644 --- a/drivers/media/pci/intel/ivsc/mei_csi.c +++ b/drivers/media/pci/intel/ivsc/mei_csi.c @@ -128,7 +128,6 @@ struct mei_csi { int streaming; struct media_pad pads[CSI_NUM_PADS]; - struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS]; /* number of data lanes used on the CSI-2 link */ u32 nr_of_lanes; @@ -329,58 +328,17 @@ err: return ret; } -static struct v4l2_mbus_framefmt * -mei_csi_get_pad_format(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - unsigned int pad, u32 which) -{ - struct mei_csi *csi = sd_to_csi(sd); - - switch (which) { - case V4L2_SUBDEV_FORMAT_TRY: - return v4l2_subdev_state_get_format(sd_state, pad); - case V4L2_SUBDEV_FORMAT_ACTIVE: - return &csi->format_mbus[pad]; - default: - return NULL; - } -} - static int mei_csi_init_state(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state) { struct v4l2_mbus_framefmt *mbusformat; - struct mei_csi *csi = sd_to_csi(sd); unsigned int i; - mutex_lock(&csi->lock); - for (i = 0; i < sd->entity.num_pads; i++) { mbusformat = v4l2_subdev_state_get_format(sd_state, i); *mbusformat = mei_csi_format_mbus_default; } - mutex_unlock(&csi->lock); - - return 0; -} - -static int mei_csi_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) -{ - struct v4l2_mbus_framefmt *mbusformat; - struct mei_csi *csi = sd_to_csi(sd); - - mutex_lock(&csi->lock); - - mbusformat = mei_csi_get_pad_format(sd, sd_state, format->pad, - format->which); - if (mbusformat) - format->format = *mbusformat; - - mutex_unlock(&csi->lock); - return 0; } @@ -388,20 +346,17 @@ static int mei_csi_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *sd_state, struct v4l2_subdev_format *format) { - struct v4l2_mbus_framefmt *source_mbusformat; - struct v4l2_mbus_framefmt *mbusformat; - struct mei_csi *csi = sd_to_csi(sd); - struct media_pad *pad; + struct v4l2_mbus_framefmt *source_fmt; + struct v4l2_mbus_framefmt *sink_fmt; - mbusformat = mei_csi_get_pad_format(sd, sd_state, format->pad, - format->which); - if (!mbusformat) - return -EINVAL; + sink_fmt = v4l2_subdev_state_get_format(sd_state, CSI_PAD_SINK); + source_fmt = v4l2_subdev_state_get_format(sd_state, CSI_PAD_SOURCE); - source_mbusformat = mei_csi_get_pad_format(sd, sd_state, CSI_PAD_SOURCE, - format->which); - if (!source_mbusformat) - return -EINVAL; + if (format->pad) { + *source_fmt = *sink_fmt; + + return 0; + } v4l_bound_align_image(&format->format.width, 1, 65536, 0, &format->format.height, 1, 65536, 0, 0); @@ -504,18 +459,8 @@ static int mei_csi_set_fmt(struct v4l2_subdev *sd, if (format->format.field == V4L2_FIELD_ANY) format->format.field = V4L2_FIELD_NONE; - mutex_lock(&csi->lock); - - pad = &csi->pads[format->pad]; - if (pad->flags & MEDIA_PAD_FL_SOURCE) - format->format = csi->format_mbus[CSI_PAD_SINK]; - - *mbusformat = format->format; - - if (pad->flags & MEDIA_PAD_FL_SINK) - *source_mbusformat = format->format; - - mutex_unlock(&csi->lock); + *sink_fmt = format->format; + *source_fmt = *sink_fmt; return 0; } @@ -554,7 +499,7 @@ static const struct v4l2_subdev_video_ops mei_csi_video_ops = { }; static const struct v4l2_subdev_pad_ops mei_csi_pad_ops = { - .get_fmt = mei_csi_get_fmt, + .get_fmt = v4l2_subdev_get_fmt, .set_fmt = mei_csi_set_fmt, }; @@ -749,6 +694,7 @@ static int mei_csi_probe(struct mei_cl_device *cldev, goto err_disable; csi->subdev.dev = &cldev->dev; + csi->subdev.state_lock = &csi->lock; v4l2_subdev_init(&csi->subdev, &mei_csi_subdev_ops); csi->subdev.internal_ops = &mei_csi_internal_ops; v4l2_set_subdevdata(&csi->subdev, csi); @@ -764,9 +710,6 @@ static int mei_csi_probe(struct mei_cl_device *cldev, if (ret) goto err_ctrl_handler; - csi->format_mbus[CSI_PAD_SOURCE] = mei_csi_format_mbus_default; - csi->format_mbus[CSI_PAD_SINK] = mei_csi_format_mbus_default; - csi->pads[CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; csi->pads[CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK; ret = media_entity_pads_init(&csi->subdev.entity, CSI_NUM_PADS, |