Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * v4l2-spi - SPI helpers for Video4Linux2
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/spi/spi.h>
0008 #include <media/v4l2-common.h>
0009 #include <media/v4l2-device.h>
0010 
0011 void v4l2_spi_subdev_unregister(struct v4l2_subdev *sd)
0012 {
0013     struct spi_device *spi = v4l2_get_subdevdata(sd);
0014 
0015     if (spi && !spi->dev.of_node && !spi->dev.fwnode)
0016         spi_unregister_device(spi);
0017 }
0018 
0019 void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
0020               const struct v4l2_subdev_ops *ops)
0021 {
0022     v4l2_subdev_init(sd, ops);
0023     sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
0024     /* the owner is the same as the spi_device's driver owner */
0025     sd->owner = spi->dev.driver->owner;
0026     sd->dev = &spi->dev;
0027     /* spi_device and v4l2_subdev point to one another */
0028     v4l2_set_subdevdata(sd, spi);
0029     spi_set_drvdata(spi, sd);
0030     /* initialize name */
0031     snprintf(sd->name, sizeof(sd->name), "%s %s",
0032          spi->dev.driver->name, dev_name(&spi->dev));
0033 }
0034 EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
0035 
0036 struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
0037                     struct spi_master *master,
0038                     struct spi_board_info *info)
0039 {
0040     struct v4l2_subdev *sd = NULL;
0041     struct spi_device *spi = NULL;
0042 
0043     if (!v4l2_dev)
0044         return NULL;
0045     if (info->modalias[0])
0046         request_module(info->modalias);
0047 
0048     spi = spi_new_device(master, info);
0049 
0050     if (!spi || !spi->dev.driver)
0051         goto error;
0052 
0053     if (!try_module_get(spi->dev.driver->owner))
0054         goto error;
0055 
0056     sd = spi_get_drvdata(spi);
0057 
0058     /*
0059      * Register with the v4l2_device which increases the module's
0060      * use count as well.
0061      */
0062     if (v4l2_device_register_subdev(v4l2_dev, sd))
0063         sd = NULL;
0064 
0065     /* Decrease the module use count to match the first try_module_get. */
0066     module_put(spi->dev.driver->owner);
0067 
0068 error:
0069     /*
0070      * If we have a client but no subdev, then something went wrong and
0071      * we must unregister the client.
0072      */
0073     if (!sd)
0074         spi_unregister_device(spi);
0075 
0076     return sd;
0077 }
0078 EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);