Re: [RFC 07/12] media: exynos5-is: Adding media device driver for exynos5

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Sylwester,

Thanks for the review.
I will address all you comments for this patch in the next version.

Thanks,
Shaik Ameer Basha

On Mon, Mar 11, 2013 at 3:58 AM, Sylwester Nawrocki
<sylvester.nawrocki@xxxxxxxxx> wrote:
> On 03/06/2013 12:53 PM, Shaik Ameer Basha wrote:
>>
>> This patch adds support for media device for EXYNOS5 SoCs.
>> The current media device supports the following ips to connect
>> through the media controller framework.
>>
>> * MIPI-CSIS
>>    Support interconnection(subdev interface) between devices
>>
>> * FIMC-LITE
>>    Support capture interface from device(Sensor, MIPI-CSIS) to memory
>>    Support interconnection(subdev interface) between devices
>>
>> G-Scaler will be added later to the current media device.
>>
>> * Gscaler: general scaler
>>    Support memory to memory interface
>>    Support output interface from memory to display device(LCD, TV)
>>    Support capture interface from device(FIMC-LITE, FIMD) to memory
>>
>> -->  media 0
>>    Camera Capture path consists of MIPI-CSIS, FIMC-LITE and G-Scaler
>>    +--------+     +-----------+     +-----------------+
>>    | Sensor | -->  | FIMC-LITE | -->  | G-Scaler-capture |
>>    +--------+     +-----------+     +-----------------+
>>
>>    +--------+     +-----------+     +-----------+     +-----------------+
>>    | Sensor | -->  | MIPI-CSIS | -->  | FIMC-LITE | -->  |
>> G-Scaler-capture |
>>    +--------+     +-----------+     +-----------+     +-----------------+
>>
>> Signed-off-by: Shaik Ameer Basha<shaik.ameer@xxxxxxxxxxx>
>> ---
>>   drivers/media/platform/Kconfig                   |    1 +
>>   drivers/media/platform/Makefile                  |    1 +
>>   drivers/media/platform/exynos5-is/Kconfig        |    7 +
>>   drivers/media/platform/exynos5-is/Makefile       |    4 +
>>   drivers/media/platform/exynos5-is/exynos5-mdev.c | 1309
>> ++++++++++++++++++++++
>>   drivers/media/platform/exynos5-is/exynos5-mdev.h |  107 ++
>>   6 files changed, 1429 insertions(+)
>>   create mode 100644 drivers/media/platform/exynos5-is/Kconfig
>>   create mode 100644 drivers/media/platform/exynos5-is/Makefile
>>   create mode 100644 drivers/media/platform/exynos5-is/exynos5-mdev.c
>>   create mode 100644 drivers/media/platform/exynos5-is/exynos5-mdev.h
>>
> ...
>
>> diff --git a/drivers/media/platform/exynos5-is/exynos5-mdev.c
>> b/drivers/media/platform/exynos5-is/exynos5-mdev.c
>> new file mode 100644
>> index 0000000..1158696
>> --- /dev/null
>> +++ b/drivers/media/platform/exynos5-is/exynos5-mdev.c
>> @@ -0,0 +1,1309 @@
>> +/*
>> + * S5P/EXYNOS4 SoC series camera host interface media device driver
>
>
> EXYNOS5
>
>
>> + * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
>> + * Sylwester Nawrocki<s.nawrocki@xxxxxxxxxxx>
>
>
> This is incorrect too, you should add your authorship and a note it
> is based on other code, with a proper copyright notice.
>
>
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published
>> + * by the Free Software Foundation, either version 2 of the License,
>> + * or (at your option) any later version.
>> + */
>> +
>> +#include<linux/bug.h>
>> +#include<linux/device.h>
>> +#include<linux/errno.h>
>> +#include<linux/i2c.h>
>> +#include<linux/kernel.h>
>> +#include<linux/list.h>
>> +#include<linux/module.h>
>> +#include<linux/of.h>
>> +#include<linux/of_platform.h>
>> +#include<linux/of_device.h>
>> +#include<linux/of_i2c.h>
>> +#include<linux/pinctrl/consumer.h>
>> +#include<linux/platform_device.h>
>> +#include<linux/pm_runtime.h>
>> +#include<linux/types.h>
>> +#include<linux/slab.h>
>> +#include<media/v4l2-ctrls.h>
>> +#include<media/v4l2-of.h>
>> +#include<media/media-device.h>
>> +
>> +#include "exynos5-mdev.h"
>> +
>> +#define dbg(fmt, args...) \
>> +       pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args)
>> +
>> +static struct fimc_md *g_exynos_mdev;
>> +
>> +static int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
>> +static int __fimc_md_set_camclk(struct fimc_md *fmd,
>> +                               struct fimc_sensor_info *s_info,
>> +                               bool on);
>> +/**
>> + * fimc_pipeline_prepare - update pipeline information with subdevice
>> pointers
>> + * @fimc: fimc device terminating the pipeline
>> + *
>> + * Caller holds the graph mutex.
>> + */
>> +static void fimc_pipeline_prepare(struct exynos5_pipeline0 *p,
>> +                                 struct media_entity *me)
>> +{
>> +       struct media_pad *pad =&me->pads[0];
>
>
> This will need to be changed to support subdevs with more than 2 pads.
> I should post relevant patch this week.
>
>> +       struct v4l2_subdev *sd;
>> +       int i;
>> +
>> +       for (i = 0; i<  IDX_MAX; i++)
>> +               p->subdevs[i] = NULL;
>> +
>> +       while (1) {
>> +
>> +               if (!(pad->flags&  MEDIA_PAD_FL_SINK))
>>
>> +                       break;
>> +
>> +               /* source pad */
>> +               pad = media_entity_remote_source(pad);
>> +
>> +               if (pad != NULL)
>> +                       pr_err("entity type: %d, entity name: %s\n",
>> +                           media_entity_type(pad->entity),
>> pad->entity->name);
>> +
>> +               if (pad == NULL ||
>> +                   media_entity_type(pad->entity) !=
>> MEDIA_ENT_T_V4L2_SUBDEV)
>> +                       break;
>> +
>> +               sd = media_entity_to_v4l2_subdev(pad->entity);
>> +
>> +               switch (sd->grp_id) {
>> +               case GRP_ID_FIMC_IS_SENSOR:
>> +               case GRP_ID_SENSOR:
>> +                       p->subdevs[IDX_SENSOR] = sd;
>> +                       break;
>> +               case GRP_ID_CSIS:
>> +                       p->subdevs[IDX_CSIS] = sd;
>> +                       break;
>> +               case GRP_ID_FLITE:
>> +                       p->subdevs[IDX_FLITE] = sd;
>> +                       break;
>> +               default:
>> +                       pr_warn("%s: Unknown subdev grp_id: %#x\n",
>> +                               __func__, sd->grp_id);
>> +               }
>> +
>> +               /* sink pad */
>> +               pad =&sd->entity.pads[0];
>> +       }
>> +}
>
> ...
>
>> +/*
>> + * Sensor subdevice helper functions
>> + */
>> +static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
>> +                                  struct fimc_sensor_info *s_info)
>> +{
>> +       struct i2c_adapter *adapter;
>> +       struct v4l2_subdev *sd = NULL;
>> +
>> +       if (!s_info || !fmd)
>> +               return NULL;
>> +
>> +       adapter = i2c_get_adapter(s_info->pdata.i2c_bus_num);
>> +       if (!adapter) {
>> +               v4l2_warn(&fmd->v4l2_dev,
>> +                         "Failed to get I2C adapter %d, deferring
>> probe\n",
>> +                         s_info->pdata.i2c_bus_num);
>> +               return ERR_PTR(-EPROBE_DEFER);
>> +       }
>> +       sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
>> +                                      s_info->pdata.board_info, NULL);
>> +       if (IS_ERR_OR_NULL(sd)) {
>> +               i2c_put_adapter(adapter);
>> +               v4l2_warn(&fmd->v4l2_dev,
>> +                         "Failed to acquire subdev %s, deferring
>> probe\n",
>> +                         s_info->pdata.board_info->type);
>> +               return ERR_PTR(-EPROBE_DEFER);
>> +       }
>> +       v4l2_set_subdev_hostdata(sd, s_info);
>> +       sd->grp_id = GRP_ID_SENSOR;
>> +
>> +       v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
>> +                 sd->name);
>> +       return sd;
>> +}
>> +
>> +static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
>> +{
>> +       struct i2c_client *client = v4l2_get_subdevdata(sd);
>> +       struct i2c_adapter *adapter;
>> +
>> +       if (!client)
>> +               return;
>> +       v4l2_device_unregister_subdev(sd);
>> +
>> +       if (!client->dev.of_node) {
>> +               adapter = client->adapter;
>> +               i2c_unregister_device(client);
>> +               if (adapter)
>> +                       i2c_put_adapter(adapter);
>> +       }
>> +}
>
>
> You don't need the above code which is for !CONFIG_OF only.
>
>> +#ifdef CONFIG_OF
>
>
> Just add "depends on OF" in Kconfig for the whole driver and
> you can drop all #ifdef CONFIG_OF.
>
>> +/* Register I2C client subdev associated with @node. */
>> +static int fimc_md_of_add_sensor(struct fimc_md *fmd,
>> +                                struct device_node *node, int index)
>> +{
>> +       struct fimc_sensor_info *si;
>> +       struct i2c_client *client;
>> +       struct v4l2_subdev *sd;
>> +       int ret;
>> +
>> +       if (WARN_ON(index>= ARRAY_SIZE(fmd->sensor)))
>> +               return -EINVAL;
>> +
>> +       si =&fmd->sensor[index];
>>
>> +
>> +       client = of_find_i2c_device_by_node(node);
>> +       if (!client)
>> +               return -EPROBE_DEFER;
>> +
>> +       device_lock(&client->dev);
>> +
>> +       if (!client->driver ||
>> +           !try_module_get(client->driver->driver.owner)) {
>> +               ret = -EPROBE_DEFER;
>> +               goto dev_put;
>> +       }
>> +
>> +       /* Enable sensor's master clock */
>> +       ret = __fimc_md_set_camclk(fmd, si, true);
>> +       if (ret<  0)
>> +               goto mod_put;
>> +
>> +       sd = i2c_get_clientdata(client);
>> +
>> +       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
>> +       __fimc_md_set_camclk(fmd, si, false);
>> +       if (ret<  0)
>> +               goto mod_put;
>> +
>> +       v4l2_set_subdev_hostdata(sd, si);
>> +       sd->grp_id = GRP_ID_SENSOR;
>> +       si->subdev = sd;
>> +       v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s
>> (%d)\n",
>> +                 sd->name, fmd->num_sensors);
>> +       fmd->num_sensors++;
>> +
>> +mod_put:
>> +       module_put(client->driver->driver.owner);
>> +dev_put:
>> +       device_unlock(&client->dev);
>> +       put_device(&client->dev);
>> +       return ret;
>> +}
>
> ...
>
>> +#else
>> +#define fimc_md_of_sensors_register(fmd, np) (-ENOSYS)
>
>
> This would never be used since Exynos5 is a dt-only platform.
>
>
>> +#endif
>> +
>> +static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
>> +{
>> +       struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
>> +       struct device_node *of_node = fmd->pdev->dev.of_node;
>> +       int num_clients = 0;
>> +       int ret, i;
>> +
>> +       if (of_node) {
>> +               fmd->num_sensors = 0;
>> +               ret = fimc_md_of_sensors_register(fmd, of_node);
>> +       } else if (pdata) {
>
>
> The code below is for !CONFIG_OF only, no need to repeat it for Exynos5.
>
>> +               WARN_ON(pdata->num_clients>  ARRAY_SIZE(fmd->sensor));
>> +               num_clients = min_t(u32, pdata->num_clients,
>> +                                   ARRAY_SIZE(fmd->sensor));
>> +               fmd->num_sensors = num_clients;
>> +
>> +               fmd->num_sensors = num_clients;
>> +               for (i = 0; i<  num_clients; i++) {
>> +                       struct v4l2_subdev *sd;
>> +
>> +                       fmd->sensor[i].pdata = pdata->source_info[i];
>> +                       ret = __fimc_md_set_camclk(fmd,&fmd->sensor[i],
>> true);
>>
>> +                       if (ret)
>> +                               break;
>> +                       sd = fimc_md_register_sensor(fmd,&fmd->sensor[i]);
>> +                       ret = __fimc_md_set_camclk(fmd,&fmd->sensor[i],
>> false);
>>
>> +
>> +                       if (IS_ERR(sd)) {
>> +                               fmd->sensor[i].subdev = NULL;
>> +                               ret = PTR_ERR(sd);
>> +                               break;
>> +                       }
>> +                       fmd->sensor[i].subdev = sd;
>> +                       if (ret)
>> +                               break;
>> +               }
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +/*
>> + * MIPI-CSIS, FIMC and FIMC-LITE platform devices registration.
>> + */
>> +
>> +static int register_fimc_lite_entity(struct fimc_md *fmd,
>> +                                    struct fimc_lite *fimc_lite)
>> +{
>> +       struct v4l2_subdev *sd;
>> +       int ret;
>> +
>> +       if (WARN_ON(fimc_lite->index>= FIMC_LITE_MAX_DEVS ||
>> +                   fmd->fimc_lite[fimc_lite->index]))
>> +               return -EBUSY;
>> +
>> +       sd =&fimc_lite->subdev;
>>
>> +       sd->grp_id = GRP_ID_FLITE;
>> +       v4l2_set_subdev_hostdata(sd, (void *)&exynos5_pipeline0_ops);
>> +
>> +       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
>> +       if (!ret)
>> +               fmd->fimc_lite[fimc_lite->index] = fimc_lite;
>> +       else
>> +               v4l2_err(&fmd->v4l2_dev, "Failed to register
>> FIMC.LITE%d\n",
>> +                        fimc_lite->index);
>> +       return ret;
>> +}
>> +
>> +static int register_csis_entity(struct fimc_md *fmd,
>> +                               struct platform_device *pdev,
>> +                               struct v4l2_subdev *sd)
>> +{
>> +       struct device_node *node = pdev->dev.of_node;
>> +       int id, ret;
>> +
>> +       id = node ? of_alias_get_id(node, "csis") : max(0, pdev->id);
>> +
>> +       if (WARN_ON(id>= CSIS_MAX_ENTITIES || fmd->csis[id].sd))
>> +               return -EBUSY;
>> +
>> +       if (WARN_ON(id>= CSIS_MAX_ENTITIES))
>> +               return 0;
>> +
>> +       sd->grp_id = GRP_ID_CSIS;
>> +       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
>> +       if (!ret)
>> +               fmd->csis[id].sd = sd;
>> +       else
>> +               v4l2_err(&fmd->v4l2_dev,
>> +                        "Failed to register MIPI-CSIS.%d (%d)\n", id,
>> ret);
>> +
>> +       return ret;
>> +}
>> +
>> +static int fimc_md_register_platform_entity(struct fimc_md *fmd,
>> +                                           struct platform_device *pdev,
>> +                                           int plat_entity)
>> +{
>> +       struct device *dev =&pdev->dev;
>>
>> +       int ret = -EPROBE_DEFER;
>> +       void *drvdata;
>> +
>> +       /* Lock to ensure dev->driver won't change. */
>> +       device_lock(dev);
>> +
>> +       if (!dev->driver || !try_module_get(dev->driver->owner))
>> +               goto dev_unlock;
>> +
>> +       drvdata = dev_get_drvdata(dev);
>> +       /* Some subdev didn't probe succesfully id drvdata is NULL */
>> +       if (drvdata) {
>> +               switch (plat_entity) {
>> +               case IDX_FLITE:
>> +                       ret = register_fimc_lite_entity(fmd, drvdata);
>> +                       break;
>> +               case IDX_CSIS:
>> +                       ret = register_csis_entity(fmd, pdev, drvdata);
>> +                       break;
>> +               default:
>> +                       ret = -ENODEV;
>> +               }
>> +       }
>> +
>> +       module_put(dev->driver->owner);
>> +dev_unlock:
>> +       device_unlock(dev);
>> +       if (ret == -EPROBE_DEFER)
>> +               dev_info(&fmd->pdev->dev, "deferring %s device
>> registration\n",
>> +                       dev_name(dev));
>> +       else if (ret<  0)
>> +               dev_err(&fmd->pdev->dev, "%s device registration failed
>> (%d)\n",
>> +                       dev_name(dev), ret);
>> +       return ret;
>> +}
>> +
>> +static int fimc_md_pdev_match(struct device *dev, void *data)
>
>
> This function is also useless in your case.
>
>
>> +{
>> +       struct platform_device *pdev = to_platform_device(dev);
>> +       int plat_entity = -1;
>> +       int ret;
>> +
>> +       if (!get_device(dev))
>> +               return -ENODEV;
>> +
>> +       if (!strcmp(pdev->name, CSIS_DRIVER_NAME))
>> +               plat_entity = IDX_CSIS;
>> +       else if (!strcmp(pdev->name, FIMC_LITE_DRV_NAME))
>> +               plat_entity = IDX_FLITE;
>> +
>> +       if (plat_entity>= 0)
>> +               ret = fimc_md_register_platform_entity(data, pdev,
>> +                                                      plat_entity);
>> +       put_device(dev);
>> +       return 0;
>> +}
>> +
>> +/* Register FIMC, FIMC-LITE and CSIS media entities */
>> +#ifdef CONFIG_OF
>> +static int fimc_md_register_of_platform_entities(struct fimc_md *fmd,
>> +                                                struct device_node
>> *parent)
>> +{
>> +       struct device_node *node;
>> +       int ret = 0;
>> +
>> +       for_each_available_child_of_node(parent, node) {
>> +               struct platform_device *pdev;
>> +               int plat_entity = -1;
>> +
>> +               pdev = of_find_device_by_node(node);
>> +               if (!pdev)
>> +                       continue;
>> +
>> +               /* If driver of any entity isn't ready try all again
>> later. */
>> +               if (!strcmp(node->name, CSIS_OF_NODE_NAME))
>> +                       plat_entity = IDX_CSIS;
>> +               else if (!strcmp(node->name, FIMC_LITE_OF_NODE_NAME))
>> +                       plat_entity = IDX_FLITE;
>> +
>> +               if (plat_entity>= 0)
>> +                       ret = fimc_md_register_platform_entity(fmd, pdev,
>> +                                                       plat_entity);
>> +               put_device(&pdev->dev);
>> +               if (ret<  0)
>> +                       break;
>> +       }
>> +
>> +       return ret;
>> +}
>> +#else
>> +#define fimc_md_register_platform_entities(fmd) (-ENOSYS)
>> +#endif
>
> ...
>>
>> +static int fimc_md_link_notify(struct media_pad *source,
>> +                              struct media_pad *sink, u32 flags)
>> +{
>> +       struct fimc_lite *fimc_lite = NULL;
>> +       struct exynos_pipeline *pipeline;
>> +       struct exynos5_pipeline0 *p;
>> +       struct v4l2_subdev *sd;
>> +       struct mutex *lock;
>> +       int ret = 0;
>> +       int ref_count;
>> +
>> +       if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
>> +               return 0;
>> +
>> +       sd = media_entity_to_v4l2_subdev(sink->entity);
>> +
>> +       switch (sd->grp_id) {
>> +       case GRP_ID_FLITE:
>> +               fimc_lite = v4l2_get_subdevdata(sd);
>> +               if (WARN_ON(fimc_lite == NULL))
>> +                       return 0;
>> +               pipeline =&fimc_lite->pipeline;
>> +               lock =&fimc_lite->lock;
>>
>> +               break;
>> +       default:
>> +               return 0;
>> +       }
>> +
>> +       p = (struct exynos5_pipeline0 *)pipeline->priv;
>> +       if (!p || !p->is_init)
>> +               return -EINVAL;
>> +
>> +       if (!(flags&  MEDIA_LNK_FL_ENABLED)) {
>>
>> +               int i;
>> +               mutex_lock(lock);
>
>
> ref_count needs to be checked here as well.
>
>
>> +               ret = __fimc_pipeline_close(pipeline);
>> +               for (i = 0; i<  IDX_MAX; i++)
>> +                       p->subdevs[i] = NULL;
>> +               mutex_unlock(lock);
>> +               return ret;
>> +       }
>> +       /*
>> +        * Link activation. Enable power of pipeline elements only if the
>> +        * pipeline is already in use, i.e. its video node is opened.
>> +        * Recreate the controls destroyed during the link deactivation.
>
>
> I think this line should be deleted.
>
>
>> +        */
>> +       mutex_lock(lock);
>> +
>> +       ref_count = fimc_lite->ref_count;
>> +       if (ref_count>  0)
>> +               ret = __fimc_pipeline_open(pipeline, source->entity,
>> true);
>> +
>> +       mutex_unlock(lock);
>> +       return ret ? -EPIPE : ret;
>> +}
>> +
>> +static ssize_t fimc_md_sysfs_show(struct device *dev,
>> +                                 struct device_attribute *attr, char
>> *buf)
>> +{
>> +       struct platform_device *pdev = to_platform_device(dev);
>> +       struct fimc_md *fmd = platform_get_drvdata(pdev);
>> +
>> +       if (fmd->user_subdev_api)
>> +               return strlcpy(buf, "Sub-device API (sub-dev)\n",
>> PAGE_SIZE);
>> +
>> +       return strlcpy(buf, "V4L2 video node only API (vid-dev)\n",
>> PAGE_SIZE);
>> +}
>> +
>> +static ssize_t fimc_md_sysfs_store(struct device *dev,
>> +                                  struct device_attribute *attr,
>> +                                  const char *buf, size_t count)
>> +{
>> +       struct platform_device *pdev = to_platform_device(dev);
>> +       struct fimc_md *fmd = platform_get_drvdata(pdev);
>> +       bool subdev_api;
>> +       int i;
>> +
>> +       if (!strcmp(buf, "vid-dev\n"))
>> +               subdev_api = false;
>> +       else if (!strcmp(buf, "sub-dev\n"))
>> +               subdev_api = true;
>> +       else
>> +               return count;
>> +
>> +       fmd->user_subdev_api = subdev_api;
>> +       for (i = 0; i<  FIMC_LITE_MAX_DEVS; i++)
>> +               if (fmd->fimc_lite[i])
>> +                       fmd->fimc_lite[i]->user_subdev_api = subdev_api;
>> +
>> +       return count;
>> +}
>> +/*
>> + * This device attribute is to select video pipeline configuration
>> method.
>> + * There are following valid values:
>> + *  vid-dev - for V4L2 video node API only, subdevice will be configured
>> + *  by the host driver.
>> + *  sub-dev - for media controller API, subdevs must be configured in
>> user
>> + *  space before starting streaming.
>> + */
>> +static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
>> +                  fimc_md_sysfs_show, fimc_md_sysfs_store);
>
>
> Please don't copy that. It is a not standard attribute that you should not
> need in this driver anyway.
>
>> +/**
>> + * fimc_md_sensor_notify - v4l2_device notification from a sensor subdev
>> + * @sd: pointer to a subdev generating the notification
>> + * @notification: the notification type, must be S5P_FIMC_TX_END_NOTIFY
>> + * @arg: pointer to an u32 type integer that stores the frame payload
>> value
>> + *
>> + * Passes the sensor notification to the capture device
>> + */
>> +static void fimc_md_sensor_notify(struct v4l2_subdev *sd,
>> +                               unsigned int notification, void *arg)
>> +{
>> +       struct fimc_md *fmd;
>> +       struct exynos_pipeline *ep;
>> +       struct exynos5_pipeline0 *p;
>> +       unsigned long flags;
>> +
>> +       if (sd == NULL)
>> +               return;
>> +
>> +       ep = media_pipe_to_exynos_pipeline(sd->entity.pipe);
>> +       p = (struct exynos5_pipeline0 *)ep->priv;
>> +
>> +       spin_lock_irqsave(&fmd->slock, flags);
>> +
>> +       if (p->sensor_notify)
>> +               p->sensor_notify(sd, notification, arg);
>> +
>> +       spin_unlock_irqrestore(&fmd->slock, flags);
>> +}
>> +
>> +static int fimc_md_probe(struct platform_device *pdev)
>> +{
>> +       struct device *dev =&pdev->dev;
>>
>> +       struct v4l2_device *v4l2_dev;
>> +       struct fimc_md *fmd;
>> +       int ret;
>> +
>> +       fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL);
>> +       if (!fmd)
>> +               return -ENOMEM;
>> +
>> +       spin_lock_init(&fmd->slock);
>> +       fmd->pdev = pdev;
>> +
>> +       strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
>
>
> Please change this to "SAMSUNG EXYNOS5 IS" or something similar.
> This could confuse user space!
>
>> +               sizeof(fmd->media_dev.model));
>> +       fmd->media_dev.link_notify = fimc_md_link_notify;
>> +       fmd->media_dev.dev = dev;
>> +
>> +       v4l2_dev =&fmd->v4l2_dev;
>> +       v4l2_dev->mdev =&fmd->media_dev;
>>
>> +       v4l2_dev->notify = fimc_md_sensor_notify;
>> +       strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
>
>
> exynos-fimc-md ?
>
>> +
>> +       ret = v4l2_device_register(dev,&fmd->v4l2_dev);
>>
>> +       if (ret<  0) {
>> +               v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n",
>> ret);
>> +
>> +               return ret;
>> +
>> +       }
>> +       ret = media_device_register(&fmd->media_dev);
>> +       if (ret<  0) {
>> +               v4l2_err(v4l2_dev, "Failed to register media dev: %d\n",
>> ret);
>> +               goto err_md;
>> +       }
>> +       ret = fimc_md_get_clocks(fmd);
>> +       if (ret)
>> +               goto err_clk;
>> +
>> +       fmd->user_subdev_api = (dev->of_node != NULL);
>> +       g_exynos_mdev = fmd;
>> +
>> +       /* Protect the media graph while we're registering entities */
>> +       mutex_lock(&fmd->media_dev.graph_mutex);
>> +
>> +       if (fmd->pdev->dev.of_node)
>> +               ret = fimc_md_register_of_platform_entities(fmd,
>> dev->of_node);
>> +       else
>> +               ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
>> +                                               fimc_md_pdev_match);
>> +
>> +       if (ret)
>> +               goto err_unlock;
>> +
>> +       if (dev->platform_data || dev->of_node) {
>
>
> platform_data will never be used, and dev->of_node would be always not NULL.
>
>
>> +               ret = fimc_md_register_sensor_entities(fmd);
>> +               if (ret)
>> +                       goto err_unlock;
>> +       }
>> +
>> +       ret = fimc_md_create_links(fmd);
>> +       if (ret)
>> +               goto err_unlock;
>> +
>> +       ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
>> +       if (ret)
>> +               goto err_unlock;
>> +
>> +       ret = device_create_file(&pdev->dev,&dev_attr_subdev_conf_mode);
>> +       if (ret)
>> +               goto err_unlock;
>> +
>> +       platform_set_drvdata(pdev, fmd);
>> +       mutex_unlock(&fmd->media_dev.graph_mutex);
>> +       return 0;
>> +
>> +err_unlock:
>> +       mutex_unlock(&fmd->media_dev.graph_mutex);
>> +err_clk:
>> +       media_device_unregister(&fmd->media_dev);
>> +       fimc_md_put_clocks(fmd);
>> +       fimc_md_unregister_entities(fmd);
>> +err_md:
>> +       v4l2_device_unregister(&fmd->v4l2_dev);
>> +       return ret;
>> +}
>> +
>
> ...
>
>> +static struct platform_device_id fimc_driver_ids[] __always_unused = {
>> +       { .name = "exynos-fimc-md" },
>> +       { },
>> +};
>> +MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
>> +
>> +static const struct of_device_id fimc_md_of_match[] __initconst = {
>
>
> The attribute is wrong. I would remove that "__initconst".
>
>
>> +       { .compatible = "samsung,exynos5-fimc" },
>> +       { },
>> +};
>> +MODULE_DEVICE_TABLE(of, fimc_md_of_match);
>> +
>
>
> --
>
> Regards,
> Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux