aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c')
-rw-r--r--drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c402
1 files changed, 222 insertions, 180 deletions
diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
index d2262275a870..ce26741ae9d9 100644
--- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
+++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c
@@ -23,6 +23,7 @@
#include <media/v4l2-event.h>
#include <media/v4l2-common.h>
#include <linux/delay.h>
+#include <linux/platform_device.h>
#include "mmal-common.h"
#include "mmal-encodings.h"
@@ -78,131 +79,132 @@ static const struct v4l2_fract
/* video formats */
static struct mmal_fmt formats[] = {
{
- .name = "4:2:0, planar, YUV",
- .fourcc = V4L2_PIX_FMT_YUV420,
- .flags = 0,
- .mmal = MMAL_ENCODING_I420,
- .depth = 12,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 1,
- },
- {
- .name = "4:2:2, packed, YUYV",
- .fourcc = V4L2_PIX_FMT_YUYV,
- .flags = 0,
- .mmal = MMAL_ENCODING_YUYV,
- .depth = 16,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 2,
- },
- {
- .name = "RGB24 (LE)",
- .fourcc = V4L2_PIX_FMT_RGB24,
- .flags = 0,
- .mmal = MMAL_ENCODING_RGB24,
- .depth = 24,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 3,
- },
- {
- .name = "JPEG",
- .fourcc = V4L2_PIX_FMT_JPEG,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal = MMAL_ENCODING_JPEG,
- .depth = 8,
- .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
- .ybbp = 0,
- },
- {
- .name = "H264",
- .fourcc = V4L2_PIX_FMT_H264,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal = MMAL_ENCODING_H264,
- .depth = 8,
- .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
- .ybbp = 0,
- },
- {
- .name = "MJPEG",
- .fourcc = V4L2_PIX_FMT_MJPEG,
- .flags = V4L2_FMT_FLAG_COMPRESSED,
- .mmal = MMAL_ENCODING_MJPEG,
- .depth = 8,
- .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
- .ybbp = 0,
- },
- {
- .name = "4:2:2, packed, YVYU",
- .fourcc = V4L2_PIX_FMT_YVYU,
- .flags = 0,
- .mmal = MMAL_ENCODING_YVYU,
- .depth = 16,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 2,
- },
- {
- .name = "4:2:2, packed, VYUY",
- .fourcc = V4L2_PIX_FMT_VYUY,
- .flags = 0,
- .mmal = MMAL_ENCODING_VYUY,
- .depth = 16,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 2,
- },
- {
- .name = "4:2:2, packed, UYVY",
- .fourcc = V4L2_PIX_FMT_UYVY,
- .flags = 0,
- .mmal = MMAL_ENCODING_UYVY,
- .depth = 16,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 2,
- },
- {
- .name = "4:2:0, planar, NV12",
- .fourcc = V4L2_PIX_FMT_NV12,
- .flags = 0,
- .mmal = MMAL_ENCODING_NV12,
- .depth = 12,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 1,
- },
- {
- .name = "RGB24 (BE)",
- .fourcc = V4L2_PIX_FMT_BGR24,
- .flags = 0,
- .mmal = MMAL_ENCODING_BGR24,
- .depth = 24,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 3,
- },
- {
- .name = "4:2:0, planar, YVU",
- .fourcc = V4L2_PIX_FMT_YVU420,
- .flags = 0,
- .mmal = MMAL_ENCODING_YV12,
- .depth = 12,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 1,
- },
- {
- .name = "4:2:0, planar, NV21",
- .fourcc = V4L2_PIX_FMT_NV21,
- .flags = 0,
- .mmal = MMAL_ENCODING_NV21,
- .depth = 12,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 1,
- },
- {
- .name = "RGB32 (BE)",
- .fourcc = V4L2_PIX_FMT_BGR32,
- .flags = 0,
- .mmal = MMAL_ENCODING_BGRA,
- .depth = 32,
- .mmal_component = MMAL_COMPONENT_CAMERA,
- .ybbp = 4,
- },
+ .name = "4:2:0, planar, YUV",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_I420,
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 1,
+ .remove_padding = 1,
+ }, {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_YUYV,
+ .depth = 16,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 2,
+ .remove_padding = 0,
+ }, {
+ .name = "RGB24 (LE)",
+ .fourcc = V4L2_PIX_FMT_RGB24,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_RGB24,
+ .depth = 24,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 3,
+ .remove_padding = 0,
+ }, {
+ .name = "JPEG",
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_JPEG,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
+ .ybbp = 0,
+ .remove_padding = 0,
+ }, {
+ .name = "H264",
+ .fourcc = V4L2_PIX_FMT_H264,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_H264,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
+ .ybbp = 0,
+ .remove_padding = 0,
+ }, {
+ .name = "MJPEG",
+ .fourcc = V4L2_PIX_FMT_MJPEG,
+ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_MJPEG,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
+ .ybbp = 0,
+ .remove_padding = 0,
+ }, {
+ .name = "4:2:2, packed, YVYU",
+ .fourcc = V4L2_PIX_FMT_YVYU,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_YVYU,
+ .depth = 16,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 2,
+ .remove_padding = 0,
+ }, {
+ .name = "4:2:2, packed, VYUY",
+ .fourcc = V4L2_PIX_FMT_VYUY,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_VYUY,
+ .depth = 16,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 2,
+ .remove_padding = 0,
+ }, {
+ .name = "4:2:2, packed, UYVY",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_UYVY,
+ .depth = 16,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 2,
+ .remove_padding = 0,
+ }, {
+ .name = "4:2:0, planar, NV12",
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_NV12,
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 1,
+ .remove_padding = 1,
+ }, {
+ .name = "RGB24 (BE)",
+ .fourcc = V4L2_PIX_FMT_BGR24,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_BGR24,
+ .depth = 24,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 3,
+ .remove_padding = 0,
+ }, {
+ .name = "4:2:0, planar, YVU",
+ .fourcc = V4L2_PIX_FMT_YVU420,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_YV12,
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 1,
+ .remove_padding = 1,
+ }, {
+ .name = "4:2:0, planar, NV21",
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_NV21,
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 1,
+ .remove_padding = 1,
+ }, {
+ .name = "RGB32 (BE)",
+ .fourcc = V4L2_PIX_FMT_BGR32,
+ .flags = 0,
+ .mmal = MMAL_ENCODING_BGRA,
+ .depth = 32,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ .ybbp = 4,
+ .remove_padding = 0,
+ },
};
static struct mmal_fmt *get_format(struct v4l2_format *f)
@@ -245,8 +247,10 @@ static int queue_setup(struct vb2_queue *vq,
return -EINVAL;
}
- if (*nbuffers < (dev->capture.port->current_buffer.num + 2))
- *nbuffers = (dev->capture.port->current_buffer.num + 2);
+ if (*nbuffers < dev->capture.port->minimum_buffer.num)
+ *nbuffers = dev->capture.port->minimum_buffer.num;
+
+ dev->capture.port->current_buffer.num = *nbuffers;
*nplanes = 1;
@@ -263,16 +267,30 @@ static int queue_setup(struct vb2_queue *vq,
return 0;
}
+static int buffer_init(struct vb2_buffer *vb)
+{
+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
+ struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+ __func__, dev, vb);
+ buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
+ buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+
+ return mmal_vchi_buffer_init(dev->instance, buf);
+}
+
static int buffer_prepare(struct vb2_buffer *vb)
{
struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
unsigned long size;
- v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
- __func__, dev);
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+ __func__, dev, vb);
- BUG_ON(!dev->capture.port);
- BUG_ON(!dev->capture.fmt);
+ if (!dev->capture.port || !dev->capture.fmt)
+ return -ENODEV;
size = dev->capture.stride * dev->capture.height;
if (vb2_plane_size(vb, 0) < size) {
@@ -285,6 +303,17 @@ static int buffer_prepare(struct vb2_buffer *vb)
return 0;
}
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb);
+ struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb);
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n",
+ __func__, dev, vb);
+ mmal_vchi_buffer_cleanup(buf);
+}
+
static inline bool is_capturing(struct bm2835_mmal_dev *dev)
{
return dev->capture.camera_port ==
@@ -450,10 +479,8 @@ static void buffer_queue(struct vb2_buffer *vb)
int ret;
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
- "%s: dev:%p buf:%p\n", __func__, dev, buf);
-
- buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
- buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0);
+ "%s: dev:%p buf:%p, idx %u\n",
+ __func__, dev, buf, vb2->vb2_buf.index);
ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
if (ret < 0)
@@ -465,7 +492,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
int ret;
- int parameter_size;
+ u32 parameter_size;
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
__func__, dev);
@@ -617,7 +644,9 @@ static void bm2835_mmal_unlock(struct vb2_queue *vq)
static const struct vb2_ops bm2835_mmal_video_qops = {
.queue_setup = queue_setup,
+ .buf_init = buffer_init,
.buf_prepare = buffer_prepare,
+ .buf_cleanup = buffer_cleanup,
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
@@ -634,17 +663,19 @@ static int set_overlay_params(struct bm2835_mmal_dev *dev,
struct vchiq_mmal_port *port)
{
struct mmal_parameter_displayregion prev_config = {
- .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA |
- MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN,
- .layer = PREVIEW_LAYER,
- .alpha = dev->overlay.global_alpha,
- .fullscreen = 0,
- .dest_rect = {
- .x = dev->overlay.w.left,
- .y = dev->overlay.w.top,
- .width = dev->overlay.w.width,
- .height = dev->overlay.w.height,
- },
+ .set = MMAL_DISPLAY_SET_LAYER |
+ MMAL_DISPLAY_SET_ALPHA |
+ MMAL_DISPLAY_SET_DEST_RECT |
+ MMAL_DISPLAY_SET_FULLSCREEN,
+ .layer = PREVIEW_LAYER,
+ .alpha = dev->overlay.global_alpha,
+ .fullscreen = 0,
+ .dest_rect = {
+ .x = dev->overlay.w.left,
+ .y = dev->overlay.w.top,
+ .width = dev->overlay.w.width,
+ .height = dev->overlay.w.height,
+ },
};
return vchiq_mmal_port_parameter_set(dev->instance, port,
MMAL_PARAMETER_DISPLAYREGION,
@@ -662,7 +693,7 @@ static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
fmt = &formats[f->index];
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strlcpy((char *)f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
f->flags = fmt->flags;
@@ -820,7 +851,7 @@ static int vidioc_enum_input(struct file *file, void *priv,
return -EINVAL;
inp->type = V4L2_INPUT_TYPE_CAMERA;
- sprintf(inp->name, "Camera %u", inp->index);
+ sprintf((char *)inp->name, "Camera %u", inp->index);
return 0;
}
@@ -848,11 +879,11 @@ static int vidioc_querycap(struct file *file, void *priv,
vchiq_mmal_version(dev->instance, &major, &minor);
- strcpy(cap->driver, "bm2835 mmal");
- snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d",
+ strcpy((char *)cap->driver, "bm2835 mmal");
+ snprintf((char *)cap->card, sizeof(cap->card), "mmal service %d.%d",
major, minor);
- snprintf(cap->bus_info, sizeof(cap->bus_info),
+ snprintf((char *)cap->bus_info, sizeof(cap->bus_info),
"platform:%s", dev->v4l2_dev.name);
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
@@ -871,7 +902,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
fmt = &formats[f->index];
- strlcpy(f->description, fmt->name, sizeof(f->description));
+ strlcpy((char *)f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
f->flags = fmt->flags;
@@ -928,9 +959,19 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
&f->fmt.pix.height, MIN_HEIGHT, dev->max_height,
1, 0);
f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp;
+ if (!mfmt->remove_padding) {
+ int align_mask = ((32 * mfmt->depth) >> 3) - 1;
+ /* GPU isn't removing padding, so stride is aligned to 32 */
+ f->fmt.pix.bytesperline =
+ (f->fmt.pix.bytesperline + align_mask) & ~align_mask;
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
+ "Not removing padding, so bytes/line = %d, "
+ "(align_mask %d)\n",
+ f->fmt.pix.bytesperline, align_mask);
+ }
/* Image buffer has to be padded to allow for alignment, even though
- * we then remove that padding before delivering the buffer.
+ * we sometimes then remove that padding before delivering the buffer.
*/
f->fmt.pix.sizeimage = ((f->fmt.pix.height + 15) & ~15) *
(((f->fmt.pix.width + 31) & ~31) * mfmt->depth) >> 3;
@@ -963,8 +1004,10 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
struct vchiq_mmal_port *port = NULL, *camera_port = NULL;
struct vchiq_mmal_component *encode_component = NULL;
struct mmal_fmt *mfmt = get_format(f);
+ u32 remove_padding;
- BUG_ON(!mfmt);
+ if (!mfmt)
+ return -EINVAL;
if (dev->capture.encode_component) {
v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
@@ -1031,6 +1074,12 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev,
camera_port->format.encoding = MMAL_ENCODING_RGB24;
}
+ remove_padding = mfmt->remove_padding;
+ vchiq_mmal_port_parameter_set(dev->instance,
+ camera_port,
+ MMAL_PARAMETER_NO_IMAGE_PADDING,
+ &remove_padding, sizeof(remove_padding));
+
camera_port->format.encoding_variant = 0;
camera_port->es.video.width = f->fmt.pix.width;
camera_port->es.video.height = f->fmt.pix.height;
@@ -1348,7 +1397,6 @@ static int vidioc_s_parm(struct file *file, void *priv,
{
struct bm2835_mmal_dev *dev = video_drvdata(file);
struct v4l2_fract tpf;
- struct mmal_parameter_rational fps_param;
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
@@ -1365,10 +1413,6 @@ static int vidioc_s_parm(struct file *file, void *priv,
parm->parm.capture.readbuffers = 1;
parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- fps_param.num = 0; /* Select variable fps, and then use
- * FPS_RANGE to select the actual limits.
- */
- fps_param.den = 1;
set_framerate_params(dev);
return 0;
@@ -1445,7 +1489,7 @@ static int get_num_cameras(struct vchiq_mmal_instance *instance,
int ret;
struct vchiq_mmal_component *cam_info_component;
struct mmal_parameter_camera_info_t cam_info = {0};
- int param_size = sizeof(cam_info);
+ u32 param_size = sizeof(cam_info);
int i;
/* create a camera_info component */
@@ -1504,13 +1548,12 @@ static int set_camera_parameters(struct vchiq_mmal_instance *instance,
#define MAX_SUPPORTED_ENCODINGS 20
/* MMAL instance and component init */
-static int __init mmal_init(struct bm2835_mmal_dev *dev)
+static int mmal_init(struct bm2835_mmal_dev *dev)
{
int ret;
struct mmal_es_format_local *format;
- u32 bool_true = 1;
u32 supported_encodings[MAX_SUPPORTED_ENCODINGS];
- int param_size;
+ u32 param_size;
struct vchiq_mmal_component *camera;
ret = vchiq_mmal_init(&dev->instance);
@@ -1592,11 +1635,6 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
format->es->video.frame_rate.num = 0; /* Rely on fps_range */
format->es->video.frame_rate.den = 1;
- vchiq_mmal_port_parameter_set(dev->instance,
- &camera->output[MMAL_CAMERA_PORT_VIDEO],
- MMAL_PARAMETER_NO_IMAGE_PADDING,
- &bool_true, sizeof(bool_true));
-
format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format;
format->encoding = MMAL_ENCODING_OPAQUE;
@@ -1618,11 +1656,6 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev)
dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
- vchiq_mmal_port_parameter_set(dev->instance,
- &camera->output[MMAL_CAMERA_PORT_CAPTURE],
- MMAL_PARAMETER_NO_IMAGE_PADDING,
- &bool_true, sizeof(bool_true));
-
/* get the preview component ready */
ret = vchiq_mmal_component_init(
dev->instance, "ril.video_render",
@@ -1723,8 +1756,8 @@ unreg_mmal:
return ret;
}
-static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
- struct video_device *vfd)
+static int bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
+ struct video_device *vfd)
{
int ret;
@@ -1803,7 +1836,7 @@ static struct v4l2_format default_v4l2_format = {
.fmt.pix.sizeimage = 1024 * 768,
};
-static int __init bm2835_mmal_init(void)
+static int bcm2835_mmal_probe(struct platform_device *pdev)
{
int ret;
struct bm2835_mmal_dev *dev;
@@ -1923,7 +1956,7 @@ cleanup_gdev:
return ret;
}
-static void __exit bm2835_mmal_exit(void)
+static int bcm2835_mmal_remove(struct platform_device *pdev)
{
int camera;
struct vchiq_mmal_instance *instance = gdev[0]->instance;
@@ -1933,7 +1966,16 @@ static void __exit bm2835_mmal_exit(void)
gdev[camera] = NULL;
}
vchiq_mmal_finalise(instance);
+
+ return 0;
}
-module_init(bm2835_mmal_init);
-module_exit(bm2835_mmal_exit);
+static struct platform_driver bcm2835_camera_driver = {
+ .probe = bcm2835_mmal_probe,
+ .remove = bcm2835_mmal_remove,
+ .driver = {
+ .name = "bcm2835-camera",
+ },
+};
+
+module_platform_driver(bcm2835_camera_driver)