|
@@ -51,6 +51,9 @@
|
|
#include <linux/string.h>
|
|
#include <linux/string.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c.h>
|
|
|
|
+#if defined(CONFIG_SPI)
|
|
|
|
+#include <linux/spi/spi.h>
|
|
|
|
+#endif
|
|
#include <asm/uaccess.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/system.h>
|
|
#include <asm/system.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/pgtable.h>
|
|
@@ -955,6 +958,66 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
|
|
|
|
|
|
#endif /* defined(CONFIG_I2C) */
|
|
#endif /* defined(CONFIG_I2C) */
|
|
|
|
|
|
|
|
+#if defined(CONFIG_SPI)
|
|
|
|
+
|
|
|
|
+/* Load a spi sub-device. */
|
|
|
|
+
|
|
|
|
+void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
|
|
|
|
+ const struct v4l2_subdev_ops *ops)
|
|
|
|
+{
|
|
|
|
+ v4l2_subdev_init(sd, ops);
|
|
|
|
+ sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
|
|
|
|
+ /* the owner is the same as the spi_device's driver owner */
|
|
|
|
+ sd->owner = spi->dev.driver->owner;
|
|
|
|
+ /* spi_device and v4l2_subdev point to one another */
|
|
|
|
+ v4l2_set_subdevdata(sd, spi);
|
|
|
|
+ spi_set_drvdata(spi, sd);
|
|
|
|
+ /* initialize name */
|
|
|
|
+ strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name));
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
|
|
|
|
+
|
|
|
|
+struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
|
|
|
|
+ struct spi_master *master, struct spi_board_info *info)
|
|
|
|
+{
|
|
|
|
+ struct v4l2_subdev *sd = NULL;
|
|
|
|
+ struct spi_device *spi = NULL;
|
|
|
|
+
|
|
|
|
+ BUG_ON(!v4l2_dev);
|
|
|
|
+
|
|
|
|
+ if (info->modalias)
|
|
|
|
+ request_module(info->modalias);
|
|
|
|
+
|
|
|
|
+ spi = spi_new_device(master, info);
|
|
|
|
+
|
|
|
|
+ if (spi == NULL || spi->dev.driver == NULL)
|
|
|
|
+ goto error;
|
|
|
|
+
|
|
|
|
+ if (!try_module_get(spi->dev.driver->owner))
|
|
|
|
+ goto error;
|
|
|
|
+
|
|
|
|
+ sd = spi_get_drvdata(spi);
|
|
|
|
+
|
|
|
|
+ /* Register with the v4l2_device which increases the module's
|
|
|
|
+ use count as well. */
|
|
|
|
+ if (v4l2_device_register_subdev(v4l2_dev, sd))
|
|
|
|
+ sd = NULL;
|
|
|
|
+
|
|
|
|
+ /* Decrease the module use count to match the first try_module_get. */
|
|
|
|
+ module_put(spi->dev.driver->owner);
|
|
|
|
+
|
|
|
|
+error:
|
|
|
|
+ /* If we have a client but no subdev, then something went wrong and
|
|
|
|
+ we must unregister the client. */
|
|
|
|
+ if (spi && sd == NULL)
|
|
|
|
+ spi_unregister_device(spi);
|
|
|
|
+
|
|
|
|
+ return sd;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
|
|
|
|
+
|
|
|
|
+#endif /* defined(CONFIG_SPI) */
|
|
|
|
+
|
|
/* Clamp x to be between min and max, aligned to a multiple of 2^align. min
|
|
/* Clamp x to be between min and max, aligned to a multiple of 2^align. min
|
|
* and max don't have to be aligned, but there must be at least one valid
|
|
* and max don't have to be aligned, but there must be at least one valid
|
|
* value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples
|
|
* value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples
|