/***************************************************************************
* Copyright (C) 2006-2010 by Marin Mitov *
* mitov@issp.bas.bg *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <linux/version.h>
#include <linux/stringify.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf-dma-contig.h>
#include "dt3155v4l.h"
#define DT3155_VENDOR_ID 0x8086
#define DT3155_DEVICE_ID 0x1223
/* DT3155_CHUNK_SIZE is 4M (2^22) 8 full size buffers */
#define DT3155_CHUNK_SIZE (1U << 22)
#define DT3155_COH_FLAGS (GFP_KERNEL | GFP_DMA32 | __GFP_COLD | __GFP_NOWARN)
#define DT3155_BUF_SIZE (768 * 576)
/* global initializers (for all boards) */
#ifdef CONFIG_DT3155_CCIR
static const u8 csr2_init = VT_50HZ;
#define DT3155_CURRENT_NORM V4L2_STD_625_50
static const unsigned int img_width = 768;
static const unsigned int img_height = 576;
static const unsigned int frames_per_sec = 25;
static const struct v4l2_fmtdesc frame_std[] = {
{
.index = 0,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.flags = 0,
.description = "CCIR/50Hz 8 bits gray",
.pixelformat = V4L2_PIX_FMT_GREY,
},
};
#else
static const u8 csr2_init = VT_60HZ;
#define DT3155_CURRENT_NORM V4L2_STD_525_60
static const unsigned int img_width = 640;
static const unsigned int img_height = 480;
static const unsigned int frames_per_sec = 30;
static const struct v4l2_fmtdesc frame_std[] = {
{
.index = 0,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.flags = 0,
.description = "RS-170/60Hz 8 bits gray",
.pixelformat = V4L2_PIX_FMT_GREY,
},
};
#endif
#define NUM_OF_FORMATS ARRAY_SIZE(frame_std)
static u8 config_init = ACQ_MODE_EVEN;
/**
* read_i2c_reg - reads an internal i2c register
*
* @addr: dt3155 mmio base address
* @index: index (internal address) of register to read
* @data: pointer to byte the read data will be placed in
*
* returns: zero on success or error code
*
* This function starts reading the specified (by index) register
* and busy waits for the process to finish. The result is placed
* in a byte pointed by data.
*/
static int
read_i2c_reg(void __iomem *addr, u8 index, u8 *data)
{
u32 tmp = index;
iowrite32((tmp<<17) | IIC_READ, addr + IIC_CSR2);
mmiowb();
udelay(45); /* wait at least 43 usec for NEW_CYCLE to clear */
if (ioread32(addr + IIC_CSR2) & NEW_CYCLE) {
/* error: NEW_CYCLE not cleared */
printk(KERN_ERR "dt3155: NEW_CYCLE not cleared\n");
return -EIO;
}
tmp = ioread32(addr + IIC_CSR1);
if (tmp & DIRECT_ABORT) {
/* error: DIRECT_ABORT set */
printk(KERN_ERR "dt3155: DIRECT_ABORT set\n");
/* reset DIRECT_ABORT bit */
iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
return -EIO;
}
*data = tmp>>24;
return 0;
}
/**
* write_i2c_reg - writes to an internal i2c register
*
* @addr: dt3155 mmio base address
* @index: index (internal address) of register to read
* @data: data to be written
*
* returns: zero on success or error code
*
* This function starts writting the specified (by index) register
* and busy waits for the process to finish.
*/
static int
write_i2c_reg(void __iomem *