@@ -35,6 +35,8 @@ source "drivers/media/platform/omap/Kconfig"
source "drivers/media/platform/blackfin/Kconfig"
+source "drivers/media/platform/imx/Kconfig"
+
config VIDEO_SH_VOU
tristate "SuperH VOU video output driver"
depends on MEDIA_CAMERA_SUPPORT
@@ -1,3 +1,16 @@
+config MEDIA_IMX
+ tristate "Multimedia Support for Freescale i.MX"
+ depends on MEDIA_CONTROLLER
+ ---help---
+ This driver provides a SoC wide media controller device that all
+ multimedia components in i.MX5 and i.MX6 SoCs can register with.
+
+config MEDIA_IMX_IPU
+ tristate "i.MX Image Processing Unit (v3) core driver"
+ ---help---
+ This driver provides core support for the i.MX IPUv3 contained in
+ i.MX5 and i.MX6 SoCs.
+
config VIDEO_IMX_IPU_COMMON
tristate
@@ -1,3 +1,4 @@
+obj-$(CONFIG_MEDIA_IMX) += imx-media.o
obj-$(CONFIG_VIDEO_IMX_IPU_COMMON) += imx-ipu.o
obj-$(CONFIG_VIDEO_IMX_IPU_SCALER) += imx-ipu-scaler.o
obj-$(CONFIG_VIDEO_IMX_IPU_VDIC) += imx-ipu-vdic.o
new file mode 100644
@@ -0,0 +1,174 @@
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <media/media-device.h>
+#include <media/v4l2-device.h>
+#include <video/imx-ipu-v3.h>
+
+struct ipu_media_controller {
+ struct v4l2_device v4l2_dev;
+ struct media_device mdev;
+};
+
+static struct ipu_media_controller *ipu_media;
+
+struct media_device *ipu_find_media_device(void)
+{
+ return &ipu_media->mdev;
+}
+EXPORT_SYMBOL_GPL(ipu_find_media_device);
+
+struct ipu_media_link {
+ struct v4l2_async_notifier asn;
+ struct v4l2_async_subdev asd;
+ struct v4l2_async_subdev *asdp;
+ struct v4l2_subdev *sd;
+ int padno;
+ struct device_node *endpoint;
+ u32 media_link_flags;
+};
+
+static int ipu_media_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ struct ipu_media_controller *im = ipu_media;
+ struct ipu_media_link *link = container_of(notifier,
+ struct ipu_media_link, asn);
+ struct device_node *np, *rp;
+ uint32_t portno = 0;
+ int ret;
+
+ if ((sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) {
+ ret = v4l2_device_register_subdev_node(&im->v4l2_dev, sd);
+ if (ret)
+ return ret;
+ }
+
+ np = link->endpoint;
+ rp = of_graph_get_remote_port(np);
+ of_property_read_u32(rp, "reg", &portno);
+
+ ret = media_entity_create_link(&sd->entity, portno, &link->sd->entity,
+ link->padno, link->media_link_flags);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void ipu_media_unbind(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+ if ((sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE)) {
+ video_unregister_device(sd->devnode);
+ kfree(sd->devnode);
+ }
+}
+
+struct ipu_media_link *ipu_media_entity_create_link(struct v4l2_subdev *sd,
+ int padno, struct device_node *endpoint,
+ u32 media_link_flags)
+{
+ struct ipu_media_controller *im = ipu_media;
+ struct ipu_media_link *link;
+ int ret;
+ struct device_node *rpp;
+
+ rpp = of_graph_get_remote_port_parent(endpoint);
+ if (!rpp)
+ return ERR_PTR(-EINVAL);
+
+ pr_info("%s: link on %s pad %d endpoint: %s remotenodeparent: %s\n",
+ __func__, sd->name, padno, endpoint->full_name, rpp->full_name);
+ if (!im)
+ return ERR_PTR(-ENODEV);
+
+ link = kzalloc(sizeof(*link), GFP_KERNEL);
+ if (!link)
+ return ERR_PTR(-ENOMEM);
+
+ link->sd = sd;
+ link->padno = padno;
+ link->endpoint = endpoint;
+ link->media_link_flags = media_link_flags;
+
+ link->asd.match_type = V4L2_ASYNC_MATCH_OF;
+ link->asd.match.of.node = rpp;
+
+ link->asdp = &link->asd;
+
+ link->asn.bound = ipu_media_bound;
+ link->asn.unbind = ipu_media_unbind;
+ link->asn.subdevs = &link->asdp;
+ link->asn.num_subdevs = 1;
+ link->asn.v4l2_dev = &im->v4l2_dev;
+
+ ret = v4l2_async_notifier_register(&im->v4l2_dev, &link->asn);
+ if (ret) {
+ kfree(link);
+ return ERR_PTR(ret);
+ }
+
+ return link;
+}
+EXPORT_SYMBOL_GPL(ipu_media_entity_create_link);
+
+void ipu_media_entity_remove_link(struct ipu_media_link *link)
+{
+ v4l2_async_notifier_unregister(&link->asn);
+
+ kfree(link);
+}
+EXPORT_SYMBOL_GPL(ipu_media_entity_remove_link);
+
+struct v4l2_device *ipu_media_get_v4l2_dev(void)
+{
+ if (!ipu_media)
+ return NULL;
+
+ return &ipu_media->v4l2_dev;
+}
+EXPORT_SYMBOL_GPL(ipu_media_get_v4l2_dev);
+
+int ipu_media_device_register(struct device *dev)
+{
+ struct media_device *mdev;
+ int ret;
+
+ if (ipu_media)
+ return 0;
+
+ ipu_media = devm_kzalloc(dev, sizeof(*ipu_media), GFP_KERNEL);
+ if (!ipu_media)
+ return -ENOMEM;
+
+ mdev = &ipu_media->mdev;
+
+ mdev->dev = dev;
+
+ strlcpy(mdev->model, "i.MX IPUv3", sizeof(mdev->model));
+
+ ret = media_device_register(mdev);
+ if (ret)
+ return ret;
+
+ ipu_media->v4l2_dev.mdev = mdev;
+
+ ret = v4l2_device_register(mdev->dev, &ipu_media->v4l2_dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_media_device_register);
new file mode 100644
@@ -0,0 +1,25 @@
+struct v4l2_subdev;
+struct device_node;
+struct ipu_media_link;
+struct v4l2_device;
+struct media_device;
+struct device;
+
+struct ipu_media_link *ipu_media_entity_create_link(struct v4l2_subdev *sd,
+ int padno, struct device_node *remote_node,
+ u32 media_link_flags);
+
+void ipu_media_entity_remove_link(struct ipu_media_link *link);
+
+struct v4l2_device *ipu_media_get_v4l2_dev(void);
+
+struct media_device *ipu_find_media_device(void);
+
+#ifdef CONFIG_MEDIA_IMX
+int ipu_media_device_register(struct device *dev);
+#else
+static inline int ipu_media_device_register(struct device *dev)
+{
+ return 0;
+}
+#endif
This driver registers a single, SoC wide media device, which all entities in the media graph can be registered with via OF graph bindings. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> --- drivers/media/platform/Kconfig | 2 + drivers/media/platform/imx/Kconfig | 13 +++ drivers/media/platform/imx/Makefile | 1 + drivers/media/platform/imx/imx-media.c | 174 +++++++++++++++++++++++++++++++++ include/media/imx.h | 25 +++++ 5 files changed, 215 insertions(+) create mode 100644 drivers/media/platform/imx/imx-media.c create mode 100644 include/media/imx.h