media: marvell-ccic: use async notifier to get the sensor
An instance of a sensor on DT-based MMP2 platform is always going to be created asynchronously. Let's move the manual device creation away from the core to the Cafe driver (used on OLPC XO-1, not present in DT) and set up appropriate async matches: I2C on Cafe, FWNODE on MMP (OLPC XO-1.75). Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
83c40e6611
commit
3eefe36cc0
@ -9,6 +9,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2006-11 One Laptop Per Child Association, Inc.
|
* Copyright 2006-11 One Laptop Per Child Association, Inc.
|
||||||
* Copyright 2006-11 Jonathan Corbet <corbet@lwn.net>
|
* Copyright 2006-11 Jonathan Corbet <corbet@lwn.net>
|
||||||
|
* Copyright 2018 Lubomir Rintel <lkundrak@v3.sk>
|
||||||
*
|
*
|
||||||
* Written by Jonathan Corbet, corbet@lwn.net.
|
* Written by Jonathan Corbet, corbet@lwn.net.
|
||||||
*
|
*
|
||||||
@ -25,6 +26,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
|
#include <media/i2c/ov7670.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@ -50,6 +52,7 @@ struct cafe_camera {
|
|||||||
int registered; /* Fully initialized? */
|
int registered; /* Fully initialized? */
|
||||||
struct mcam_camera mcam;
|
struct mcam_camera mcam;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
struct i2c_adapter *i2c_adapter;
|
||||||
wait_queue_head_t smbus_wait; /* Waiting on i2c events */
|
wait_queue_head_t smbus_wait; /* Waiting on i2c events */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -349,15 +352,15 @@ static int cafe_smbus_setup(struct cafe_camera *cam)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
cam->mcam.i2c_adapter = adap;
|
cam->i2c_adapter = adap;
|
||||||
cafe_smbus_enable_irq(cam);
|
cafe_smbus_enable_irq(cam);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cafe_smbus_shutdown(struct cafe_camera *cam)
|
static void cafe_smbus_shutdown(struct cafe_camera *cam)
|
||||||
{
|
{
|
||||||
i2c_del_adapter(cam->mcam.i2c_adapter);
|
i2c_del_adapter(cam->i2c_adapter);
|
||||||
kfree(cam->mcam.i2c_adapter);
|
kfree(cam->i2c_adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -450,6 +453,29 @@ static irqreturn_t cafe_irq(int irq, void *data)
|
|||||||
return IRQ_RETVAL(handled);
|
return IRQ_RETVAL(handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static struct ov7670_config sensor_cfg = {
|
||||||
|
/*
|
||||||
|
* Exclude QCIF mode, because it only captures a tiny portion
|
||||||
|
* of the sensor FOV
|
||||||
|
*/
|
||||||
|
.min_width = 320,
|
||||||
|
.min_height = 240,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the clock speed for the XO 1; I don't believe this
|
||||||
|
* driver has ever run anywhere else.
|
||||||
|
*/
|
||||||
|
.clock_speed = 45,
|
||||||
|
.use_smbus = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct i2c_board_info ov7670_info = {
|
||||||
|
.type = "ov7670",
|
||||||
|
.addr = 0x42 >> 1,
|
||||||
|
.platform_data = &sensor_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/*
|
/*
|
||||||
@ -479,12 +505,6 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
|||||||
mcam->plat_power_down = cafe_ctlr_power_down;
|
mcam->plat_power_down = cafe_ctlr_power_down;
|
||||||
mcam->dev = &pdev->dev;
|
mcam->dev = &pdev->dev;
|
||||||
snprintf(mcam->bus_info, sizeof(mcam->bus_info), "PCI:%s", pci_name(pdev));
|
snprintf(mcam->bus_info, sizeof(mcam->bus_info), "PCI:%s", pci_name(pdev));
|
||||||
/*
|
|
||||||
* Set the clock speed for the XO 1; I don't believe this
|
|
||||||
* driver has ever run anywhere else.
|
|
||||||
*/
|
|
||||||
mcam->clock_speed = 45;
|
|
||||||
mcam->use_smbus = 1;
|
|
||||||
/*
|
/*
|
||||||
* Vmalloc mode for buffers is traditional with this driver.
|
* Vmalloc mode for buffers is traditional with this driver.
|
||||||
* We *might* be able to run DMA_contig, especially on a system
|
* We *might* be able to run DMA_contig, especially on a system
|
||||||
@ -525,12 +545,21 @@ static int cafe_pci_probe(struct pci_dev *pdev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out_pdown;
|
goto out_pdown;
|
||||||
|
|
||||||
|
mcam->asd.match_type = V4L2_ASYNC_MATCH_I2C;
|
||||||
|
mcam->asd.match.i2c.adapter_id = i2c_adapter_id(cam->i2c_adapter);
|
||||||
|
mcam->asd.match.i2c.address = ov7670_info.addr;
|
||||||
|
|
||||||
ret = mccic_register(mcam);
|
ret = mccic_register(mcam);
|
||||||
if (ret == 0) {
|
if (ret)
|
||||||
|
goto out_smbus_shutdown;
|
||||||
|
|
||||||
|
if (i2c_new_device(cam->i2c_adapter, &ov7670_info)) {
|
||||||
cam->registered = 1;
|
cam->registered = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mccic_shutdown(mcam);
|
||||||
|
out_smbus_shutdown:
|
||||||
cafe_smbus_shutdown(cam);
|
cafe_smbus_shutdown(cam);
|
||||||
out_pdown:
|
out_pdown:
|
||||||
cafe_ctlr_power_down(mcam);
|
cafe_ctlr_power_down(mcam);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* so it needs platform-specific support outside of the core.
|
* so it needs platform-specific support outside of the core.
|
||||||
*
|
*
|
||||||
* Copyright 2011 Jonathan Corbet corbet@lwn.net
|
* Copyright 2011 Jonathan Corbet corbet@lwn.net
|
||||||
|
* Copyright 2018 Lubomir Rintel <lkundrak@v3.sk>
|
||||||
*/
|
*/
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -26,7 +27,6 @@
|
|||||||
#include <media/v4l2-ioctl.h>
|
#include <media/v4l2-ioctl.h>
|
||||||
#include <media/v4l2-ctrls.h>
|
#include <media/v4l2-ctrls.h>
|
||||||
#include <media/v4l2-event.h>
|
#include <media/v4l2-event.h>
|
||||||
#include <media/i2c/ov7670.h>
|
|
||||||
#include <media/videobuf2-vmalloc.h>
|
#include <media/videobuf2-vmalloc.h>
|
||||||
#include <media/videobuf2-dma-contig.h>
|
#include <media/videobuf2-dma-contig.h>
|
||||||
#include <media/videobuf2-dma-sg.h>
|
#include <media/videobuf2-dma-sg.h>
|
||||||
@ -93,6 +93,9 @@ MODULE_PARM_DESC(buffer_mode,
|
|||||||
#define sensor_call(cam, o, f, args...) \
|
#define sensor_call(cam, o, f, args...) \
|
||||||
v4l2_subdev_call(cam->sensor, o, f, ##args)
|
v4l2_subdev_call(cam->sensor, o, f, ##args)
|
||||||
|
|
||||||
|
#define notifier_to_mcam(notifier) \
|
||||||
|
container_of(notifier, struct mcam_camera, notifier)
|
||||||
|
|
||||||
static struct mcam_format_struct {
|
static struct mcam_format_struct {
|
||||||
__u8 *desc;
|
__u8 *desc;
|
||||||
__u32 pixelformat;
|
__u32 pixelformat;
|
||||||
@ -1715,23 +1718,94 @@ EXPORT_SYMBOL_GPL(mccic_irq);
|
|||||||
/*
|
/*
|
||||||
* Registration and such.
|
* Registration and such.
|
||||||
*/
|
*/
|
||||||
static struct ov7670_config sensor_cfg = {
|
|
||||||
/*
|
|
||||||
* Exclude QCIF mode, because it only captures a tiny portion
|
|
||||||
* of the sensor FOV
|
|
||||||
*/
|
|
||||||
.min_width = 320,
|
|
||||||
.min_height = 240,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static int mccic_notify_bound(struct v4l2_async_notifier *notifier,
|
||||||
|
struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd)
|
||||||
|
{
|
||||||
|
struct mcam_camera *cam = notifier_to_mcam(notifier);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&cam->s_mutex);
|
||||||
|
if (cam->sensor) {
|
||||||
|
cam_err(cam, "sensor already bound\n");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
v4l2_set_subdev_hostdata(subdev, cam);
|
||||||
|
cam->sensor = subdev;
|
||||||
|
|
||||||
|
ret = mcam_cam_init(cam);
|
||||||
|
if (ret) {
|
||||||
|
cam->sensor = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mcam_setup_vb2(cam);
|
||||||
|
if (ret) {
|
||||||
|
cam->sensor = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
cam->vdev = mcam_v4l_template;
|
||||||
|
cam->vdev.v4l2_dev = &cam->v4l2_dev;
|
||||||
|
cam->vdev.lock = &cam->s_mutex;
|
||||||
|
cam->vdev.queue = &cam->vb_queue;
|
||||||
|
video_set_drvdata(&cam->vdev, cam);
|
||||||
|
ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
|
||||||
|
if (ret) {
|
||||||
|
cam->sensor = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
cam_dbg(cam, "sensor %s bound\n", subdev->name);
|
||||||
|
out:
|
||||||
|
mutex_unlock(&cam->s_mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mccic_notify_unbind(struct v4l2_async_notifier *notifier,
|
||||||
|
struct v4l2_subdev *subdev, struct v4l2_async_subdev *asd)
|
||||||
|
{
|
||||||
|
struct mcam_camera *cam = notifier_to_mcam(notifier);
|
||||||
|
|
||||||
|
mutex_lock(&cam->s_mutex);
|
||||||
|
if (cam->sensor != subdev) {
|
||||||
|
cam_err(cam, "sensor %s not bound\n", subdev->name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
video_unregister_device(&cam->vdev);
|
||||||
|
cam->sensor = NULL;
|
||||||
|
cam_dbg(cam, "sensor %s unbound\n", subdev->name);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&cam->s_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mccic_notify_complete(struct v4l2_async_notifier *notifier)
|
||||||
|
{
|
||||||
|
struct mcam_camera *cam = notifier_to_mcam(notifier);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the v4l2 setup done.
|
||||||
|
*/
|
||||||
|
ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
|
||||||
|
if (!ret)
|
||||||
|
cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct v4l2_async_notifier_operations mccic_notify_ops = {
|
||||||
|
.bound = mccic_notify_bound,
|
||||||
|
.unbind = mccic_notify_unbind,
|
||||||
|
.complete = mccic_notify_complete,
|
||||||
|
};
|
||||||
|
|
||||||
int mccic_register(struct mcam_camera *cam)
|
int mccic_register(struct mcam_camera *cam)
|
||||||
{
|
{
|
||||||
struct i2c_board_info ov7670_info = {
|
|
||||||
.type = "ov7670",
|
|
||||||
.addr = 0x42 >> 1,
|
|
||||||
.platform_data = &sensor_cfg,
|
|
||||||
};
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1744,17 +1818,20 @@ int mccic_register(struct mcam_camera *cam)
|
|||||||
printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, attempting vmalloc mode instead\n");
|
printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, attempting vmalloc mode instead\n");
|
||||||
cam->buffer_mode = B_vmalloc;
|
cam->buffer_mode = B_vmalloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
|
if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
|
||||||
printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
|
printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
|
||||||
cam->buffer_mode);
|
cam->buffer_mode);
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register with V4L
|
* Register with V4L
|
||||||
*/
|
*/
|
||||||
ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
|
ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
mutex_init(&cam->s_mutex);
|
mutex_init(&cam->s_mutex);
|
||||||
cam->state = S_NOTREADY;
|
cam->state = S_NOTREADY;
|
||||||
@ -1764,43 +1841,20 @@ int mccic_register(struct mcam_camera *cam)
|
|||||||
mcam_ctlr_init(cam);
|
mcam_ctlr_init(cam);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the v4l2 setup done.
|
* Register sensor notifier.
|
||||||
*/
|
*/
|
||||||
ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
|
v4l2_async_notifier_init(&cam->notifier);
|
||||||
if (ret)
|
ret = v4l2_async_notifier_add_subdev(&cam->notifier, &cam->asd);
|
||||||
goto out_unregister;
|
if (ret) {
|
||||||
cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
|
cam_warn(cam, "failed to add subdev to a notifier");
|
||||||
|
goto out;
|
||||||
/*
|
|
||||||
* Try to find the sensor.
|
|
||||||
*/
|
|
||||||
sensor_cfg.clock_speed = cam->clock_speed;
|
|
||||||
sensor_cfg.use_smbus = cam->use_smbus;
|
|
||||||
cam->sensor = v4l2_i2c_new_subdev_board(&cam->v4l2_dev,
|
|
||||||
cam->i2c_adapter, &ov7670_info, NULL);
|
|
||||||
if (cam->sensor == NULL) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto out_unregister;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mcam_cam_init(cam);
|
cam->notifier.ops = &mccic_notify_ops;
|
||||||
if (ret)
|
ret = v4l2_async_notifier_register(&cam->v4l2_dev, &cam->notifier);
|
||||||
goto out_unregister;
|
if (ret < 0) {
|
||||||
|
cam_warn(cam, "failed to register a sensor notifier");
|
||||||
ret = mcam_setup_vb2(cam);
|
goto out;
|
||||||
if (ret)
|
|
||||||
goto out_unregister;
|
|
||||||
|
|
||||||
mutex_lock(&cam->s_mutex);
|
|
||||||
cam->vdev = mcam_v4l_template;
|
|
||||||
cam->vdev.v4l2_dev = &cam->v4l2_dev;
|
|
||||||
cam->vdev.lock = &cam->s_mutex;
|
|
||||||
cam->vdev.queue = &cam->vb_queue;
|
|
||||||
video_set_drvdata(&cam->vdev, cam);
|
|
||||||
ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
|
|
||||||
if (ret) {
|
|
||||||
mutex_unlock(&cam->s_mutex);
|
|
||||||
goto out_unregister;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1811,11 +1865,10 @@ int mccic_register(struct mcam_camera *cam)
|
|||||||
cam_warn(cam, "Unable to alloc DMA buffers at load will try again later.");
|
cam_warn(cam, "Unable to alloc DMA buffers at load will try again later.");
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&cam->s_mutex);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_unregister:
|
out:
|
||||||
v4l2_ctrl_handler_free(&cam->ctrl_handler);
|
v4l2_async_notifier_unregister(&cam->notifier);
|
||||||
v4l2_device_unregister(&cam->v4l2_dev);
|
v4l2_device_unregister(&cam->v4l2_dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1835,8 +1888,8 @@ void mccic_shutdown(struct mcam_camera *cam)
|
|||||||
}
|
}
|
||||||
if (cam->buffer_mode == B_vmalloc)
|
if (cam->buffer_mode == B_vmalloc)
|
||||||
mcam_free_dma_bufs(cam);
|
mcam_free_dma_bufs(cam);
|
||||||
video_unregister_device(&cam->vdev);
|
|
||||||
v4l2_ctrl_handler_free(&cam->ctrl_handler);
|
v4l2_ctrl_handler_free(&cam->ctrl_handler);
|
||||||
|
v4l2_async_notifier_unregister(&cam->notifier);
|
||||||
v4l2_device_unregister(&cam->v4l2_dev);
|
v4l2_device_unregister(&cam->v4l2_dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mccic_shutdown);
|
EXPORT_SYMBOL_GPL(mccic_shutdown);
|
||||||
|
@ -102,14 +102,11 @@ struct mcam_camera {
|
|||||||
* These fields should be set by the platform code prior to
|
* These fields should be set by the platform code prior to
|
||||||
* calling mcam_register().
|
* calling mcam_register().
|
||||||
*/
|
*/
|
||||||
struct i2c_adapter *i2c_adapter;
|
|
||||||
unsigned char __iomem *regs;
|
unsigned char __iomem *regs;
|
||||||
unsigned regs_size; /* size in bytes of the register space */
|
unsigned regs_size; /* size in bytes of the register space */
|
||||||
spinlock_t dev_lock;
|
spinlock_t dev_lock;
|
||||||
struct device *dev; /* For messages, dma alloc */
|
struct device *dev; /* For messages, dma alloc */
|
||||||
enum mcam_chip_id chip_id;
|
enum mcam_chip_id chip_id;
|
||||||
short int clock_speed; /* Sensor clock speed, default 30 */
|
|
||||||
short int use_smbus; /* SMBUS or straight I2c? */
|
|
||||||
enum mcam_buffer_mode buffer_mode;
|
enum mcam_buffer_mode buffer_mode;
|
||||||
|
|
||||||
int mclk_src; /* which clock source the mclk derives from */
|
int mclk_src; /* which clock source the mclk derives from */
|
||||||
@ -150,6 +147,8 @@ struct mcam_camera {
|
|||||||
* Subsystem structures.
|
* Subsystem structures.
|
||||||
*/
|
*/
|
||||||
struct video_device vdev;
|
struct video_device vdev;
|
||||||
|
struct v4l2_async_notifier notifier;
|
||||||
|
struct v4l2_async_subdev asd;
|
||||||
struct v4l2_subdev *sensor;
|
struct v4l2_subdev *sensor;
|
||||||
|
|
||||||
/* Videobuf2 stuff */
|
/* Videobuf2 stuff */
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
* to work with the Armada 610 as used in the OLPC 1.75 system.
|
* to work with the Armada 610 as used in the OLPC 1.75 system.
|
||||||
*
|
*
|
||||||
* Copyright 2011 Jonathan Corbet <corbet@lwn.net>
|
* Copyright 2011 Jonathan Corbet <corbet@lwn.net>
|
||||||
|
* Copyright 2018 Lubomir Rintel <lkundrak@v3.sk>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/i2c.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@ -314,6 +314,7 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||||||
struct mmp_camera *cam;
|
struct mmp_camera *cam;
|
||||||
struct mcam_camera *mcam;
|
struct mcam_camera *mcam;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
|
struct fwnode_handle *ep;
|
||||||
struct mmp_camera_platform_data *pdata;
|
struct mmp_camera_platform_data *pdata;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -328,7 +329,6 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||||||
mcam->plat_power_down = mmpcam_power_down;
|
mcam->plat_power_down = mmpcam_power_down;
|
||||||
mcam->calc_dphy = mmpcam_calc_dphy;
|
mcam->calc_dphy = mmpcam_calc_dphy;
|
||||||
mcam->dev = &pdev->dev;
|
mcam->dev = &pdev->dev;
|
||||||
mcam->use_smbus = 0;
|
|
||||||
pdata = pdev->dev.platform_data;
|
pdata = pdev->dev.platform_data;
|
||||||
if (pdata) {
|
if (pdata) {
|
||||||
mcam->mclk_src = pdata->mclk_src;
|
mcam->mclk_src = pdata->mclk_src;
|
||||||
@ -372,15 +372,6 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||||||
cam->power_regs = devm_ioremap_resource(&pdev->dev, res);
|
cam->power_regs = devm_ioremap_resource(&pdev->dev, res);
|
||||||
if (IS_ERR(cam->power_regs))
|
if (IS_ERR(cam->power_regs))
|
||||||
return PTR_ERR(cam->power_regs);
|
return PTR_ERR(cam->power_regs);
|
||||||
/*
|
|
||||||
* Find the i2c adapter. This assumes, of course, that the
|
|
||||||
* i2c bus is already up and functioning.
|
|
||||||
*/
|
|
||||||
mcam->i2c_adapter = platform_get_drvdata(pdata->i2c_device);
|
|
||||||
if (mcam->i2c_adapter == NULL) {
|
|
||||||
dev_err(&pdev->dev, "No i2c adapter\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Sensor GPIO pins.
|
* Sensor GPIO pins.
|
||||||
*/
|
*/
|
||||||
@ -403,6 +394,19 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
mcam_init_clk(mcam);
|
mcam_init_clk(mcam);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a match of the sensor against its OF node.
|
||||||
|
*/
|
||||||
|
ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(pdev->dev.of_node),
|
||||||
|
NULL);
|
||||||
|
if (!ep)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
mcam->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
|
||||||
|
mcam->asd.match.fwnode = fwnode_graph_get_remote_port_parent(ep);
|
||||||
|
|
||||||
|
fwnode_handle_put(ep);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Power the device up and hand it off to the core.
|
* Power the device up and hand it off to the core.
|
||||||
*/
|
*/
|
||||||
@ -412,6 +416,7 @@ static int mmpcam_probe(struct platform_device *pdev)
|
|||||||
ret = mccic_register(mcam);
|
ret = mccic_register(mcam);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_power_down;
|
goto out_power_down;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally, set up our IRQ now that the core is ready to
|
* Finally, set up our IRQ now that the core is ready to
|
||||||
* deal with it.
|
* deal with it.
|
||||||
|
@ -12,7 +12,6 @@ enum dphy3_algo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mmp_camera_platform_data {
|
struct mmp_camera_platform_data {
|
||||||
struct platform_device *i2c_device;
|
|
||||||
int sensor_power_gpio;
|
int sensor_power_gpio;
|
||||||
int sensor_reset_gpio;
|
int sensor_reset_gpio;
|
||||||
enum v4l2_mbus_type bus_type;
|
enum v4l2_mbus_type bus_type;
|
||||||
|
Loading…
Reference in New Issue
Block a user