/*
* Driver for RJ54N1CB0C CMOS Image Sensor from Micron
*
* Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
*
* 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/delay.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-chip-ident.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
#define RJ54N1_DEV_CODE 0x0400
#define RJ54N1_DEV_CODE2 0x0401
#define RJ54N1_OUT_SEL 0x0403
#define RJ54N1_XY_OUTPUT_SIZE_S_H 0x0404
#define RJ54N1_X_OUTPUT_SIZE_S_L 0x0405
#define RJ54N1_Y_OUTPUT_SIZE_S_L 0x0406
#define RJ54N1_XY_OUTPUT_SIZE_P_H 0x0407
#define RJ54N1_X_OUTPUT_SIZE_P_L 0x0408
#define RJ54N1_Y_OUTPUT_SIZE_P_L 0x0409
#define RJ54N1_LINE_LENGTH_PCK_S_H 0x040a
#define RJ54N1_LINE_LENGTH_PCK_S_L 0x040b
#define RJ54N1_LINE_LENGTH_PCK_P_H 0x040c
#define RJ54N1_LINE_LENGTH_PCK_P_L 0x040d
#define RJ54N1_RESIZE_N 0x040e
#define RJ54N1_RESIZE_N_STEP 0x040f
#define RJ54N1_RESIZE_STEP 0x0410
#define RJ54N1_RESIZE_HOLD_H 0x0411
#define RJ54N1_RESIZE_HOLD_L 0x0412
#define RJ54N1_H_OBEN_OFS 0x0413
#define RJ54N1_V_OBEN_OFS 0x0414
#define RJ54N1_RESIZE_CONTROL 0x0415
#define RJ54N1_INC_USE_SEL_H 0x0425
#define RJ54N1_INC_USE_SEL_L 0x0426
#define RJ54N1_MIRROR_STILL_MODE 0x0427
#define RJ54N1_INIT_START 0x0428
#define RJ54N1_SCALE_1_2_LEV 0x0429
#define RJ54N1_SCALE_4_LEV 0x042a
#define RJ54N1_Y_GAIN 0x04d8
#define RJ54N1_APT_GAIN_UP 0x04fa
#define RJ54N1_RA_SEL_UL 0x0530
#define RJ54N1_BYTE_SWAP 0x0531
#define RJ54N1_OUT_SIGPO 0x053b
#define RJ54N1_FRAME_LENGTH_S_H 0x0595
#define RJ54N1_FRAME_LENGTH_S_L 0x0596
#define RJ54N1_FRAME_LENGTH_P_H 0x0597
#define RJ54N1_FRAME_LENGTH_P_L 0x0598
#define RJ54N1_IOC 0x05ef
#define RJ54N1_TG_BYPASS 0x0700
#define RJ54N1_PLL_L 0x0701
#define RJ54N1_PLL_N 0x0702
#define RJ54N1_PLL_EN 0x0704
#define RJ54N1_RATIO_TG 0x0706
#define RJ54N1_RATIO_T 0x0707
#define RJ54N1_RATIO_R 0x0708
#define RJ54N1_RAMP_TGCLK_EN 0x0709
#define RJ54N1_OCLK_DSP 0x0710
#define RJ54N1_RATIO_OP 0x0711
#define RJ54N1_RATIO_O 0x0712
#define RJ54N1_OCLK_SEL_EN 0x0713
#define RJ54N1_CLK_RST 0x0717
#define RJ54N1_RESET_STANDBY 0x0718
#define E_EXCLK (1 << 7)
#define SOFT_STDBY (1 << 4)
#define SEN_RSTX (1 << 2)
#define TG_RSTX (1 << 1)
#define DSP_RSTX (1 << 0)
#define RESIZE_HOLD_SEL (1 << 2)
#define RESIZE_GO (1 << 1)
#define RJ54N1_COLUMN_SKIP 0
#define RJ54N1_ROW_SKIP 0
#define RJ54N1_MAX_WIDTH 1600
#define RJ54N1_MAX_HEIGHT 1200
/* I2C addresses: 0x50, 0x51, 0x60, 0x61 */
/* RJ54N1CB0C has only one fixed colorspace per pixelcode */
struct rj54n1_datafmt {
enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
/* Find a data format by a pixel code in an array */
static const struct rj54n1_datafmt *rj54n1_find_datafmt(
enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt,
int n)
{
int i;
for (i = 0; i < n; i++)
if (fmt[i].code == code)
return fmt + i;
return NULL;
}
static const struct rj54n1_datafmt rj54n1_colour_fmts[] = {
{V4L2_MBUS_FMT_YUYV8_2X8_LE, V4L2_COLORSPACE_JPEG},
{V4L2_MBUS_FMT_YVYU8_2X8_LE, V4L2_COLORSPACE_JPEG},
{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
{V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
};
struct rj54n1_clock_div {
u8 ratio_tg;
u8 ratio_t;
u8 ratio_r;
u8 ratio_op;
u8 ratio_o;