|
@@ -15,15 +15,14 @@
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
+#include <linux/component.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <media/media-device.h>
|
|
|
#include <media/v4l2-device.h>
|
|
|
|
|
|
-#include "vimc-capture.h"
|
|
|
#include "vimc-common.h"
|
|
|
-#include "vimc-sensor.h"
|
|
|
|
|
|
#define VIMC_PDEV_NAME "vimc"
|
|
|
#define VIMC_MDEV_MODEL_NAME "VIMC MDEV"
|
|
@@ -37,10 +36,10 @@
|
|
|
}
|
|
|
|
|
|
struct vimc_device {
|
|
|
- /*
|
|
|
- * The pipeline configuration
|
|
|
- * (filled before calling vimc_device_register)
|
|
|
- */
|
|
|
+ /* The platform device */
|
|
|
+ struct platform_device pdev;
|
|
|
+
|
|
|
+ /* The pipeline configuration */
|
|
|
const struct vimc_pipeline_config *pipe_cfg;
|
|
|
|
|
|
/* The Associated media_device parent */
|
|
@@ -49,43 +48,14 @@ struct vimc_device {
|
|
|
/* Internal v4l2 parent device*/
|
|
|
struct v4l2_device v4l2_dev;
|
|
|
|
|
|
- /* Internal topology */
|
|
|
- struct vimc_ent_device **ved;
|
|
|
-};
|
|
|
-
|
|
|
-/**
|
|
|
- * enum vimc_ent_node - Select the functionality of a node in the topology
|
|
|
- * @VIMC_ENT_NODE_SENSOR: A node of type SENSOR simulates a camera sensor
|
|
|
- * generating internal images in bayer format and
|
|
|
- * propagating those images through the pipeline
|
|
|
- * @VIMC_ENT_NODE_CAPTURE: A node of type CAPTURE is a v4l2 video_device
|
|
|
- * that exposes the received image from the
|
|
|
- * pipeline to the user space
|
|
|
- * @VIMC_ENT_NODE_INPUT: A node of type INPUT is a v4l2 video_device that
|
|
|
- * receives images from the user space and
|
|
|
- * propagates them through the pipeline
|
|
|
- * @VIMC_ENT_NODE_DEBAYER: A node type DEBAYER expects to receive a frame
|
|
|
- * in bayer format converts it to RGB
|
|
|
- * @VIMC_ENT_NODE_SCALER: A node of type SCALER scales the received image
|
|
|
- * by a given multiplier
|
|
|
- *
|
|
|
- * This enum is used in the entity configuration struct to allow the definition
|
|
|
- * of a custom topology specifying the role of each node on it.
|
|
|
- */
|
|
|
-enum vimc_ent_node {
|
|
|
- VIMC_ENT_NODE_SENSOR,
|
|
|
- VIMC_ENT_NODE_CAPTURE,
|
|
|
- VIMC_ENT_NODE_INPUT,
|
|
|
- VIMC_ENT_NODE_DEBAYER,
|
|
|
- VIMC_ENT_NODE_SCALER,
|
|
|
+ /* Subdevices */
|
|
|
+ struct platform_device **subdevs;
|
|
|
};
|
|
|
|
|
|
/* Structure which describes individual configuration for each entity */
|
|
|
struct vimc_ent_config {
|
|
|
const char *name;
|
|
|
- size_t pads_qty;
|
|
|
- const unsigned long *pads_flag;
|
|
|
- enum vimc_ent_node node;
|
|
|
+ const char *drv;
|
|
|
};
|
|
|
|
|
|
/* Structure which describes links between entities */
|
|
@@ -112,60 +82,40 @@ struct vimc_pipeline_config {
|
|
|
static const struct vimc_ent_config ent_config[] = {
|
|
|
{
|
|
|
.name = "Sensor A",
|
|
|
- .pads_qty = 1,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SOURCE},
|
|
|
- .node = VIMC_ENT_NODE_SENSOR,
|
|
|
+ .drv = "vimc-sensor",
|
|
|
},
|
|
|
{
|
|
|
.name = "Sensor B",
|
|
|
- .pads_qty = 1,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SOURCE},
|
|
|
- .node = VIMC_ENT_NODE_SENSOR,
|
|
|
+ .drv = "vimc-sensor",
|
|
|
},
|
|
|
{
|
|
|
.name = "Debayer A",
|
|
|
- .pads_qty = 2,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SINK,
|
|
|
- MEDIA_PAD_FL_SOURCE},
|
|
|
- .node = VIMC_ENT_NODE_DEBAYER,
|
|
|
+ .drv = "vimc-debayer",
|
|
|
},
|
|
|
{
|
|
|
.name = "Debayer B",
|
|
|
- .pads_qty = 2,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SINK,
|
|
|
- MEDIA_PAD_FL_SOURCE},
|
|
|
- .node = VIMC_ENT_NODE_DEBAYER,
|
|
|
+ .drv = "vimc-debayer",
|
|
|
},
|
|
|
{
|
|
|
.name = "Raw Capture 0",
|
|
|
- .pads_qty = 1,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SINK},
|
|
|
- .node = VIMC_ENT_NODE_CAPTURE,
|
|
|
+ .drv = "vimc-capture",
|
|
|
},
|
|
|
{
|
|
|
.name = "Raw Capture 1",
|
|
|
- .pads_qty = 1,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SINK},
|
|
|
- .node = VIMC_ENT_NODE_CAPTURE,
|
|
|
+ .drv = "vimc-capture",
|
|
|
},
|
|
|
{
|
|
|
.name = "RGB/YUV Input",
|
|
|
- .pads_qty = 1,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SOURCE},
|
|
|
- .node = VIMC_ENT_NODE_INPUT,
|
|
|
+ /* TODO: change this to vimc-input when it is implemented */
|
|
|
+ .drv = "vimc-sensor",
|
|
|
},
|
|
|
{
|
|
|
.name = "Scaler",
|
|
|
- .pads_qty = 2,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SINK,
|
|
|
- MEDIA_PAD_FL_SOURCE},
|
|
|
- .node = VIMC_ENT_NODE_SCALER,
|
|
|
+ .drv = "vimc-scaler",
|
|
|
},
|
|
|
{
|
|
|
.name = "RGB/YUV Capture",
|
|
|
- .pads_qty = 1,
|
|
|
- .pads_flag = (const unsigned long[]){MEDIA_PAD_FL_SINK},
|
|
|
- .node = VIMC_ENT_NODE_CAPTURE,
|
|
|
+ .drv = "vimc-capture",
|
|
|
},
|
|
|
};
|
|
|
|
|
@@ -197,111 +147,40 @@ static const struct vimc_pipeline_config pipe_cfg = {
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
-static void vimc_device_unregister(struct vimc_device *vimc)
|
|
|
+static int vimc_create_links(struct vimc_device *vimc)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
-
|
|
|
- media_device_unregister(&vimc->mdev);
|
|
|
- /* Cleanup (only initialized) entities */
|
|
|
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
|
|
|
- if (vimc->ved[i] && vimc->ved[i]->destroy)
|
|
|
- vimc->ved[i]->destroy(vimc->ved[i]);
|
|
|
-
|
|
|
- vimc->ved[i] = NULL;
|
|
|
- }
|
|
|
- v4l2_device_unregister(&vimc->v4l2_dev);
|
|
|
- media_device_cleanup(&vimc->mdev);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * TODO: remove this function when all the
|
|
|
- * entities specific code are implemented
|
|
|
- */
|
|
|
-static void vimc_raw_destroy(struct vimc_ent_device *ved)
|
|
|
-{
|
|
|
- media_device_unregister_entity(ved->ent);
|
|
|
-
|
|
|
- media_entity_cleanup(ved->ent);
|
|
|
-
|
|
|
- vimc_pads_cleanup(ved->pads);
|
|
|
-
|
|
|
- kfree(ved->ent);
|
|
|
-
|
|
|
- kfree(ved);
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * TODO: remove this function when all the
|
|
|
- * entities specific code are implemented
|
|
|
- */
|
|
|
-static struct vimc_ent_device *vimc_raw_create(struct v4l2_device *v4l2_dev,
|
|
|
- const char *const name,
|
|
|
- u16 num_pads,
|
|
|
- const unsigned long *pads_flag)
|
|
|
-{
|
|
|
- struct vimc_ent_device *ved;
|
|
|
int ret;
|
|
|
|
|
|
- /* Allocate the main ved struct */
|
|
|
- ved = kzalloc(sizeof(*ved), GFP_KERNEL);
|
|
|
- if (!ved)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
-
|
|
|
- /* Allocate the media entity */
|
|
|
- ved->ent = kzalloc(sizeof(*ved->ent), GFP_KERNEL);
|
|
|
- if (!ved->ent) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto err_free_ved;
|
|
|
- }
|
|
|
-
|
|
|
- /* Allocate the pads */
|
|
|
- ved->pads = vimc_pads_init(num_pads, pads_flag);
|
|
|
- if (IS_ERR(ved->pads)) {
|
|
|
- ret = PTR_ERR(ved->pads);
|
|
|
- goto err_free_ent;
|
|
|
+ /* Initialize the links between entities */
|
|
|
+ for (i = 0; i < vimc->pipe_cfg->num_links; i++) {
|
|
|
+ const struct vimc_ent_link *link = &vimc->pipe_cfg->links[i];
|
|
|
+ /*
|
|
|
+ * TODO: Check another way of retrieving ved struct without
|
|
|
+ * relying on platform_get_drvdata
|
|
|
+ */
|
|
|
+ struct vimc_ent_device *ved_src =
|
|
|
+ platform_get_drvdata(vimc->subdevs[link->src_ent]);
|
|
|
+ struct vimc_ent_device *ved_sink =
|
|
|
+ platform_get_drvdata(vimc->subdevs[link->sink_ent]);
|
|
|
+
|
|
|
+ ret = media_create_pad_link(ved_src->ent, link->src_pad,
|
|
|
+ ved_sink->ent, link->sink_pad,
|
|
|
+ link->flags);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
- /* Initialize the media entity */
|
|
|
- ved->ent->name = name;
|
|
|
- ved->ent->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
|
|
|
- ret = media_entity_pads_init(ved->ent, num_pads, ved->pads);
|
|
|
- if (ret)
|
|
|
- goto err_cleanup_pads;
|
|
|
-
|
|
|
- /* Register the media entity */
|
|
|
- ret = media_device_register_entity(v4l2_dev->mdev, ved->ent);
|
|
|
- if (ret)
|
|
|
- goto err_cleanup_entity;
|
|
|
-
|
|
|
- /* Fill out the destroy function and return */
|
|
|
- ved->destroy = vimc_raw_destroy;
|
|
|
- return ved;
|
|
|
-
|
|
|
-err_cleanup_entity:
|
|
|
- media_entity_cleanup(ved->ent);
|
|
|
-err_cleanup_pads:
|
|
|
- vimc_pads_cleanup(ved->pads);
|
|
|
-err_free_ent:
|
|
|
- kfree(ved->ent);
|
|
|
-err_free_ved:
|
|
|
- kfree(ved);
|
|
|
-
|
|
|
- return ERR_PTR(ret);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-static int vimc_device_register(struct vimc_device *vimc)
|
|
|
+static int vimc_comp_bind(struct device *master)
|
|
|
{
|
|
|
- unsigned int i;
|
|
|
+ struct vimc_device *vimc = container_of(to_platform_device(master),
|
|
|
+ struct vimc_device, pdev);
|
|
|
int ret;
|
|
|
|
|
|
- /* Allocate memory for the vimc_ent_devices pointers */
|
|
|
- vimc->ved = devm_kcalloc(vimc->mdev.dev, vimc->pipe_cfg->num_ents,
|
|
|
- sizeof(*vimc->ved), GFP_KERNEL);
|
|
|
- if (!vimc->ved)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- /* Link the media device within the v4l2_device */
|
|
|
- vimc->v4l2_dev.mdev = &vimc->mdev;
|
|
|
+ dev_dbg(master, "bind");
|
|
|
|
|
|
/* Register the v4l2 struct */
|
|
|
ret = v4l2_device_register(vimc->mdev.dev, &vimc->v4l2_dev);
|
|
@@ -311,66 +190,22 @@ static int vimc_device_register(struct vimc_device *vimc)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- /* Initialize entities */
|
|
|
- for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
|
|
|
- struct vimc_ent_device *(*create_func)(struct v4l2_device *,
|
|
|
- const char *const,
|
|
|
- u16,
|
|
|
- const unsigned long *);
|
|
|
-
|
|
|
- /* Register the specific node */
|
|
|
- switch (vimc->pipe_cfg->ents[i].node) {
|
|
|
- case VIMC_ENT_NODE_SENSOR:
|
|
|
- create_func = vimc_sen_create;
|
|
|
- break;
|
|
|
-
|
|
|
- case VIMC_ENT_NODE_CAPTURE:
|
|
|
- create_func = vimc_cap_create;
|
|
|
- break;
|
|
|
-
|
|
|
- /* TODO: Instantiate the specific topology node */
|
|
|
- case VIMC_ENT_NODE_INPUT:
|
|
|
- case VIMC_ENT_NODE_DEBAYER:
|
|
|
- case VIMC_ENT_NODE_SCALER:
|
|
|
- default:
|
|
|
- /*
|
|
|
- * TODO: remove this when all the entities specific
|
|
|
- * code are implemented
|
|
|
- */
|
|
|
- create_func = vimc_raw_create;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- vimc->ved[i] = create_func(&vimc->v4l2_dev,
|
|
|
- vimc->pipe_cfg->ents[i].name,
|
|
|
- vimc->pipe_cfg->ents[i].pads_qty,
|
|
|
- vimc->pipe_cfg->ents[i].pads_flag);
|
|
|
- if (IS_ERR(vimc->ved[i])) {
|
|
|
- ret = PTR_ERR(vimc->ved[i]);
|
|
|
- vimc->ved[i] = NULL;
|
|
|
- goto err;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Initialize the links between entities */
|
|
|
- for (i = 0; i < vimc->pipe_cfg->num_links; i++) {
|
|
|
- const struct vimc_ent_link *link = &vimc->pipe_cfg->links[i];
|
|
|
+ /* Bind subdevices */
|
|
|
+ ret = component_bind_all(master, &vimc->v4l2_dev);
|
|
|
+ if (ret)
|
|
|
+ goto err_v4l2_unregister;
|
|
|
|
|
|
- ret = media_create_pad_link(vimc->ved[link->src_ent]->ent,
|
|
|
- link->src_pad,
|
|
|
- vimc->ved[link->sink_ent]->ent,
|
|
|
- link->sink_pad,
|
|
|
- link->flags);
|
|
|
- if (ret)
|
|
|
- goto err;
|
|
|
- }
|
|
|
+ /* Initialize links */
|
|
|
+ ret = vimc_create_links(vimc);
|
|
|
+ if (ret)
|
|
|
+ goto err_comp_unbind_all;
|
|
|
|
|
|
/* Register the media device */
|
|
|
ret = media_device_register(&vimc->mdev);
|
|
|
if (ret) {
|
|
|
dev_err(vimc->mdev.dev,
|
|
|
"media device register failed (err=%d)\n", ret);
|
|
|
- return ret;
|
|
|
+ goto err_comp_unbind_all;
|
|
|
}
|
|
|
|
|
|
/* Expose all subdev's nodes*/
|
|
@@ -379,32 +214,106 @@ static int vimc_device_register(struct vimc_device *vimc)
|
|
|
dev_err(vimc->mdev.dev,
|
|
|
"vimc subdev nodes registration failed (err=%d)\n",
|
|
|
ret);
|
|
|
- goto err;
|
|
|
+ goto err_mdev_unregister;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
-err:
|
|
|
- /* Destroy the so far created topology */
|
|
|
- vimc_device_unregister(vimc);
|
|
|
+err_mdev_unregister:
|
|
|
+ media_device_unregister(&vimc->mdev);
|
|
|
+err_comp_unbind_all:
|
|
|
+ component_unbind_all(master, NULL);
|
|
|
+err_v4l2_unregister:
|
|
|
+ v4l2_device_unregister(&vimc->v4l2_dev);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void vimc_comp_unbind(struct device *master)
|
|
|
+{
|
|
|
+ struct vimc_device *vimc = container_of(to_platform_device(master),
|
|
|
+ struct vimc_device, pdev);
|
|
|
+
|
|
|
+ dev_dbg(master, "unbind");
|
|
|
+
|
|
|
+ media_device_unregister(&vimc->mdev);
|
|
|
+ component_unbind_all(master, NULL);
|
|
|
+ v4l2_device_unregister(&vimc->v4l2_dev);
|
|
|
+}
|
|
|
+
|
|
|
+static int vimc_comp_compare(struct device *comp, void *data)
|
|
|
+{
|
|
|
+ const struct platform_device *pdev = to_platform_device(comp);
|
|
|
+ const char *name = data;
|
|
|
+
|
|
|
+ return !strcmp(pdev->dev.platform_data, name);
|
|
|
+}
|
|
|
+
|
|
|
+static struct component_match *vimc_add_subdevs(struct vimc_device *vimc)
|
|
|
+{
|
|
|
+ struct component_match *match = NULL;
|
|
|
+ struct vimc_platform_data pdata;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < vimc->pipe_cfg->num_ents; i++) {
|
|
|
+ dev_dbg(&vimc->pdev.dev, "new pdev for %s\n",
|
|
|
+ vimc->pipe_cfg->ents[i].drv);
|
|
|
+
|
|
|
+ strlcpy(pdata.entity_name, vimc->pipe_cfg->ents[i].name,
|
|
|
+ sizeof(pdata.entity_name));
|
|
|
+
|
|
|
+ vimc->subdevs[i] = platform_device_register_data(&vimc->pdev.dev,
|
|
|
+ vimc->pipe_cfg->ents[i].drv,
|
|
|
+ PLATFORM_DEVID_AUTO,
|
|
|
+ &pdata,
|
|
|
+ sizeof(pdata));
|
|
|
+ if (!vimc->subdevs[i]) {
|
|
|
+ while (--i >= 0)
|
|
|
+ platform_device_unregister(vimc->subdevs[i]);
|
|
|
+
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+ }
|
|
|
+
|
|
|
+ component_match_add(&vimc->pdev.dev, &match, vimc_comp_compare,
|
|
|
+ (void *)vimc->pipe_cfg->ents[i].name);
|
|
|
+ }
|
|
|
+
|
|
|
+ return match;
|
|
|
+}
|
|
|
+
|
|
|
+static void vimc_rm_subdevs(struct vimc_device *vimc)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ for (i = 0; i < vimc->pipe_cfg->num_ents; i++)
|
|
|
+ platform_device_unregister(vimc->subdevs[i]);
|
|
|
+}
|
|
|
+
|
|
|
+static const struct component_master_ops vimc_comp_ops = {
|
|
|
+ .bind = vimc_comp_bind,
|
|
|
+ .unbind = vimc_comp_unbind,
|
|
|
+};
|
|
|
+
|
|
|
static int vimc_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
- struct vimc_device *vimc;
|
|
|
+ struct vimc_device *vimc = container_of(pdev, struct vimc_device, pdev);
|
|
|
+ struct component_match *match = NULL;
|
|
|
int ret;
|
|
|
|
|
|
- /* Prepare the vimc topology structure */
|
|
|
+ dev_dbg(&pdev->dev, "probe");
|
|
|
|
|
|
- /* Allocate memory for the vimc structure */
|
|
|
- vimc = kzalloc(sizeof(*vimc), GFP_KERNEL);
|
|
|
- if (!vimc)
|
|
|
+ /* Create platform_device for each entity in the topology*/
|
|
|
+ vimc->subdevs = devm_kcalloc(&vimc->pdev.dev, vimc->pipe_cfg->num_ents,
|
|
|
+ sizeof(*vimc->subdevs), GFP_KERNEL);
|
|
|
+ if (!vimc->subdevs)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- /* Set the pipeline configuration struct */
|
|
|
- vimc->pipe_cfg = &pipe_cfg;
|
|
|
+ match = vimc_add_subdevs(vimc);
|
|
|
+ if (IS_ERR(match))
|
|
|
+ return PTR_ERR(match);
|
|
|
+
|
|
|
+ /* Link the media device within the v4l2_device */
|
|
|
+ vimc->v4l2_dev.mdev = &vimc->mdev;
|
|
|
|
|
|
/* Initialize media device */
|
|
|
strlcpy(vimc->mdev.model, VIMC_MDEV_MODEL_NAME,
|
|
@@ -412,28 +321,27 @@ static int vimc_probe(struct platform_device *pdev)
|
|
|
vimc->mdev.dev = &pdev->dev;
|
|
|
media_device_init(&vimc->mdev);
|
|
|
|
|
|
- /* Create vimc topology */
|
|
|
- ret = vimc_device_register(vimc);
|
|
|
+ /* Add self to the component system */
|
|
|
+ ret = component_master_add_with_match(&pdev->dev, &vimc_comp_ops,
|
|
|
+ match);
|
|
|
if (ret) {
|
|
|
- dev_err(vimc->mdev.dev,
|
|
|
- "vimc device registration failed (err=%d)\n", ret);
|
|
|
+ media_device_cleanup(&vimc->mdev);
|
|
|
+ vimc_rm_subdevs(vimc);
|
|
|
kfree(vimc);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- /* Link the topology object with the platform device object */
|
|
|
- platform_set_drvdata(pdev, vimc);
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static int vimc_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
- struct vimc_device *vimc = platform_get_drvdata(pdev);
|
|
|
+ struct vimc_device *vimc = container_of(pdev, struct vimc_device, pdev);
|
|
|
|
|
|
- /* Destroy all the topology */
|
|
|
- vimc_device_unregister(vimc);
|
|
|
- kfree(vimc);
|
|
|
+ dev_dbg(&pdev->dev, "remove");
|
|
|
+
|
|
|
+ component_master_del(&pdev->dev, &vimc_comp_ops);
|
|
|
+ vimc_rm_subdevs(vimc);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -442,9 +350,12 @@ static void vimc_dev_release(struct device *dev)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-static struct platform_device vimc_pdev = {
|
|
|
- .name = VIMC_PDEV_NAME,
|
|
|
- .dev.release = vimc_dev_release,
|
|
|
+static struct vimc_device vimc_dev = {
|
|
|
+ .pipe_cfg = &pipe_cfg,
|
|
|
+ .pdev = {
|
|
|
+ .name = VIMC_PDEV_NAME,
|
|
|
+ .dev.release = vimc_dev_release,
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
static struct platform_driver vimc_pdrv = {
|
|
@@ -459,29 +370,29 @@ static int __init vimc_init(void)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
- ret = platform_device_register(&vimc_pdev);
|
|
|
+ ret = platform_device_register(&vimc_dev.pdev);
|
|
|
if (ret) {
|
|
|
- dev_err(&vimc_pdev.dev,
|
|
|
+ dev_err(&vimc_dev.pdev.dev,
|
|
|
"platform device registration failed (err=%d)\n", ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
ret = platform_driver_register(&vimc_pdrv);
|
|
|
if (ret) {
|
|
|
- dev_err(&vimc_pdev.dev,
|
|
|
+ dev_err(&vimc_dev.pdev.dev,
|
|
|
"platform driver registration failed (err=%d)\n", ret);
|
|
|
-
|
|
|
- platform_device_unregister(&vimc_pdev);
|
|
|
+ platform_driver_unregister(&vimc_pdrv);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void __exit vimc_exit(void)
|
|
|
{
|
|
|
platform_driver_unregister(&vimc_pdrv);
|
|
|
|
|
|
- platform_device_unregister(&vimc_pdev);
|
|
|
+ platform_device_unregister(&vimc_dev.pdev);
|
|
|
}
|
|
|
|
|
|
module_init(vimc_init);
|