/* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics
* Digitizer with Horizontal PLL registers
*
* Copyright (C) 2009 Texas Instruments Inc
* Author: Santiago Nunez-Corrales <[email protected]>
*
* This code is partially based upon the TVP5150 driver
* written by Mauro Carvalho Chehab ([email protected]),
* the TVP514x driver written by Vaibhav Hiremath <[email protected]>
* and the TVP7002 driver in the TI LSP 2.10.00.14. Revisions by
* Muralidharan Karicheri and Snehaprabha Narnakaje (TI).
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/v4l2-dv-timings.h>
#include <media/tvp7002.h>
#include <media/v4l2-async.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-of.h>
#include "tvp7002_reg.h"
MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver");
MODULE_AUTHOR("Santiago Nunez-Corrales <[email protected]>");
MODULE_LICENSE("GPL");
/* I2C retry attempts */
#define I2C_RETRY_COUNT (5)
/* End of registers */
#define TVP7002_EOR 0x5c
/* Read write definition for registers */
#define TVP7002_READ 0
#define TVP7002_WRITE 1
#define TVP7002_RESERVED 2
/* Interlaced vs progressive mask and shift */
#define TVP7002_IP_SHIFT 5
#define TVP7002_INPR_MASK (0x01 << TVP7002_IP_SHIFT)
/* Shift for CPL and LPF registers */
#define TVP7002_CL_SHIFT 8
#define TVP7002_CL_MASK 0x0f
/* Debug functions */
static bool debug;
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-2)");
/* Structure for register values */
struct i2c_reg_value {
u8 reg;
u8 value;
u8 type;
};
/*
* Register default values (according to tvp7002 datasheet)
* In the case of read-only registers, the value (0xff) is
* never written. R/W functionality is controlled by the
* writable bit in the register struct definition.
*/
static const struct i2c_reg_value tvp7002_init_default[] = {
{ TVP7002_CHIP_REV, 0xff, TVP7002_READ },
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE },
{ TVP7002_HPLL_PHASE_SEL, 0x80, TVP7002_WRITE },
{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
{ TVP7002_HSYNC_OUT_W, 0x60, TVP7002_WRITE },
{ TVP7002_B_FINE_GAIN, 0x00, TVP7002_WRITE },
{ TVP7002_G_FINE_GAIN, 0x00, TVP7002_WRITE },
{ TVP7002_R_FINE_GAIN, 0x00, TVP7002_WRITE },
{ TVP7002_B_FINE_OFF_MSBS, 0x80, TVP7002_WRITE },
{ TVP7002_G_FINE_OFF_MSBS, 0x80, TVP7002_WRITE },
{ TVP7002_R_FINE_OFF_MSBS, 0x80, TVP7002_WRITE },
{ TVP7002_SYNC_CTL_1, 0x20, TVP7002_WRITE },
{ TVP7002_HPLL_AND_CLAMP_CTL, 0x2e, TVP7002_WRITE },
{ TVP7002_SYNC_ON_G_THRS, 0x5d, TVP7002_WRITE },
{ TVP7002_SYNC_SEPARATOR_THRS, 0x47, TVP7002_WRITE },
{ TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE },
{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
{ TVP7002_SYNC_DETECT_STAT, 0xff, TVP7002_READ },
{ TVP7002_OUT_FORMATTER, 0x47, TVP7002_WRITE },
{ TVP7002_MISC_CTL_1, 0x01, TVP7002_WRITE },
{ TVP7002_MISC_CTL_2, 0x00, TVP7002_WRITE },
{ TVP7002_MISC_CTL_3, 0x01, TVP7002_WRITE },
{ TVP7002_IN_MUX_SEL_1, 0x00, TVP7002_WRITE },
{ TVP7002_IN_MUX_SEL_2, 0x67, TVP7002_WRITE },
{ TVP7002_B_AND_G_COARSE_GAIN, 0x77, TVP7002_WRITE },
{ TVP7002_R_COARSE_GAIN, 0x07, TVP7002_WRITE },
{ TVP7002_FINE_OFF_LSBS, 0x00, TVP7002_WRITE },
{ TVP7002_B_COARSE_OFF, 0x10, TVP7002_WRITE },
{ TVP7002_G_COARSE_OFF, 0x10, TVP7002_WRITE },
{ TVP7002_R_COARSE_OFF, 0x10, TVP7002_WRITE },
{ TVP7002_HSOUT_OUT_START, 0x08, TVP7002_WRITE },
{ TVP7002_MISC_CTL_4, 0x00, TVP7002_WRITE },
{ TVP7002_B_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ },
{ TVP7002_G_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ },
{ TVP7002_R_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ },
{ TVP7002_AUTO_LVL_CTL_ENABLE, 0x80, TVP7002_WRITE },
{ TVP7002_DGTL_ALC_OUT_MSBS, 0xff, TVP7002_READ },
{ TVP7002_AUTO_LVL_CTL_FILTER, 0x53, TVP7002_WRITE },
{ 0x29, 0x08, TVP7002_RESERVED },
{ TVP7002_FINE_CLAMP_CTL, 0x07, TVP7002_WRITE },
/* PWR_CTL is controlled only by the probe and reset functions */
{ TVP7002_PWR_CTL, 0x00, TVP7002_RESERVED },
{ TVP7002_ADC_SETUP, 0x50, TVP7002_WRITE },
{ TVP7002_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE },
{ TVP7002_SOG_CLAMP, 0x80, TVP7002_WRITE },
{ TVP7002_RGB_COARSE_CLAMP_CTL, 0x8c, TVP7002_WRITE },
{ TVP7002_SOG_COARSE_CLAMP_CTL, 0x04, TVP7002_WRITE },
{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
{ 0x32, 0x18, TVP7002_RESERVED },
{ 0x33, 0x60, TVP7002_RESERVED },
{ TVP7002_MVIS_STRIPPER_W, 0xff, TVP7002_RESERVED },
{ TVP7002_VSYNC_ALGN, 0x10, TVP7002_WRITE },
{ TVP7002_SYNC_BYPASS, 0x00, TVP7002_WRITE },
{ TVP7002_L_FRAME_STAT_LSBS, 0xff, TVP7002_READ },
{ TVP7002_L_FRAME_STAT_MSBS, 0xff, TVP7002_READ },
{ TVP7002_CLK_L_STAT_LSBS, 0xff, TVP7002_READ },
{ TVP7002_CLK_L_STAT_MSBS, 0xff, TVP7002_READ },
{ TVP7002_HSYNC_W, 0xff, TVP7002_READ },
{ TVP7002_VSYNC_W, 0xff, TVP7002_READ },
{ TVP7002_L_LENGTH_TOL, 0x03, TVP7002_WRITE },
{ 0x3e, 0x60, TVP7002_RESERVED },
{ TVP7002_VIDEO_BWTH_CTL, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x01, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x2c, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x06, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x2c, TVP7002_WRITE },
{ TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE },
{ TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
{ TVP7002_VBLK_F_0_DURATION, 0x1e, TVP7002_WRITE },
{ TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE },
{ TVP7002_FBIT_F_0_START_L_OFF, 0x00, TVP7002_WRITE },
{ TVP7002_FBIT_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
{ TVP7002_YUV_Y_G_COEF_LSBS, 0xe3, TVP7002_WRITE },
{ TVP7002_YUV_Y_G_COEF_MSBS, 0x16, TVP7002_WRITE },
{ TVP7002_YUV_Y_B_COEF_LSBS, 0x4f, TVP7002_WRITE },
{ TVP7002_YUV_Y_B_COEF_MSBS, 0x02, TVP7002_WRITE },
{ TVP7002_YUV_Y_R_COEF_LSBS, 0xce, TVP7002_WRITE },
{ TVP7002_YUV_Y_R_COEF_MSBS, 0x06, TVP7002_WRITE },
{ TVP7002_YUV_U_G_COEF_LSBS, 0xab, TVP7002_WRITE },
{ TVP7002_YUV_U_G_COEF_MSBS, 0xf3, TVP7002_WRITE },
{ TVP7002_YUV_U_B_COEF_LSBS, 0x00, TVP7002_WRITE },
{ TVP7002_YUV_U_B_COEF_MSBS, 0x10, TVP7002_WRITE },
{ TVP7002_YUV_U_R_COEF_LSBS, 0x55, TVP7002_WRITE },
{ TVP7002_YUV_U_R_COEF_MSBS, 0xfc, TVP7002_WRITE },
{ TVP7002_YUV_V_G_COEF_LSBS, 0x78, TVP7002_WRITE },
{ TVP7002_YUV_V_G_COEF_MSBS, 0xf1, TVP7002_WRITE },
{ TVP7002_YUV_V_B_COEF_LSBS, 0x88, TVP7002_WRITE },
{ TVP7002_YUV_V_B_COEF_MSBS, 0xfe, TVP7002_WRITE },
{ TVP7002_YUV_V_R_COEF_LSBS, 0x00, TVP7002_WRITE },
{ TVP7002_YUV_V_R_COEF_MSBS, 0x10, TVP7002_WRITE },
/* This signals end of register values */
{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
};
/* Register parameters for 480P */
static const struct i2c_reg_value tvp7002_parms_480P[] = {
{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE },
{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xa0, TVP7002_WRITE },
{ TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE },
{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0B, TVP7002_WRITE },
{ TVP7002_AVID_STOP_PIXEL_MSBS,