Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
c92b67fa
Commit
c92b67fa
authored
Nov 30, 2009
by
Jean-Paul Saman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Neuros OSD2 board's tvp7000 video decoder driver (WIP)
parent
83d25e2d
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1628 additions
and
3 deletions
+1628
-3
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-neuros-osd2.c
+12
-3
drivers/media/video/Kconfig
drivers/media/video/Kconfig
+9
-0
drivers/media/video/Makefile
drivers/media/video/Makefile
+1
-0
drivers/media/video/tvp7000.c
drivers/media/video/tvp7000.c
+1469
-0
drivers/media/video/tvp7000_regs.h
drivers/media/video/tvp7000_regs.h
+93
-0
include/linux/videodev2.h
include/linux/videodev2.h
+7
-0
include/media/tvp7000.h
include/media/tvp7000.h
+34
-0
include/media/v4l2-chip-ident.h
include/media/v4l2-chip-ident.h
+3
-0
No files found.
arch/arm/mach-davinci/board-neuros-osd2.c
View file @
c92b67fa
...
...
@@ -28,7 +28,14 @@
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <linux/videodev2.h>
#ifdef CONFIG_VIDEO_TVP5150
#include <media/tvp5150.h>
#endif
#ifdef CONFIG_VIDEO_TVP7000
#include <media/tvp7000.h>
#endif
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
...
...
@@ -212,7 +219,7 @@ static struct v4l2_input tvp5150_inputs[] = {
#endif
#ifdef CONFIG_VIDEO_TVP7000
static
struct
v
4l
2_input
tvp7000_inputs
[]
=
{
static
struct
v
l4
2_input
tvp7000_inputs
[]
=
{
{
.
index
=
0
,
.
name
=
"Component"
,
...
...
@@ -255,6 +262,7 @@ static struct vpfe_route tvp7000_routes[] = {
};
#endif
#if defined(CONFIG_VIDEO_TVP5150) || defined(CONFIG_VIDEO_TVP7000)
static
struct
vpfe_subdev_info
ntosd2_vpfe_sub_devs
[]
=
{
#ifdef CONFIG_VIDEO_TVP5150
{
...
...
@@ -289,7 +297,7 @@ static struct vpfe_subdev_info ntosd2_vpfe_sub_devs[] = {
.
vdpol
=
VPFE_PINPOL_POSITIVE
,
},
.
board_info
=
{
I2C_BOARD_INFO
(
"tvp7000"
,
0x
5c
),
// 0xfa
I2C_BOARD_INFO
(
"tvp7000"
,
0x
fa
),
// 0x5c
.
platform_data
=
NULL
,
// &tvp7000_pdata,
},
},
...
...
@@ -302,6 +310,7 @@ static struct vpfe_config ntosd2_vpfe_cfg = {
.
card_name
=
"DM6446 EVM"
,
.
ccdc
=
"DM6446 CCDC"
,
};
#endif
static
struct
platform_device
*
davinci_ntosd2_devices
[]
__initdata
=
{
&
davinci_fb_device
,
...
...
@@ -331,7 +340,7 @@ static struct i2c_board_info __initdata ntosd2_i2c_info[] = {
I2C_BOARD_INFO
(
"neuros_osd2_msp"
,
NTOSD2_MSP430_I2C_ADDR
),
},
{
I2C_BOARD_INFO
(
"tlv320aic3x"
,
NTOSD2_AUDIOSOC_I2C_ADDR
),
I2C_BOARD_INFO
(
"tlv320aic3x"
,
NTOSD2_AUDIOSOC_I2C_ADDR
),
},
};
...
...
drivers/media/video/Kconfig
View file @
c92b67fa
...
...
@@ -392,6 +392,15 @@ config VIDEO_TVP5150
To compile this driver as a module, choose M here: the
module will be called tvp5150.
config VIDEO_TVP7000
tristate "Texas Instruments TVP7000 video capture driver"
depends on VIDEO_V4L2 && I2C
---help---
Support for I2C bus based TVP7000 configuration.
To compile this driver as a module, choose M here: the
module will be called tvp7000.
config VIDEO_VPX3220
tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
depends on VIDEO_V4L2 && I2C
...
...
drivers/media/video/Makefile
View file @
c92b67fa
...
...
@@ -54,6 +54,7 @@ obj-$(CONFIG_VIDEO_BT866) += bt866.o
obj-$(CONFIG_VIDEO_KS0127)
+=
ks0127.o
obj-$(CONFIG_VIDEO_THS7303)
+=
ths7303.o
obj-$(CONFIG_VIDEO_VINO)
+=
indycam.o
obj-$(CONFIG_VIDEO_TVP7000)
+=
tvp7000.o
obj-$(CONFIG_VIDEO_TVP5150)
+=
tvp5150.o
obj-$(CONFIG_VIDEO_TVP514X)
+=
tvp514x.o
obj-$(CONFIG_VIDEO_MSP3400)
+=
msp3400.o
...
...
drivers/media/video/tvp7000.c
0 → 100644
View file @
c92b67fa
/*
* Copyright(C) 2006-2008 Neuros Technology International LLC.
* <www.neurostechnology.com>
* Copyright(C) 2009 M2X BV
* Jean-Paul Saman <jean-paul.saman@m2x.nl>
*
* 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, version 2 of the License.
*
* This program is distributed in the hope that, in addition to its
* original purpose to support Neuros hardware, it will be useful
* otherwise, 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.
*
****************************************************************************
*
* tvp7000 driver.
*
*/
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/tvp7000.h>
#include <mach/gpio.h>
#include "tvp7000_regs.h"
#define I2C_RETRY_COUNT 5
#define INIT_DEFAULT 0
/* Debug functions */
static
int
debug
;
module_param
(
debug
,
bool
,
0644
);
MODULE_PARM_DESC
(
debug
,
"Debug level (0-1)"
);
MODULE_DESCRIPTION
(
"Texas Instruments TVP7000 video decoder driver"
);
MODULE_AUTHOR
(
"Neuros Technology LLC"
);
MODULE_LICENSE
(
"GPL"
);
static
const
struct
tvp7000_reg
tvp7000_init_reg_seq
[]
=
{
{
/* 0x01 */
TOK_WRITE
,
TVP7000_PLL_DIVIDE_MSB
,
0x6b
},
{
/* 0x02 */
TOK_WRITE
,
TVP7000_PLL_DIVIDE_LSB
,
0x40
},
{
/* 0x03 */
TOK_WRITE
,
TVP7000_PLL_CTRL
,
0x68
},
{
/* 0x04 */
TOK_WRITE
,
TVP7000_PHASE_SELECT
,
0xb1
},
{
/* 0x05 */
TOK_WRITE
,
TVP7000_CLAMP_START
,
0x06
},
{
/* 0x06 */
TOK_WRITE
,
TVP7000_CLAMP_WIDTH
,
0x10
},
{
/* 0x07 */
TOK_WRITE
,
TVP7000_HSYNC_OUTPUT_WIDTH
,
0x60
},
{
/* 0x08 */
TOK_WRITE
,
TVP7000_BLUE_FINE_GAIN
,
0x80
},
{
/* 0x09 */
TOK_WRITE
,
TVP7000_GREEN_FINE_GAIN
,
0x80
},
{
/* 0x0A */
TOK_WRITE
,
TVP7000_RED_FINE_GAIN
,
0x80
},
{
/* 0x0B */
TOK_WRITE
,
TVP7000_BLUE_FINE_OFFSET
,
0x80
},
{
/* 0x0C */
TOK_WRITE
,
TVP7000_GREEN_FINE_OFFSET
,
0x80
},
{
/* 0x0D */
TOK_WRITE
,
TVP7000_RED_FINE_OFFSET
,
0x80
},
{
/* 0x0E */
TOK_WRITE
,
TVP7000_SYNC_CTRL_1
,
0x20
},
{
/* 0x0F */
TOK_WRITE
,
TVP7000_PLL_CLAMP_CTRL
,
0x2E
},
{
/* 0x10 */
TOK_WRITE
,
TVP7000_SYNC_ON_GREEN
,
0x85
},
{
/* 0x11 */
TOK_WRITE
,
TVP7000_SYNC_SEPARATOR
,
0x47
},
{
/* 0x12 */
TOK_WRITE
,
TVP7000_PRE_COAST
,
0x03
},
{
/* 0x13 */
TOK_WRITE
,
TVP7000_POST_COAST
,
0x0c
},
{
/* 0x15 */
TOK_WRITE
,
TVP7000_OUTPUT_FORMATTER
,
0x02
},
{
/* 0x16 */
TOK_WRITE
,
TVP7000_TEST_REG
,
0xe5
},
{
/* 0x19 */
TOK_WRITE
,
TVP7000_INPUT_MUX_1
,
0x00
},
{
/* 0x1A */
TOK_WRITE
,
TVP7000_INPUT_MUX_2
,
0x85
},
{
/* 0x1B */
TOK_WRITE
,
TVP7000_BLUE_GREEN_GAIN
,
0x55
},
{
/* 0x1C */
TOK_WRITE
,
TVP7000_RED_COARSE_GAIN
,
0x05
},
{
/* 0x1D */
TOK_WRITE
,
TVP7000_FINE_OFFSET_LSB
,
0x00
},
{
/* 0x1E */
TOK_WRITE
,
TVP7000_BLUE_COARSE_OFFSET
,
0x1f
},
{
/* 0x1F */
TOK_WRITE
,
TVP7000_GREEN_COARSE_OFFSET
,
0x1f
},
{
/* 0x20 */
TOK_WRITE
,
TVP7000_RED_COARSE_OFFSET
,
0x1f
},
{
/* 0x21 */
TOK_WRITE
,
TVP7000_HSOUT_OUTPUT_START
,
0x08
},
{
/* 0x22 */
TOK_WRITE
,
TVP7000_MISC_CTRL
,
0x08
},
{
/* 0x26 */
TOK_WRITE
,
TVP7000_AUTO_CTRL_ENABLE
,
0x80
},
{
/* 0x28 */
TOK_WRITE
,
TVP7000_AUTO_CTRL_FILTER
,
0x03
},
{
/* 0x2A */
TOK_WRITE
,
TVP7000_FINE_CLAMP_CTRL
,
0x07
},
{
/* 0x2B */
TOK_WRITE
,
TVP7000_POWER_CTRL
,
0x00
},
{
/* 0x2C */
TOK_WRITE
,
TVP7000_ADC_SETUP
,
0x50
},
{
/* 0x2D */
TOK_WRITE
,
TVP7000_COARSE_CLAMP_CTRL_1
,
0x00
},
{
/* 0x2E */
TOK_WRITE
,
TVP7000_SOG_CLAMP
,
0x80
},
{
/* 0x31 */
TOK_WRITE
,
TVP7000_ALC_PLACEMENT
,
0x18
},
{
TOK_TERM
,
0
,
0
},
};
#if INIT_DEFAULT
static
const
struct
tvp7000_reg
tvp7000_init_reg_default
[]
=
{
{
/* 0x01 */
TOK_WRITE
,
TVP7000_PLL_DIVIDE_MSB
,
0x69
},
{
/* 0x02 */
TOK_WRITE
,
TVP7000_PLL_DIVIDE_LSB
,
0xD0
},
{
/* 0x03 */
TOK_WRITE
,
TVP7000_PLL_CTRL
,
0x48
},
{
/* 0x04 */
TOK_WRITE
,
TVP7000_PHASE_SELECT
,
0x80
},
{
/* 0x05 */
TOK_WRITE
,
TVP7000_CLAMP_START
,
0x80
},
{
/* 0x06 */
TOK_WRITE
,
TVP7000_CLAMP_WIDTH
,
0x80
},
{
/* 0x07 */
TOK_WRITE
,
TVP7000_HSYNC_OUTPUT_WIDTH
,
0x20
},
{
/* 0x08 */
TOK_WRITE
,
TVP7000_BLUE_FINE_GAIN
,
0x80
},
{
/* 0x09 */
TOK_WRITE
,
TVP7000_GREEN_FINE_GAIN
,
0x80
},
{
/* 0x0A */
TOK_WRITE
,
TVP7000_RED_FINE_GAIN
,
0x80
},
{
/* 0x0B */
TOK_WRITE
,
TVP7000_BLUE_FINE_OFFSET
,
0x80
},
{
/* 0x0C */
TOK_WRITE
,
TVP7000_GREEN_FINE_OFFSET
,
0x80
},
{
/* 0x0D */
TOK_WRITE
,
TVP7000_RED_FINE_OFFSET
,
0x80
},
{
/* 0x0E */
TOK_WRITE
,
TVP7000_SYNC_CTRL_1
,
0x40
},
{
/* 0x0F */
TOK_WRITE
,
TVP7000_PLL_CLAMP_CTRL
,
0x4E
},
{
/* 0x10 */
TOK_WRITE
,
TVP7000_SYNC_ON_GREEN
,
0xB8
},
{
/* 0x11 */
TOK_WRITE
,
TVP7000_SYNC_SEPARATOR
,
0x20
},
{
/* 0x12 */
TOK_WRITE
,
TVP7000_PRE_COAST
,
0x00
},
{
/* 0x13 */
TOK_WRITE
,
TVP7000_POST_COAST
,
0x00
},
{
/* 0x15 */
TOK_WRITE
,
TVP7000_OUTPUT_FORMATTER
,
0x00
},
{
/* 0x16 */
TOK_WRITE
,
TVP7000_TEST_REG
,
0x00
},
{
/* 0x19 */
TOK_WRITE
,
TVP7000_INPUT_MUX_1
,
0x00
},
{
/* 0x1A */
TOK_WRITE
,
TVP7000_INPUT_MUX_2
,
0x00
},
{
/* 0x1B */
TOK_WRITE
,
TVP7000_BLUE_GREEN_GAIN
,
0x55
},
{
/* 0x1C */
TOK_WRITE
,
TVP7000_RED_COARSE_GAIN
,
0x05
},
{
/* 0x1D */
TOK_WRITE
,
TVP7000_FINE_OFFSET_LSB
,
0x00
},
{
/* 0x1E */
TOK_WRITE
,
TVP7000_BLUE_COARSE_OFFSET
,
0x20
},
{
/* 0x1F */
TOK_WRITE
,
TVP7000_GREEN_COARSE_OFFSET
,
0x20
},
{
/* 0x20 */
TOK_WRITE
,
TVP7000_RED_COARSE_OFFSET
,
0x20
},
{
/* 0x21 */
TOK_WRITE
,
TVP7000_HSOUT_OUTPUT_START
,
0x09
},
{
/* 0x22 */
TOK_WRITE
,
TVP7000_MISC_CTRL
,
0x00
},
{
/* 0x26 */
TOK_WRITE
,
TVP7000_AUTO_CTRL_ENABLE
,
0x00
},
{
/* 0x28 */
TOK_WRITE
,
TVP7000_AUTO_CTRL_FILTER
,
0x00
},
{
/* 0x2A */
TOK_WRITE
,
TVP7000_FINE_CLAMP_CTRL
,
0x00
},
{
/* 0x2B */
TOK_WRITE
,
TVP7000_POWER_CTRL
,
0x00
},
{
/* 0x2C */
TOK_WRITE
,
TVP7000_ADC_SETUP
,
0x00
},
{
/* 0x2D */
TOK_WRITE
,
TVP7000_COARSE_CLAMP_CTRL_1
,
0x00
},
{
/* 0x2E */
TOK_WRITE
,
TVP7000_SOG_CLAMP
,
0x00
},
{
/* 0x31 */
TOK_WRITE
,
TVP7000_ALC_PLACEMENT
,
0x00
},
{
TOK_TERM
,
0
,
0
},
};
#endif
/* Video Standards */
enum
tvp7000_std
{
VGA60HZ
=
0
,
VGA72HZ
,
VGA75HZ
,
VGA85HZ
,
SVGA56HZ
,
SVGA60HZ
,
SVGA72HZ
,
SVGA75HZ
,
SVGA85HZ
,
XGA60HZ
,
XGA70HZ
,
XGA75HZ
,
XGA85HZ
,
SXGA60HZ
,
SXGA75HZ
,
VIDEO480P60HZ
,
VIDEO576P50HZ
,
VIDEO720P60HZ
,
VIDEO720P50HZ
,
VIDEO1080I60HZ
,
VIDEO1080I50HZ
,
VIDEO1080P60HZ
,
VIDEO1080P50HZ
,
/* invalid standard */
STD_INVALID
,
};
/**
* struct tvp7000_std_info - Structure to store standard informations
* @width: Line width in pixels
* @height:Number of active lines
* @video_std: Value to write in REG_VIDEO_STD register
* @standard: v4l2 standard structure information
*/
struct
tvp7000_std_info
{
u8
plldiv_msb
;
u8
plldiv_lsb
;
u8
pll_ctrl
;
u8
phase_select_bit0
;
u8
pre_coast
;
u8
post_coast
;
u8
clamp_start
;
u8
clamp_width
;
u8
alc_placement
;
unsigned
long
width
;
unsigned
long
height
;
enum
tvp7000_std
video_std
;
struct
v4l2_standard
standard
;
};
/**
* List of image formats supported by TVP7000 decoder
* Currently we are using 8 bit mode only, but can be
* extended to 10/20 bit mode.
*/
static
const
struct
v4l2_fmtdesc
tvp7000_fmt_list
[]
=
{
{
.
index
=
0
,
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
.
flags
=
0
,
.
description
=
"8-bit UYVY 4:2:2 Format"
,
.
pixelformat
=
V4L2_PIX_FMT_UYVY
,
},
};
static
struct
tvp7000_std_info
video_info
[]
=
{
{
/* VGA standard: 640*480 resolution,60HZ refresh rate,
31.5kHZ Horizontal frequency,25.175MHZ pixel rate,
*/
.
plldiv_msb
=
0x64
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x01
,
.
width
=
640
,
.
height
=
480
,
.
video_std
=
VGA60HZ
,
.
standard
=
{
.
index
=
0
,
.
id
=
V4L2_STD_NTSC
,
.
name
=
"VGA60HZ"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
640
},
},
{
/* VGA standard: 640*480 resolution,72HZ refresh rate,
37.9kHZ Horizontal frequency,31.5MHZ pixel rate,
*/
.
plldiv_msb
=
0x68
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x58
,
.
phase_select_bit0
=
0x01
,
.
width
=
640
,
.
height
=
480
,
.
video_std
=
VGA72HZ
,
.
standard
=
{
.
index
=
1
,
.
id
=
V4L2_STD_NTSC
,
.
name
=
"VGA72HZ"
,
.
frameperiod
=
{
1001
,
72000
},
.
framelines
=
640
},
},
{
/* VGA standard: 640*480 resolution,75HZ refresh rate,
37.5kHZ Horizontal frequency,31.5MHZ pixel rate,
*/
.
plldiv_msb
=
0x69
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x58
,
.
phase_select_bit0
=
0x01
,
.
width
=
640
,
.
height
=
480
,
.
video_std
=
VGA75HZ
,
.
standard
=
{
.
index
=
2
,
.
id
=
V4L2_STD_NTSC
,
.
name
=
"VGA75HZ"
,
.
frameperiod
=
{
1001
,
75000
},
.
framelines
=
640
},
},
{
/* VGA standard: 640*480 resolution,85HZ refresh rate,
43.3kHZ Horizontal frequency,36MHZ pixel rate,
*/
.
plldiv_msb
=
0x34
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x00
,
.
width
=
640
,
.
height
=
480
,
.
video_std
=
VGA85HZ
,
.
standard
=
{
.
index
=
3
,
.
id
=
V4L2_STD_NTSC
,
.
name
=
"VGA85HZ"
,
.
frameperiod
=
{
1001
,
85000
},
.
framelines
=
640
},
},
{
/* SVGA standard: 800*600 resolution,56HZ refresh rate,
35.1kHZ Horizontal frequency,36MHZ pixel rate,
*/
.
plldiv_msb
=
0x40
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x00
,
.
width
=
800
,
.
height
=
600
,
.
video_std
=
SVGA56HZ
,
.
standard
=
{
.
index
=
4
,
.
id
=
V4L2_STD_PAL
,
.
name
=
"SVGA56HZ"
,
.
frameperiod
=
{
1001
,
56000
},
.
framelines
=
800
},
},
{
/* SVGA standard: 800*600 resolution,60HZ refresh rate,
37.9kHZ Horizontal frequency,40MHZ pixel rate,
*/
.
plldiv_msb
=
0x42
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x00
,
.
width
=
800
,
.
height
=
600
,
.
video_std
=
SVGA60HZ
,
.
standard
=
{
.
index
=
5
,
.
id
=
V4L2_STD_PAL
,
.
name
=
"SVGA60HZ"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
800
},
},
{
/* SVGA standard: 800*600 resolution,72HZ refresh rate,
48.1kHZ Horizontal frequency,50MHZ pixel rate,
*/
.
plldiv_msb
=
0x41
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x00
,
.
width
=
800
,
.
height
=
600
,
.
video_std
=
SVGA72HZ
,
.
standard
=
{
.
index
=
6
,
.
id
=
V4L2_STD_PAL
,
.
name
=
"SVGA72HZ"
,
.
frameperiod
=
{
1001
,
72000
},
.
framelines
=
800
},
},
{
/* SVGA standard: 800*600 resolution,75HZ refresh rate,
46.9kHZ Horizontal frequency,49.5MHZ pixel rate,
*/
.
plldiv_msb
=
0x42
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x00
,
.
width
=
800
,
.
height
=
600
,
.
video_std
=
SVGA75HZ
,
.
standard
=
{
.
index
=
7
,
.
id
=
V4L2_STD_PAL
,
.
name
=
"SVGA75HZ"
,
.
frameperiod
=
{
1001
,
75000
},
.
framelines
=
800
},
},
{
/* SVGA standard: 800*600 resolution,85HZ refresh rate,
53.7kHZ Horizontal frequency,56.25MHZ pixel rate,
*/
.
plldiv_msb
=
0x41
,
.
plldiv_lsb
=
0x80
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x00
,
.
width
=
800
,
.
height
=
600
,
.
video_std
=
SVGA85HZ
,
.
standard
=
{
.
index
=
8
,
.
id
=
V4L2_STD_PAL
,
.
name
=
"SVGA85HZ"
,
.
frameperiod
=
{
1001
,
85000
},
.
framelines
=
800
},
},
{
/* XGA standard: 1024*768 resolution,60HZ refresh rate,
48.4kHZ Horizontal frequency,65MHZ pixel rate,
*/
.
plldiv_msb
=
0x54
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x58
,
.
phase_select_bit0
=
0x00
,
.
width
=
1024
,
.
height
=
768
,
.
video_std
=
XGA60HZ
,
.
standard
=
{
.
index
=
9
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"XGA60HZ"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
1024
},
},
{
/* XGA standard: 1024*768 resolution,70HZ refresh rate,
56.5kHZ Horizontal frequency,75MHZ pixel rate,
*/
.
plldiv_msb
=
0x53
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
width
=
1024
,
.
height
=
768
,
.
video_std
=
XGA70HZ
,
.
standard
=
{
.
index
=
10
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"XGA70HZ"
,
.
frameperiod
=
{
1001
,
70000
},
.
framelines
=
1024
},
},
{
/* XGA standard: 1024*768 resolution,75HZ refresh rate,
60kHZ Horizontal frequency,78.75MHZ pixel rate,
*/
.
plldiv_msb
=
0x52
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
width
=
1024
,
.
height
=
768
,
.
video_std
=
XGA75HZ
,
.
standard
=
{
.
index
=
11
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"XGA75HZ"
,
.
frameperiod
=
{
1001
,
75000
},
.
framelines
=
1024
},
},
{
/* XGA standard: 1024*768 resolution,85HZ refresh rate,
68.7kHZ Horizontal frequency,94.5MHZ pixel rate,
*/
.
plldiv_msb
=
0x56
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
width
=
1024
,
.
height
=
768
,
.
video_std
=
XGA85HZ
,
.
standard
=
{
.
index
=
12
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"XGA85HZ"
,
.
frameperiod
=
{
1001
,
85000
},
.
framelines
=
1024
},
},
{
/* SXGA standard: 1280*1024 resolution,60HZ refresh rate,
64kHZ Horizontal frequency,108MHZ pixel rate,
*/
.
plldiv_msb
=
0x69
,
.
plldiv_lsb
=
0x80
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
width
=
1280
,
.
height
=
1024
,
.
video_std
=
SXGA60HZ
,
.
standard
=
{
.
index
=
13
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"SXGA60HZ"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
1024
},
},
{
/* SXGA standard: 1280*1024 resolution,75HZ refresh rate,
80kHZ Horizontal frequency,135MHZ pixel rate,
*/
.
plldiv_msb
=
0x69
,
.
plldiv_lsb
=
0x80
,
.
pll_ctrl
=
0x98
,
.
phase_select_bit0
=
0x00
,
.
width
=
1280
,
.
height
=
1024
,
.
video_std
=
SXGA75HZ
,
.
standard
=
{
.
index
=
14
,
.
id
=
V4L2_STD_HD_1080P
,
.
name
=
"SXGA75HZ"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
1280
},
},
{
/* Video standard: 720*480p resolution,60HZ refresh rate,
31.468kHZ Horizontal frequency,27MHZ pixel rate.
*/
.
plldiv_msb
=
0x6B
,
.
plldiv_lsb
=
0x40
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x01
,
.
pre_coast
=
0x03
,
.
post_coast
=
0x0c
,
.
clamp_start
=
0x06
,
.
clamp_width
=
0x10
,
.
alc_placement
=
0x18
,
.
video_std
=
VIDEO480P60HZ
,
.
width
=
720
,
.
height
=
480
,
.
standard
=
{
.
index
=
15
,
.
id
=
V4L2_STD_HD_480P
,
.
name
=
"480P"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
720
},
},
{
/* Video standard: 720*576p resolution,50HZ refresh rate,
31.25kHZ Horizontal frequency,27MHZ pixel rate.
*/
.
plldiv_msb
=
0x6C
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0x68
,
.
phase_select_bit0
=
0x01
,
.
pre_coast
=
0x03
,
.
post_coast
=
0x0c
,
.
clamp_start
=
0x06
,
.
clamp_width
=
0x10
,
.
alc_placement
=
0x18
,
.
width
=
720
,
.
height
=
576
,
.
video_std
=
VIDEO576P50HZ
,
.
standard
=
{
.
index
=
16
,
.
id
=
V4L2_STD_HD_576P
,
.
name
=
"576P"
,
.
frameperiod
=
{
1001
,
50000
},
.
framelines
=
625
},
},
{
/* Video standard: 1280*720p resolution,60HZ refresh rate,
45kHZ Horizontal frequency,74.25MHZ pixel rate.
*/
.
plldiv_msb
=
0x67
,
.
plldiv_lsb
=
0x20
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
pre_coast
=
0x0
,
.
post_coast
=
0x0
,
.
clamp_start
=
0x32
,
.
clamp_width
=
0x20
,
.
alc_placement
=
0x5a
,
.
width
=
1280
,
.
height
=
720
,
.
video_std
=
VIDEO720P60HZ
,
.
standard
=
{
.
index
=
17
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"720P"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
1185
},
},
{
/* Video standard: 1280*720p resolution,50HZ refresh rate,
37.5kHZ Horizontal frequency,74.25MHZ pixel rate.
*/
.
plldiv_msb
=
0x7B
,
.
plldiv_lsb
=
0xC0
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
pre_coast
=
0x0
,
.
post_coast
=
0x0
,
.
clamp_start
=
0x32
,
.
clamp_width
=
0x20
,
.
alc_placement
=
0x5a
,
.
width
=
1280
,
.
height
=
720
,
.
video_std
=
VIDEO720P50HZ
,
.
standard
=
{
.
index
=
18
,
.
id
=
V4L2_STD_HD_720P
,
.
name
=
"720P"
,
.
frameperiod
=
{
1001
,
50000
},
.
framelines
=
1185
},
},
{
/* Video standard: 1920*1080i resolution,60HZ refresh rate,
33.75kHZ Horizontal frequency,74.25MHZ pixel rate.
*/
.
plldiv_msb
=
0x89
,
.
plldiv_lsb
=
0x80
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
pre_coast
=
0x03
,
.
post_coast
=
0x0
,
.
clamp_start
=
0x32
,
.
clamp_width
=
0x20
,
.
alc_placement
=
0x5a
,
.
width
=
1920
,
.
height
=
1080
,
.
video_std
=
VIDEO1080I60HZ
,
.
standard
=
{
.
index
=
19
,
.
id
=
V4L2_STD_HD_1080I
,
.
name
=
"1080I"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
1825
},
},
{
/* Video standard: 1920*1080i resolution,50HZ refresh rate,
28.125kHZ Horizontal frequency,74.25MHZ pixel rate.
*/
.
plldiv_msb
=
0xA5
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0xA8
,
.
phase_select_bit0
=
0x00
,
.
pre_coast
=
0x03
,
.
post_coast
=
0x0
,
.
clamp_start
=
0x32
,
.
clamp_width
=
0x20
,
.
alc_placement
=
0x5a
,
.
width
=
1920
,
.
height
=
1080
,
.
video_std
=
VIDEO1080I50HZ
,
.
standard
=
{
.
index
=
20
,
.
id
=
V4L2_STD_HD_1080I
,
.
name
=
"1080I"
,
.
frameperiod
=
{
1001
,
50000
},
.
framelines
=
1825
},
},
#ifndef MACH_NEUROS_OSD2
{
/* Video standard: 1920*1080p resolution,60HZ refresh rate,
67.5kHZ Horizontal frequency,148.5MHZ pixel rate.
*/
.
plldiv_msb
=
0x89
,
.
plldiv_lsb
=
0x80
,
.
pll_ctrl
=
0xD8
,
.
phase_select_bit0
=
0x00
,
.
pre_coast
=
0x0
,
.
post_coast
=
0x0
,
.
clamp_start
=
0x32
,
.
clamp_width
=
0x20
,
.
alc_placement
=
0x5a
,
.
width
=
1920
,
.
height
=
1080
,
.
video_std
=
VIDEO1080P60HZ
,
.
standard
=
{
.
index
=
21
,
.
id
=
V4L2_STD_HD_1080P
,
.
name
=
"1080P"
,
.
frameperiod
=
{
1001
,
60000
},
.
framelines
=
1825
},
},
{
/* Video standard: 1920*1080p resolution,50HZ refresh rate,
56.25kHZ Horizontal frequency,148.5MHZ pixel rate.
*/
.
plldiv_msb
=
0xA5
,
.
plldiv_lsb
=
0x00
,
.
pll_ctrl
=
0xD8
,
.
phase_select_bit0
=
0x00
,
.
pre_coast
=
0x0
,
.
post_coast
=
0x0
,
.
clamp_start
=
0x32
,
.
clamp_width
=
0x20
,
.
alc_placement
=
0x5a
,
.
width
=
1920
,
.
height
=
1080
,
.
video_std
=
VIDEO1080P50HZ
,
.
standard
=
{
.
index
=
22
,
.
id
=
V4L2_STD_HD_1080P
,
.
name
=
"1080P"
,
.
frameperiod
=
{
1001
,
50000
},
.
framelines
=
1825
},
},
#endif
};
/**
* struct tvp7000_decoder - TVP7000 decoder object
* @sd: Subdevice Slave handle
* @tvp7000_regs: copy of hw's regs with preset values.
* @pdata: Board specific
* @ver: Chip version
* @streaming: TVP7000 decoder streaming - enabled or disabled.
* @pix: Current pixel format
* @num_fmts: Number of formats
* @fmt_list: Format list
* @current_std: Current standard
* @num_stds: Number of standards
* @std_list: Standards list
* @input: Input routing at chip level
* @output: Output routing at chip level
*/
struct
tvp7000_decoder
{
struct
v4l2_subdev
sd
;
struct
tvp7000_reg
tvp7000_regs
[
ARRAY_SIZE
(
tvp7000_init_reg_seq
)];
const
struct
tvp7000_platform_data
*
pdata
;
int
ver
;
int
streaming
;
struct
v4l2_pix_format
pix
;
int
num_fmts
;
const
struct
v4l2_fmtdesc
*
fmt_list
;
enum
tvp7000_std
current_std
;
int
num_stds
;
struct
tvp7000_std_info
*
std_list
;
/* Input and Output Routing parameters */
u32
input
;
u32
output
;
};
static
inline
struct
tvp7000_decoder
*
to_decoder
(
struct
v4l2_subdev
*
sd
)
{
return
container_of
(
sd
,
struct
tvp7000_decoder
,
sd
);
}
/**
* tvp7000_read_reg() - Read a value from a register in an TVP7000.
* @sd: ptr to v4l2_subdev struct
* @reg: TVP7000 register address
*
* Returns value read if successful, or non-zero (-1) otherwise.
*/
static
int
tvp7000_read_reg
(
struct
v4l2_subdev
*
sd
,
u8
reg
)
{
int
err
,
retry
=
0
;
struct
i2c_client
*
client
=
v4l2_get_subdevdata
(
sd
);
read_again:
err
=
i2c_smbus_read_byte_data
(
client
,
reg
);
if
(
err
==
-
1
)
{
if
(
retry
<=
I2C_RETRY_COUNT
)
{
v4l2_warn
(
sd
,
"Read: retry ... %d
\n
"
,
retry
);
retry
++
;
msleep_interruptible
(
10
);
goto
read_again
;
}
}
return
err
;
}
/**
* dump_reg() - dump the register content of TVP7000.
* @sd: ptr to v4l2_subdev struct
* @reg: TVP7000 register address
*/
static
void
dump_reg
(
struct
v4l2_subdev
*
sd
,
u8
reg
)
{
u32
val
;
val
=
tvp7000_read_reg
(
sd
,
reg
);
v4l2_info
(
sd
,
"Reg(0x%.2X): 0x%.2X
\n
"
,
reg
,
val
);
}
/**
* tvp7000_write_reg() - Write a value to a register in TVP7000
* @sd: ptr to v4l2_subdev struct
* @reg: TVP7000 register address
* @val: value to be written to the register
*
* Write a value to a register in an TVP7000 decoder device.
* Returns zero if successful, or non-zero otherwise.
*/
static
int
tvp7000_write_reg
(
struct
v4l2_subdev
*
sd
,
u8
reg
,
u8
val
)
{
int
err
,
retry
=
0
;
struct
i2c_client
*
client
=
v4l2_get_subdevdata
(
sd
);
write_again:
err
=
i2c_smbus_write_byte_data
(
client
,
reg
,
val
);
if
(
err
)
{
if
(
retry
<=
I2C_RETRY_COUNT
)
{
v4l2_warn
(
sd
,
"Write: retry ... %d
\n
"
,
retry
);
retry
++
;
msleep_interruptible
(
10
);
goto
write_again
;
}
}
return
err
;
}
static
void
tvp7000_device_power_on
(
bool
on
)
{
#define HD_CAP_GPIO GPIO(39)
s8
level
=
(
on
==
true
)
?
0
:
1
;
/* enable the GPIO(39) direction mode as output */
gpio_direction_output
(
HD_CAP_GPIO
,
level
);
/* when on == true */
/* set the Reset pin level as High for 5ms */
gpio_set_value
(
HD_CAP_GPIO
,
level
);
mdelay
(
5
);
/* pull down the Reset pin level for 5us,
reset the chip(Reset pin active in low) */
gpio_set_value
(
HD_CAP_GPIO
,
!
level
);
udelay
(
5
);
/* pull up the Reset pin and delay for 5us,
now,tvp7000 is power up */
gpio_set_value
(
HD_CAP_GPIO
,
level
);
udelay
(
5
);
#undef HD_CAP_GPIO
}
static
int
tvp7000_setup_video_standard
(
struct
v4l2_subdev
*
sd
,
const
struct
tvp7000_std_info
*
std
)
{
int
err
=
0
;
int
val
;
if
(
std
==
NULL
)
return
-
EINVAL
;
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_PLL_DIVIDE_MSB
,
std
->
plldiv_msb
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_PLL_DIVIDE_LSB
,
std
->
plldiv_lsb
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_PLL_CTRL
,
std
->
pll_ctrl
);
val
=
tvp7000_read_reg
(
sd
,
TVP7000_PHASE_SELECT
);
val
&=
~
0x01
;
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_PHASE_SELECT
,
(
std
->
phase_select_bit0
&
0x01
)
|
val
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_PRE_COAST
,
std
->
pre_coast
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_POST_COAST
,
std
->
post_coast
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_CLAMP_START
,
std
->
clamp_start
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_CLAMP_WIDTH
,
std
->
clamp_width
);
err
|=
tvp7000_write_reg
(
sd
,
TVP7000_ALC_PLACEMENT
,
std
->
alc_placement
);
return
err
;
}
static
inline
int
tvp7000_selmux
(
struct
v4l2_subdev
*
sd
)
{
if
(
tvp7000_write_reg
(
sd
,
TVP7000_INPUT_MUX_1
,
0
))
// set channel 1
return
-
1
;
return
0
;
}
static
int
input_signal_exist
(
struct
v4l2_subdev
*
sd
)
{
int
val
;
val
=
tvp7000_read_reg
(
sd
,
TVP7000_SYNC_DETECT_STATUS
);
if
((
val
&
0x80
)
&&
(
val
&
0x10
))
return
0
;
return
-
1
;
}
/**
* tvp7000_write_regs() : Initializes a list of TVP7000 registers
* @sd: ptr to v4l2_subdev struct
* @reglist: list of TVP7000 registers and values
*
* Initializes a list of TVP7000 registers:-
* if token is TOK_TERM, then entire write operation terminates
* if token is TOK_DELAY, then a delay of 'val' msec is introduced
* if token is TOK_SKIP, then the register write is skipped
* if token is TOK_WRITE, then the register write is performed
* Returns zero if successful, or non-zero otherwise.
*/
static
int
tvp7000_write_regs
(
struct
v4l2_subdev
*
sd
,
const
struct
tvp7000_reg
reglist
[])
{
int
err
;
const
struct
tvp7000_reg
*
next
=
reglist
;
for
(;
next
->
token
!=
TOK_TERM
;
next
++
)
{
if
(
next
->
token
==
TOK_DELAY
)
{
msleep
(
next
->
val
);
continue
;
}
if
(
next
->
token
==
TOK_SKIP
)
continue
;
err
=
tvp7000_write_reg
(
sd
,
next
->
reg
,
(
u8
)
next
->
val
);
if
(
err
)
{
v4l2_err
(
sd
,
"Write failed. Err[%d]
\n
"
,
err
);
return
err
;
}
}
return
0
;
}
/**
* tvp7000_configure() - Configure the TVP7000 registers
* @sd: ptr to v4l2_subdev struct
* @decoder: ptr to tvp7000_decoder structure
*
* Returns zero if successful, or non-zero otherwise.
*/
static
int
tvp7000_configure
(
struct
v4l2_subdev
*
sd
,
struct
tvp7000_decoder
*
decoder
)
{
int
err
;
#if INIT_DEFAULT
/* initialize TVP7000 as its default values */
tvp7000_write_regs
(
sd
,
tvp7000_init_reg_default
);
#endif
/* common register initialization */
err
=
tvp7000_write_regs
(
sd
,
decoder
->
tvp7000_regs
);
if
(
err
)
return
err
;
if
(
tvp7000_selmux
(
sd
))
return
-
1
;
#if 0
if (debug)
tvp7000_reg_dump(sd);
#endif
return
0
;
}
static
int
tvp7000_g_input_status
(
struct
v4l2_subdev
*
sd
,
u32
*
status
)
{
if
(
input_signal_exist
(
sd
)
<
0
)
return
-
EINVAL
;
*
status
=
TVP7000_COMPONENT
;
return
0
;
}
static
int
tvp7000_s_routing
(
struct
v4l2_subdev
*
sd
,
u32
input
,
u32
output
,
u32
config
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
int
err
;
decoder
->
input
=
input
;
decoder
->
output
=
output
;
if
(
decoder
->
input
!=
TVP7000_COMPONENT
)
return
-
EINVAL
;
err
=
tvp7000_configure
(
sd
,
decoder
);
if
(
err
)
return
-
EBUSY
;
v4l2_dbg
(
1
,
debug
,
sd
,
"Selecting video route: route input=%i, output=%i "
"=> tvp7000 input=%i
\n
"
,
decoder
->
input
,
decoder
->
output
,
input
);
return
0
;
}
static
int
tvp7000_reset
(
struct
v4l2_subdev
*
sd
,
u32
val
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
int
err
=
tvp7000_configure
(
sd
,
decoder
);
if
(
err
)
printk
(
KERN_ERR
"tvp7000_reset failed
\n
"
);
return
err
;
}
/**
* tvp7000_querystd() - V4L2 decoder interface handler for querystd
* @sd: pointer to standard V4L2 sub-device structure
* @std_id: standard V4L2 std_id ioctl enum
*
* Returns the current standard detected by TVP5146/47. If no active input is
* detected, returns -EINVAL
*/
static
int
tvp7000_querystd
(
struct
v4l2_subdev
*
sd
,
v4l2_std_id
*
std_id
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
enum
tvp7000_std
current_std
;
if
(
std_id
==
NULL
)
return
-
EINVAL
;
/* get the current standard */
current_std
=
decoder
->
current_std
;
if
(
current_std
==
STD_INVALID
)
return
-
EINVAL
;
if
(
decoder
->
input
!=
TVP7000_COMPONENT
)
return
-
EINVAL
;
if
(
input_signal_exist
(
sd
)
<
0
)
return
-
EINVAL
;
decoder
->
current_std
=
current_std
;
*
std_id
=
decoder
->
std_list
[
current_std
].
standard
.
id
;
v4l2_dbg
(
1
,
debug
,
sd
,
"Current STD: %s"
,
decoder
->
std_list
[
current_std
].
standard
.
name
);
return
0
;
}
static
int
tvp7000_s_std
(
struct
v4l2_subdev
*
sd
,
v4l2_std_id
std
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
enum
tvp7000_std
mode
=
STD_INVALID
;
int
ret
,
i
;
for
(
i
=
0
;
i
<
decoder
->
num_stds
;
i
++
)
if
(
std
&
decoder
->
std_list
[
i
].
standard
.
id
)
break
;
if
((
i
==
decoder
->
num_stds
)
||
(
i
==
STD_INVALID
))
return
-
EINVAL
;
switch
(
i
)
{
case
V4L2_STD_HD_480P
:
mode
=
VIDEO480P60HZ
;
break
;
case
V4L2_STD_HD_576P
:
mode
=
VIDEO576P50HZ
;
break
;
case
V4L2_STD_HD_720P
:
mode
=
VIDEO720P60HZ
;
break
;
case
V4L2_STD_HD_1080I
:
mode
=
VIDEO1080I60HZ
;
break
;
default:
return
-
EINVAL
;
}
ret
=
tvp7000_setup_video_standard
(
sd
,
&
decoder
->
std_list
[
mode
]);
if
(
!
ret
)
return
-
EIO
;
decoder
->
current_std
=
mode
;
v4l2_dbg
(
1
,
debug
,
sd
,
"Standard set to: %s"
,
decoder
->
std_list
[
i
].
standard
.
name
);
return
ret
;
}
/**
* tvp7000_enum_fmt_cap() - V4L2 decoder interface handler for enum_fmt
* @sd: pointer to standard V4L2 sub-device structure
* @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure
*
* Implement the VIDIOC_ENUM_FMT ioctl to enumerate supported formats
*/
static
int
tvp7000_enum_fmt_cap
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_fmtdesc
*
fmt
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
int
index
;
if
(
fmt
==
NULL
)
return
-
EINVAL
;
index
=
fmt
->
index
;
if
((
index
>=
decoder
->
num_fmts
)
||
(
index
<
0
))
/* Index out of bound */
return
-
EINVAL
;
if
(
fmt
->
type
!=
V4L2_BUF_TYPE_VIDEO_CAPTURE
)
/* only capture is supported */
return
-
EINVAL
;
memcpy
(
fmt
,
&
decoder
->
fmt_list
[
index
],
sizeof
(
struct
v4l2_fmtdesc
));
v4l2_dbg
(
1
,
debug
,
sd
,
"Current FMT: index - %d (%s)"
,
decoder
->
fmt_list
[
index
].
index
,
decoder
->
fmt_list
[
index
].
description
);
return
0
;
}
/**
* tvp7000_try_fmt_cap() - V4L2 decoder interface handler for try_fmt
* @sd: pointer to standard V4L2 sub-device structure
* @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure
*
* Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This
* ioctl is used to negotiate the image capture size and pixel format
* without actually making it take effect.
*/
static
int
tvp7000_try_fmt_cap
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_format
*
f
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
int
ifmt
;
struct
v4l2_pix_format
*
pix
;
enum
tvp7000_std
current_std
;
if
(
f
==
NULL
)
return
-
EINVAL
;
if
(
f
->
type
!=
V4L2_BUF_TYPE_VIDEO_CAPTURE
)
/* only capture is supported */
f
->
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
pix
=
&
f
->
fmt
.
pix
;
/* Calculate height and width based on current standard */
current_std
=
decoder
->
current_std
;
if
(
current_std
==
STD_INVALID
)
return
-
EINVAL
;
pix
->
width
=
decoder
->
std_list
[
current_std
].
width
;
pix
->
height
=
decoder
->
std_list
[
current_std
].
height
;
for
(
ifmt
=
0
;
ifmt
<
decoder
->
num_fmts
;
ifmt
++
)
{
if
(
pix
->
pixelformat
==
decoder
->
fmt_list
[
ifmt
].
pixelformat
)
break
;
}
if
(
ifmt
==
decoder
->
num_fmts
)
/* None of the format matched, select default */
ifmt
=
0
;
pix
->
pixelformat
=
decoder
->
fmt_list
[
ifmt
].
pixelformat
;
pix
->
field
=
V4L2_FIELD_INTERLACED
;
pix
->
bytesperline
=
pix
->
width
*
2
;
pix
->
sizeimage
=
pix
->
bytesperline
*
pix
->
height
;
pix
->
colorspace
=
V4L2_COLORSPACE_SMPTE170M
;
pix
->
priv
=
0
;
v4l2_dbg
(
1
,
debug
,
sd
,
"Try FMT: pixelformat - %s, bytesperline - %d"
"Width - %d, Height - %d"
,
decoder
->
fmt_list
[
ifmt
].
description
,
pix
->
bytesperline
,
pix
->
width
,
pix
->
height
);
return
0
;
}
/**
* tvp7000_s_fmt_cap() - V4L2 decoder interface handler for s_fmt
* @sd: pointer to standard V4L2 sub-device structure
* @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure
*
* If the requested format is supported, configures the HW to use that
* format, returns error code if format not supported or HW can't be
* correctly configured.
*/
static
int
tvp7000_s_fmt_cap
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_format
*
f
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
struct
v4l2_pix_format
*
pix
;
int
rval
;
if
(
f
==
NULL
)
return
-
EINVAL
;
if
(
f
->
type
!=
V4L2_BUF_TYPE_VIDEO_CAPTURE
)
/* only capture is supported */
return
-
EINVAL
;
pix
=
&
f
->
fmt
.
pix
;
rval
=
tvp7000_try_fmt_cap
(
sd
,
f
);
if
(
rval
)
return
rval
;
decoder
->
pix
=
*
pix
;
return
rval
;
}
/**
* tvp7000_g_fmt_cap() - V4L2 decoder interface handler for tvp7000_g_fmt_cap
* @sd: pointer to standard V4L2 sub-device structure
* @f: pointer to standard V4L2 v4l2_format structure
*
* Returns the decoder's current pixel format in the v4l2_format
* parameter.
*/
static
int
tvp7000_g_fmt_cap
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_format
*
f
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
if
(
f
==
NULL
)
return
-
EINVAL
;
if
(
f
->
type
!=
V4L2_BUF_TYPE_VIDEO_CAPTURE
)
/* only capture is supported */
return
-
EINVAL
;
f
->
fmt
.
pix
=
decoder
->
pix
;
v4l2_dbg
(
1
,
debug
,
sd
,
"Current FMT: bytesperline - %d"
"Width - %d, Height - %d"
,
decoder
->
pix
.
bytesperline
,
decoder
->
pix
.
width
,
decoder
->
pix
.
height
);
return
0
;
}
/**
* tvp7000_g_parm() - V4L2 decoder interface handler for g_parm
* @sd: pointer to standard V4L2 sub-device structure
* @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
*
* Returns the decoder's video CAPTURE parameters.
*/
static
int
tvp7000_g_parm
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_streamparm
*
a
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
struct
v4l2_captureparm
*
cparm
;
enum
tvp7000_std
current_std
;
if
(
a
==
NULL
)
return
-
EINVAL
;
if
(
a
->
type
!=
V4L2_BUF_TYPE_VIDEO_CAPTURE
)
/* only capture is supported */
return
-
EINVAL
;
memset
(
a
,
0
,
sizeof
(
*
a
));
a
->
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
/* get the current standard */
current_std
=
decoder
->
current_std
;
if
(
current_std
==
STD_INVALID
)
return
-
EINVAL
;
cparm
=
&
a
->
parm
.
capture
;
cparm
->
capability
=
V4L2_CAP_TIMEPERFRAME
;
cparm
->
timeperframe
=
decoder
->
std_list
[
current_std
].
standard
.
frameperiod
;
return
0
;
}
/**
* tvp7000_s_parm() - V4L2 decoder interface handler for s_parm
* @sd: pointer to standard V4L2 sub-device structure
* @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
*
* Configures the decoder to use the input parameters, if possible. If
* not possible, returns the appropriate error code.
*/
static
int
tvp7000_s_parm
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_streamparm
*
a
)
{
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
struct
v4l2_fract
*
timeperframe
;
enum
tvp7000_std
current_std
;
if
(
a
==
NULL
)
return
-
EINVAL
;
if
(
a
->
type
!=
V4L2_BUF_TYPE_VIDEO_CAPTURE
)
/* only capture is supported */
return
-
EINVAL
;
timeperframe
=
&
a
->
parm
.
capture
.
timeperframe
;
/* get the current standard */
current_std
=
decoder
->
current_std
;
if
(
current_std
==
STD_INVALID
)
return
-
EINVAL
;
*
timeperframe
=
decoder
->
std_list
[
current_std
].
standard
.
frameperiod
;
return
0
;
}
/**
* tvp7000_s_stream() - V4L2 decoder i/f handler for s_stream
* @sd: pointer to standard V4L2 sub-device structure
* @enable: streaming enable or disable
*
* Sets streaming to enable or disable, if possible.
*/
static
int
tvp7000_s_stream
(
struct
v4l2_subdev
*
sd
,
int
enable
)
{
int
err
=
0
;
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
if
(
decoder
->
streaming
==
enable
)
return
0
;
switch
(
enable
)
{
case
0
:
{
/* Power Down Sequence */
tvp7000_device_power_on
(
false
);
decoder
->
streaming
=
enable
;
break
;
}
case
1
:
{
int
err
;
tvp7000_device_power_on
(
true
);
err
=
tvp7000_configure
(
sd
,
decoder
);
if
(
err
)
{
v4l2_err
(
sd
,
"Unable to configure decoder
\n
"
);
return
-
EBUSY
;
}
decoder
->
streaming
=
enable
;
break
;
}
default:
err
=
-
ENODEV
;
break
;
}
return
err
;
}
static
int
tvp7000_g_chip_ident
(
struct
v4l2_subdev
*
sd
,
struct
v4l2_dbg_chip_ident
*
chip
)
{
int
rev
;
struct
i2c_client
*
client
=
v4l2_get_subdevdata
(
sd
);
rev
=
tvp7000_read_reg
(
sd
,
TVP7000_CHIP_REVISION
);
printk
(
KERN_INFO
"tvp7000 detected Revision: %d
\n
"
,
rev
);
return
v4l2_chip_ident_i2c_client
(
client
,
chip
,
V4L2_IDENT_TVP7000
,
rev
);
}
static
const
struct
v4l2_subdev_core_ops
tvp7000_core_ops
=
{
.
reset
=
tvp7000_reset
,
.
s_std
=
tvp7000_s_std
,
.
g_chip_ident
=
tvp7000_g_chip_ident
,
};
static
const
struct
v4l2_subdev_video_ops
tvp7000_video_ops
=
{
.
s_routing
=
tvp7000_s_routing
,
.
querystd
=
tvp7000_querystd
,
.
g_input_status
=
tvp7000_g_input_status
,
.
enum_fmt
=
tvp7000_enum_fmt_cap
,
.
g_fmt
=
tvp7000_g_fmt_cap
,
.
try_fmt
=
tvp7000_try_fmt_cap
,
.
s_fmt
=
tvp7000_s_fmt_cap
,
.
g_parm
=
tvp7000_g_parm
,
.
s_parm
=
tvp7000_s_parm
,
.
s_stream
=
tvp7000_s_stream
,
};
static
const
struct
v4l2_subdev_ops
tvp7000_ops
=
{
.
core
=
&
tvp7000_core_ops
,
.
video
=
&
tvp7000_video_ops
,
};
static
struct
tvp7000_decoder
tvp7000_dev
=
{
.
streaming
=
0
,
.
fmt_list
=
tvp7000_fmt_list
,
.
num_fmts
=
ARRAY_SIZE
(
tvp7000_fmt_list
),
.
pix
=
{
/* Default to PAL 8-bit YUV 422 */
.
width
=
720
,
.
height
=
480
,
.
pixelformat
=
V4L2_PIX_FMT_UYVY
,
.
field
=
0
,
//V4L2_FIELD_INTERLACED,
.
bytesperline
=
720
*
2
,
.
sizeimage
=
720
*
2
*
480
,
.
colorspace
=
V4L2_COLORSPACE_SMPTE170M
,
},
.
current_std
=
VIDEO480P60HZ
,
.
std_list
=
video_info
,
.
num_stds
=
ARRAY_SIZE
(
video_info
),
};
/**
* tvp7000_probe() - decoder driver i2c probe handler
* @client: i2c driver client device structure
* @id: i2c driver id table
*
* Register decoder as an i2c client device and V4L2
* device.
*/
static
int
tvp7000_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
struct
tvp7000_decoder
*
decoder
;
struct
v4l2_subdev
*
sd
;
/* power on the tvp7000 Video decoder*/
tvp7000_device_power_on
(
true
);
mdelay
(
500
);
/* Check if the adapter supports the needed features */
if
(
!
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_SMBUS_WORD_DATA
|
I2C_FUNC_SMBUS_WRITE_BYTE
))
return
-
EIO
;
#if 0
if (!client->dev.platform_data) {
v4l2_err(client, "No platform data!!\n");
return -ENODEV;
}
#endif
decoder
=
kzalloc
(
sizeof
(
*
decoder
),
GFP_KERNEL
);
if
(
!
decoder
)
return
-
ENOMEM
;
/* Initialize the tvp7000_decoder with default configuration */
*
decoder
=
tvp7000_dev
;
/* Copy default register configuration */
memcpy
(
decoder
->
tvp7000_regs
,
tvp7000_init_reg_seq
,
sizeof
(
tvp7000_init_reg_seq
));
/* Copy board specific information here */
decoder
->
pdata
=
client
->
dev
.
platform_data
;
/* Register with V4L2 layer as slave device */
sd
=
&
decoder
->
sd
;
v4l2_i2c_subdev_init
(
sd
,
client
,
&
tvp7000_ops
);
v4l_info
(
client
,
"chip found @ 0x%02x (%s)
\n
"
,
client
->
addr
<<
1
,
client
->
adapter
->
name
);
v4l2_info
(
sd
,
"%s decoder driver registered !!
\n
"
,
sd
->
name
);
return
0
;
}
/**
* tvp7000_remove() - decoder driver i2c remove handler
* @client: i2c driver client device structure
*
* Unregister decoder as an i2c client device and V4L2
* device. Complement of tvp7000_probe().
*/
static
int
tvp7000_remove
(
struct
i2c_client
*
client
)
{
struct
v4l2_subdev
*
sd
=
i2c_get_clientdata
(
client
);
struct
tvp7000_decoder
*
decoder
=
to_decoder
(
sd
);
/* power down the tvp7000 Video decoder*/
tvp7000_device_power_on
(
false
);
v4l2_device_unregister_subdev
(
sd
);
kfree
(
decoder
);
return
0
;
}
/**
* I2C Device Table -
*
* name - Name of the actual device/chip.
* driver_data - Driver data
*/
static
const
struct
i2c_device_id
tvp7000_id
[]
=
{
{
"tvp7000"
,
0
},
{},
};
MODULE_DEVICE_TABLE
(
i2c
,
tvp7000_id
);
static
struct
i2c_driver
tvp7000_driver
=
{
.
driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"tvp7000"
,
},
.
probe
=
tvp7000_probe
,
.
remove
=
tvp7000_remove
,
.
id_table
=
tvp7000_id
,
};
static
__init
int
tvp7000_init
(
void
)
{
printk
(
KERN_INFO
"<%s> start:
\n
"
,
__FUNCTION__
);
return
i2c_add_driver
(
&
tvp7000_driver
);
}
static
__exit
void
tvp7000_exit
(
void
)
{
printk
(
KERN_INFO
"<%s> start:
\n
"
,
__FUNCTION__
);
i2c_del_driver
(
&
tvp7000_driver
);
}
module_init
(
tvp7000_init
);
module_exit
(
tvp7000_exit
);
drivers/media/video/tvp7000_regs.h
0 → 100644
View file @
c92b67fa
/*
* Copyright(C) 2006-2008 Neuros Technology International LLC.
* <www.neurostechnology.com>
*
*
* 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, version 2 of the License.
*
* This program is distributed in the hope that, in addition to its
* original purpose to support Neuros hardware, it will be useful
* otherwise, 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.
*
****************************************************************************
*
* tvp7000 driver header.
*
*/
#ifndef TVP7000_REGS_H__
#define TVP7000_REGS_H__
#define TVP7000_CHIP_REVISION 0x00
#define TVP7000_PLL_DIVIDE_MSB 0x01
#define TVP7000_PLL_DIVIDE_LSB 0x02
#define TVP7000_PLL_CTRL 0x03
#define TVP7000_PHASE_SELECT 0x04
#define TVP7000_CLAMP_START 0x05
#define TVP7000_CLAMP_WIDTH 0x06
#define TVP7000_HSYNC_OUTPUT_WIDTH 0x07
#define TVP7000_BLUE_FINE_GAIN 0x08
#define TVP7000_GREEN_FINE_GAIN 0x09
#define TVP7000_RED_FINE_GAIN 0x0A
#define TVP7000_BLUE_FINE_OFFSET 0x0B
#define TVP7000_GREEN_FINE_OFFSET 0x0C
#define TVP7000_RED_FINE_OFFSET 0x0D
#define TVP7000_SYNC_CTRL_1 0x0E
#define TVP7000_PLL_CLAMP_CTRL 0x0F
#define TVP7000_SYNC_ON_GREEN 0x10
#define TVP7000_SYNC_SEPARATOR 0x11
#define TVP7000_PRE_COAST 0x12
#define TVP7000_POST_COAST 0x13
#define TVP7000_SYNC_DETECT_STATUS 0x14
#define TVP7000_OUTPUT_FORMATTER 0x15
#define TVP7000_TEST_REG 0x16
/* Reserved 0x17 - 0x18 */
#define TVP7000_INPUT_MUX_1 0x19
#define TVP7000_INPUT_MUX_2 0x1A
#define TVP7000_BLUE_GREEN_GAIN 0x1B
#define TVP7000_RED_COARSE_GAIN 0x1C
#define TVP7000_FINE_OFFSET_LSB 0x1D
#define TVP7000_BLUE_COARSE_OFFSET 0x1E
#define TVP7000_GREEN_COARSE_OFFSET 0x1F
#define TVP7000_RED_COARSE_OFFSET 0x20
#define TVP7000_HSOUT_OUTPUT_START 0x21
#define TVP7000_MISC_CTRL 0x22
/* Reserved 0x23 - 0x25 */
#define TVP7000_AUTO_CTRL_ENABLE 0x26
/* Reserved 0x27 */
#define TVP7000_AUTO_CTRL_FILTER 0x28
/* Reserved 0x29 */
#define TVP7000_FINE_CLAMP_CTRL 0x2A
#define TVP7000_POWER_CTRL 0x2B
#define TVP7000_ADC_SETUP 0x2C
#define TVP7000_COARSE_CLAMP_CTRL_1 0x2D
#define TVP7000_SOG_CLAMP 0x2E
/* Reserved 0x2F - 0x30 */
#define TVP7000_ALC_PLACEMENT 0x31
/* Tokens for register write */
#define TOK_WRITE (0)
/* token for write operation */
#define TOK_TERM (1)
/* terminating token */
#define TOK_DELAY (2)
/* delay token for reg list */
#define TOK_SKIP (3)
/* token to skip a register */
/**
* struct tvp7000_reg - Structure for TVP7000 register initialization values
* @token - Token: TOK_WRITE, TOK_TERM etc..
* @reg - Register offset
* @val - Register Value for TOK_WRITE or delay in ms for TOK_DELAY
*/
struct
tvp7000_reg
{
u8
token
;
u8
reg
;
u8
val
;
};
#endif
/* TVP7000_REGS_H__ */
include/linux/videodev2.h
View file @
c92b67fa
...
...
@@ -665,6 +665,13 @@ typedef __u64 v4l2_std_id;
#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
/*FOR COMPONENT*/
#define V4L2_STD_HD_480P ((v4l2_std_id)0x04000000)
#define V4L2_STD_HD_576P ((v4l2_std_id)0x08000000)
#define V4L2_STD_HD_720P ((v4l2_std_id)0x10000000)
#define V4L2_STD_HD_1080I ((v4l2_std_id)0x20000000)
#define V4L2_STD_HD_1080P ((v4l2_std_id)0x40000000)
/* FIXME:
Although std_id is 64 bits, there is an issue on PPC32 architecture that
makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding
...
...
include/media/tvp7000.h
0 → 100644
View file @
c92b67fa
/*
* Copyright(C) 2006-2008 Neuros Technology International LLC.
* <www.neurostechnology.com>
*
*
* 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, version 2 of the License.
*
* This program is distributed in the hope that, in addition to its
* original purpose to support Neuros hardware, it will be useful
* otherwise, 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.
*
****************************************************************************
*
// * tvp7000 driver header.
*
*/
#ifndef TVP7000_H__
#define TVP7000_H__
#define TVP7000_COMPONENT 2
/* TVP7000 HW outputs */
#define TVP7000_NORMAL_SCREEN 0
#define TVP7000_BLACK_SCREEN 1
#endif
/* TVP7000_H__ */
include/media/v4l2-chip-ident.h
View file @
c92b67fa
...
...
@@ -129,6 +129,9 @@ enum {
V4L2_IDENT_SAA6752HS
=
6752
,
V4L2_IDENT_SAA6752HS_AC3
=
6753
,
/* module tvp7000 */
V4L2_IDENT_TVP7000
=
7000
,
/* module adv7170: just ident 7170 */
V4L2_IDENT_ADV7170
=
7170
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment