/*
* camera image capture (abstract) bus driver
*
* Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
*
* This driver provides an interface between platform-specific camera
* busses and camera devices. It should be used if the camera is
* connected not over a "proper" bus like PCI or USB, but over a
* special bus, like, for example, the Quick Capture interface on PXA270
* SoCs. Later it should also be used for i.MX31 SoCs from Freescale.
* It can handle multiple cameras and / or multiple busses, which can
* be used, e.g., in stereo-vision applications.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/vmalloc.h>
#include <media/soc_camera.h>
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf-core.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
static LIST_HEAD(hosts);
static LIST_HEAD(devices);
static DEFINE_MUTEX(list_lock);
const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc)
{
unsigned int i;
for (i = 0; i < icd->num_formats; i++)
if (icd->formats[i].fourcc == fourcc)
return icd->formats + i;
return NULL;
}
EXPORT_SYMBOL(soc_camera_format_by_fourcc);
const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc)
{
unsigned int i;
for (i = 0; i < icd->num_user_formats; i++)
if (icd->user_formats[i].host_fmt->fourcc == fourcc)
return icd->user_formats + i;
return NULL;
}
EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
/**
* soc_camera_apply_sensor_flags() - apply platform SOCAM_SENSOR_INVERT_* flags
* @icl: camera platform parameters
* @flags: flags to be inverted according to platform configuration
* @return: resulting flags
*/
unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
unsigned long flags)
{
unsigned long f;
/* If only one of the two polarities is supported, switch to the opposite */
if (icl->flags & SOCAM_SENSOR_INVERT_HSYNC) {
f = flags & (SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW);
if (f == SOCAM_HSYNC_ACTIVE_HIGH || f == SOCAM_HSYNC_ACTIVE_LOW)
flags ^= SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_LOW;
}
if (icl->flags & SOCAM_SENSOR_INVERT_VSYNC) {
f = flags & (SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW);
if (f == SOCAM_VSYNC_ACTIVE_HIGH || f == SOCAM_VSYNC_ACTIVE_LOW)
flags ^= SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW;
}
if (icl->flags & SOCAM_SENSOR_INVERT_PCLK) {
f = flags & (SOCAM_PCLK_SAMPLE_RISING | SOCAM_PCLK_SAMPLE_FA