summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/intel
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/intel')
-rw-r--r--drivers/media/pci/intel/ipu-bridge.c92
-rw-r--r--drivers/media/pci/intel/ipu3/ipu3-cio2.c53
-rw-r--r--drivers/media/pci/intel/ivsc/mei_csi.c83
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,