Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
config VIDEO_DAVINCI_VPIF_DISPLAY
tristate "TI DaVinci VPIF V4L2-Display driver"
depends on VIDEO_DEV && ARCH_DAVINCI
select VIDEOBUF2_DMA_CONTIG
select VIDEO_ADV7343 if MEDIA_SUBDRV_AUTOSELECT
select VIDEO_THS7303 if MEDIA_SUBDRV_AUTOSELECT
help
Enables Davinci VPIF module used for display devices.
This module is used for display on TI DM6467/DA850/OMAPL138
SoCs.
To compile this driver as a module, choose M here. There will
be two modules called vpif.ko and vpif_display.ko
config VIDEO_DAVINCI_VPIF_CAPTURE
tristate "TI DaVinci VPIF video capture driver"
depends on VIDEO_DEV && ARCH_DAVINCI
select VIDEOBUF2_DMA_CONTIG
help
Enables Davinci VPIF module used for capture devices.
This module is used for capture on TI DM6467/DA850/OMAPL138
SoCs.
To compile this driver as a module, choose M here. There will
be two modules called vpif.ko and vpif_capture.ko
config VIDEO_DM6446_CCDC
tristate "TI DM6446 CCDC video capture driver"
depends on VIDEO_V4L2 && (ARCH_DAVINCI || ARCH_OMAP3)
select VIDEOBUF_DMA_CONTIG
help
Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
with decoder modules such as TVP5146 over BT656 or
sensor module such as MT9T001 over a raw interface. This
module configures the interface and CCDC/ISIF to do
video frame capture from slave decoders.
To compile this driver as a module, choose M here. There will
be three modules called vpfe_capture.ko, vpss.ko and dm644x_ccdc.ko
config VIDEO_DM355_CCDC
tristate "TI DM355 CCDC video capture driver"
depends on VIDEO_V4L2 && ARCH_DAVINCI
select VIDEOBUF_DMA_CONTIG
help
Enables DM355 CCD hw module. DM355 CCDC hw interfaces
with decoder modules such as TVP5146 over BT656 or
sensor module such as MT9T001 over a raw interface. This
module configures the interface and CCDC/ISIF to do
video frame capture from a slave decoders
To compile this driver as a module, choose M here. There will
be three modules called vpfe_capture.ko, vpss.ko and dm355_ccdc.ko
config VIDEO_DM365_ISIF
tristate "TI DM365 ISIF video capture driver"
depends on VIDEO_V4L2 && ARCH_DAVINCI
select VIDEOBUF_DMA_CONTIG
help
Enables ISIF hw module. This is the hardware module for
configuring ISIF in VPFE to capture Raw Bayer RGB data from
a image sensor or YUV data from a YUV source.
To compile this driver as a module, choose M here. There will
be three modules called vpfe_capture.ko, vpss.ko and isif.ko
config VIDEO_DAVINCI_VPBE_DISPLAY
tristate "TI DaVinci VPBE V4L2-Display driver"
depends on ARCH_DAVINCI
select VIDEOBUF2_DMA_CONTIG
help
Enables Davinci VPBE module used for display devices.
This module is used for display on TI DM644x/DM365/DM355
based display devices.
To compile this driver as a module, choose M here. There will
be five modules created called vpss.ko, vpbe.ko, vpbe_osd.ko,
vpbe_venc.ko and vpbe_display.ko

View File

@@ -0,0 +1,15 @@
#
# Makefile for the davinci video device drivers.
#
#VPIF Display driver
obj-$(CONFIG_VIDEO_DAVINCI_VPIF_DISPLAY) += vpif.o vpif_display.o
#VPIF Capture driver
obj-$(CONFIG_VIDEO_DAVINCI_VPIF_CAPTURE) += vpif.o vpif_capture.o
# Capture: DM6446 and DM355
obj-$(CONFIG_VIDEO_DM6446_CCDC) += vpfe_capture.o vpss.o dm644x_ccdc.o
obj-$(CONFIG_VIDEO_DM355_CCDC) += vpfe_capture.o vpss.o dm355_ccdc.o
obj-$(CONFIG_VIDEO_DM365_ISIF) += vpfe_capture.o vpss.o isif.o
obj-$(CONFIG_VIDEO_DAVINCI_VPBE_DISPLAY) += vpss.o vpbe.o vpbe_osd.o \
vpbe_venc.o vpbe_display.o

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2008-2009 Texas Instruments Inc
*
* 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
*
* ccdc device API
*/
#ifndef _CCDC_HW_DEVICE_H
#define _CCDC_HW_DEVICE_H
#ifdef __KERNEL__
#include <linux/videodev2.h>
#include <linux/device.h>
#include <media/davinci/vpfe_types.h>
#include <media/davinci/ccdc_types.h>
/*
* ccdc hw operations
*/
struct ccdc_hw_ops {
/* Pointer to initialize function to initialize ccdc device */
int (*open) (struct device *dev);
/* Pointer to deinitialize function */
int (*close) (struct device *dev);
/* set ccdc base address */
void (*set_ccdc_base)(void *base, int size);
/* Pointer to function to enable or disable ccdc */
void (*enable) (int en);
/* reset sbl. only for 6446 */
void (*reset) (void);
/* enable output to sdram */
void (*enable_out_to_sdram) (int en);
/* Pointer to function to set hw parameters */
int (*set_hw_if_params) (struct vpfe_hw_if_param *param);
/* get interface parameters */
int (*get_hw_if_params) (struct vpfe_hw_if_param *param);
/*
* Pointer to function to set parameters. Used
* for implementing VPFE_S_CCDC_PARAMS
*/
int (*set_params) (void *params);
/*
* Pointer to function to get parameter. Used
* for implementing VPFE_G_CCDC_PARAMS
*/
int (*get_params) (void *params);
/* Pointer to function to configure ccdc */
int (*configure) (void);
/* Pointer to function to set buffer type */
int (*set_buftype) (enum ccdc_buftype buf_type);
/* Pointer to function to get buffer type */
enum ccdc_buftype (*get_buftype) (void);
/* Pointer to function to set frame format */
int (*set_frame_format) (enum ccdc_frmfmt frm_fmt);
/* Pointer to function to get frame format */
enum ccdc_frmfmt (*get_frame_format) (void);
/* enumerate hw pix formats */
int (*enum_pix)(u32 *hw_pix, int i);
/* Pointer to function to set buffer type */
u32 (*get_pixel_format) (void);
/* Pointer to function to get pixel format. */
int (*set_pixel_format) (u32 pixfmt);
/* Pointer to function to set image window */
int (*set_image_window) (struct v4l2_rect *win);
/* Pointer to function to set image window */
void (*get_image_window) (struct v4l2_rect *win);
/* Pointer to function to get line length */
unsigned int (*get_line_length) (void);
/* Query CCDC control IDs */
int (*queryctrl)(struct v4l2_queryctrl *qctrl);
/* Set CCDC control */
int (*set_control)(struct v4l2_control *ctrl);
/* Get CCDC control */
int (*get_control)(struct v4l2_control *ctrl);
/* Pointer to function to set frame buffer address */
void (*setfbaddr) (unsigned long addr);
/* Pointer to function to get field id */
int (*getfid) (void);
};
struct ccdc_hw_device {
/* ccdc device name */
char name[32];
/* module owner */
struct module *owner;
/* hw ops */
struct ccdc_hw_ops hw_ops;
};
/* Used by CCDC module to register & unregister with vpfe capture driver */
int vpfe_register_ccdc_device(struct ccdc_hw_device *dev);
void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,310 @@
/*
* Copyright (C) 2005-2009 Texas Instruments Inc
*
* 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
*/
#ifndef _DM355_CCDC_REGS_H
#define _DM355_CCDC_REGS_H
/**************************************************************************\
* Register OFFSET Definitions
\**************************************************************************/
#define SYNCEN 0x00
#define MODESET 0x04
#define HDWIDTH 0x08
#define VDWIDTH 0x0c
#define PPLN 0x10
#define LPFR 0x14
#define SPH 0x18
#define NPH 0x1c
#define SLV0 0x20
#define SLV1 0x24
#define NLV 0x28
#define CULH 0x2c
#define CULV 0x30
#define HSIZE 0x34
#define SDOFST 0x38
#define STADRH 0x3c
#define STADRL 0x40
#define CLAMP 0x44
#define DCSUB 0x48
#define COLPTN 0x4c
#define BLKCMP0 0x50
#define BLKCMP1 0x54
#define MEDFILT 0x58
#define RYEGAIN 0x5c
#define GRCYGAIN 0x60
#define GBGGAIN 0x64
#define BMGGAIN 0x68
#define OFFSET 0x6c
#define OUTCLIP 0x70
#define VDINT0 0x74
#define VDINT1 0x78
#define RSV0 0x7c
#define GAMMAWD 0x80
#define REC656IF 0x84
#define CCDCFG 0x88
#define FMTCFG 0x8c
#define FMTPLEN 0x90
#define FMTSPH 0x94
#define FMTLNH 0x98
#define FMTSLV 0x9c
#define FMTLNV 0xa0
#define FMTRLEN 0xa4
#define FMTHCNT 0xa8
#define FMT_ADDR_PTR_B 0xac
#define FMT_ADDR_PTR(i) (FMT_ADDR_PTR_B + (i * 4))
#define FMTPGM_VF0 0xcc
#define FMTPGM_VF1 0xd0
#define FMTPGM_AP0 0xd4
#define FMTPGM_AP1 0xd8
#define FMTPGM_AP2 0xdc
#define FMTPGM_AP3 0xe0
#define FMTPGM_AP4 0xe4
#define FMTPGM_AP5 0xe8
#define FMTPGM_AP6 0xec
#define FMTPGM_AP7 0xf0
#define LSCCFG1 0xf4
#define LSCCFG2 0xf8
#define LSCH0 0xfc
#define LSCV0 0x100
#define LSCKH 0x104
#define LSCKV 0x108
#define LSCMEMCTL 0x10c
#define LSCMEMD 0x110
#define LSCMEMQ 0x114
#define DFCCTL 0x118
#define DFCVSAT 0x11c
#define DFCMEMCTL 0x120
#define DFCMEM0 0x124
#define DFCMEM1 0x128
#define DFCMEM2 0x12c
#define DFCMEM3 0x130
#define DFCMEM4 0x134
#define CSCCTL 0x138
#define CSCM0 0x13c
#define CSCM1 0x140
#define CSCM2 0x144
#define CSCM3 0x148
#define CSCM4 0x14c
#define CSCM5 0x150
#define CSCM6 0x154
#define CSCM7 0x158
#define DATAOFST 0x15c
#define CCDC_REG_LAST DATAOFST
/**************************************************************
* Define for various register bit mask and shifts for CCDC
*
**************************************************************/
#define CCDC_RAW_IP_MODE 0
#define CCDC_VDHDOUT_INPUT 0
#define CCDC_YCINSWP_RAW (0 << 4)
#define CCDC_EXWEN_DISABLE 0
#define CCDC_DATAPOL_NORMAL 0
#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC 0
#define CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC (1 << 6)
#define CCDC_CCDCFG_WENLOG_AND 0
#define CCDC_CCDCFG_TRGSEL_WEN 0
#define CCDC_CCDCFG_EXTRG_DISABLE 0
#define CCDC_CFA_MOSAIC 0
#define CCDC_Y8POS_SHIFT 11
#define CCDC_VDC_DFCVSAT_MASK 0x3fff
#define CCDC_DATAOFST_MASK 0x0ff
#define CCDC_DATAOFST_H_SHIFT 0
#define CCDC_DATAOFST_V_SHIFT 8
#define CCDC_GAMMAWD_CFA_MASK 1
#define CCDC_GAMMAWD_CFA_SHIFT 5
#define CCDC_GAMMAWD_INPUT_SHIFT 2
#define CCDC_FID_POL_MASK 1
#define CCDC_FID_POL_SHIFT 4
#define CCDC_HD_POL_MASK 1
#define CCDC_HD_POL_SHIFT 3
#define CCDC_VD_POL_MASK 1
#define CCDC_VD_POL_SHIFT 2
#define CCDC_VD_POL_NEGATIVE (1 << 2)
#define CCDC_FRM_FMT_MASK 1
#define CCDC_FRM_FMT_SHIFT 7
#define CCDC_DATA_SZ_MASK 7
#define CCDC_DATA_SZ_SHIFT 8
#define CCDC_VDHDOUT_MASK 1
#define CCDC_VDHDOUT_SHIFT 0
#define CCDC_EXWEN_MASK 1
#define CCDC_EXWEN_SHIFT 5
#define CCDC_INPUT_MODE_MASK 3
#define CCDC_INPUT_MODE_SHIFT 12
#define CCDC_PIX_FMT_MASK 3
#define CCDC_PIX_FMT_SHIFT 12
#define CCDC_DATAPOL_MASK 1
#define CCDC_DATAPOL_SHIFT 6
#define CCDC_WEN_ENABLE (1 << 1)
#define CCDC_VDHDEN_ENABLE (1 << 16)
#define CCDC_LPF_ENABLE (1 << 14)
#define CCDC_ALAW_ENABLE 1
#define CCDC_ALAW_GAMMA_WD_MASK 7
#define CCDC_REC656IF_BT656_EN 3
#define CCDC_FMTCFG_FMTMODE_MASK 3
#define CCDC_FMTCFG_FMTMODE_SHIFT 1
#define CCDC_FMTCFG_LNUM_MASK 3
#define CCDC_FMTCFG_LNUM_SHIFT 4
#define CCDC_FMTCFG_ADDRINC_MASK 7
#define CCDC_FMTCFG_ADDRINC_SHIFT 8
#define CCDC_CCDCFG_FIDMD_SHIFT 6
#define CCDC_CCDCFG_WENLOG_SHIFT 8
#define CCDC_CCDCFG_TRGSEL_SHIFT 9
#define CCDC_CCDCFG_EXTRG_SHIFT 10
#define CCDC_CCDCFG_MSBINVI_SHIFT 13
#define CCDC_HSIZE_FLIP_SHIFT 12
#define CCDC_HSIZE_FLIP_MASK 1
#define CCDC_HSIZE_VAL_MASK 0xFFF
#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249
#define CCDC_SDOFST_INTERLACE_INVERSE 0x4B6D
#define CCDC_SDOFST_INTERLACE_NORMAL 0x0B6D
#define CCDC_SDOFST_PROGRESSIVE_INVERSE 0x4000
#define CCDC_SDOFST_PROGRESSIVE_NORMAL 0
#define CCDC_START_PX_HOR_MASK 0x7FFF
#define CCDC_NUM_PX_HOR_MASK 0x7FFF
#define CCDC_START_VER_ONE_MASK 0x7FFF
#define CCDC_START_VER_TWO_MASK 0x7FFF
#define CCDC_NUM_LINES_VER 0x7FFF
#define CCDC_BLK_CLAMP_ENABLE (1 << 15)
#define CCDC_BLK_SGAIN_MASK 0x1F
#define CCDC_BLK_ST_PXL_MASK 0x1FFF
#define CCDC_BLK_SAMPLE_LN_MASK 3
#define CCDC_BLK_SAMPLE_LN_SHIFT 13
#define CCDC_NUM_LINE_CALC_MASK 3
#define CCDC_NUM_LINE_CALC_SHIFT 14
#define CCDC_BLK_DC_SUB_MASK 0x3FFF
#define CCDC_BLK_COMP_MASK 0xFF
#define CCDC_BLK_COMP_GB_COMP_SHIFT 8
#define CCDC_BLK_COMP_GR_COMP_SHIFT 0
#define CCDC_BLK_COMP_R_COMP_SHIFT 8
#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15)
#define CCDC_LATCH_ON_VSYNC_ENABLE (0 << 15)
#define CCDC_FPC_ENABLE (1 << 15)
#define CCDC_FPC_FPC_NUM_MASK 0x7FFF
#define CCDC_DATA_PACK_ENABLE (1 << 11)
#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF
#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16
#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF
#define CCDC_FMT_VERT_FMTSLV_SHIFT 16
#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF
#define CCDC_VP_OUT_VERT_NUM_SHIFT 17
#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF
#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4
#define CCDC_VP_OUT_HORZ_ST_MASK 0xF
#define CCDC_CSC_COEF_INTEG_MASK 7
#define CCDC_CSC_COEF_DECIMAL_MASK 0x1f
#define CCDC_CSC_COEF_INTEG_SHIFT 5
#define CCDC_CSCM_MSB_SHIFT 8
#define CCDC_CSC_ENABLE 1
#define CCDC_CSC_DEC_MAX 32
#define CCDC_MFILT1_SHIFT 10
#define CCDC_MFILT2_SHIFT 8
#define CCDC_MED_FILT_THRESH 0x3FFF
#define CCDC_LPF_MASK 1
#define CCDC_LPF_SHIFT 14
#define CCDC_OFFSET_MASK 0x3FF
#define CCDC_DATASFT_MASK 7
#define CCDC_DATASFT_SHIFT 8
#define CCDC_DF_ENABLE 1
#define CCDC_FMTPLEN_P0_MASK 0xF
#define CCDC_FMTPLEN_P1_MASK 0xF
#define CCDC_FMTPLEN_P2_MASK 7
#define CCDC_FMTPLEN_P3_MASK 7
#define CCDC_FMTPLEN_P0_SHIFT 0
#define CCDC_FMTPLEN_P1_SHIFT 4
#define CCDC_FMTPLEN_P2_SHIFT 8
#define CCDC_FMTPLEN_P3_SHIFT 12
#define CCDC_FMTSPH_MASK 0x1FFF
#define CCDC_FMTLNH_MASK 0x1FFF
#define CCDC_FMTSLV_MASK 0x1FFF
#define CCDC_FMTLNV_MASK 0x7FFF
#define CCDC_FMTRLEN_MASK 0x1FFF
#define CCDC_FMTHCNT_MASK 0x1FFF
#define CCDC_ADP_INIT_MASK 0x1FFF
#define CCDC_ADP_LINE_SHIFT 13
#define CCDC_ADP_LINE_MASK 3
#define CCDC_FMTPGN_APTR_MASK 7
#define CCDC_DFCCTL_GDFCEN_MASK 1
#define CCDC_DFCCTL_VDFCEN_MASK 1
#define CCDC_DFCCTL_VDFC_DISABLE (0 << 4)
#define CCDC_DFCCTL_VDFCEN_SHIFT 4
#define CCDC_DFCCTL_VDFCSL_MASK 3
#define CCDC_DFCCTL_VDFCSL_SHIFT 5
#define CCDC_DFCCTL_VDFCUDA_MASK 1
#define CCDC_DFCCTL_VDFCUDA_SHIFT 7
#define CCDC_DFCCTL_VDFLSFT_MASK 3
#define CCDC_DFCCTL_VDFLSFT_SHIFT 8
#define CCDC_DFCMEMCTL_DFCMARST_MASK 1
#define CCDC_DFCMEMCTL_DFCMARST_SHIFT 2
#define CCDC_DFCMEMCTL_DFCMWR_MASK 1
#define CCDC_DFCMEMCTL_DFCMWR_SHIFT 0
#define CCDC_DFCMEMCTL_INC_ADDR (0 << 2)
#define CCDC_LSCCFG_GFTSF_MASK 7
#define CCDC_LSCCFG_GFTSF_SHIFT 1
#define CCDC_LSCCFG_GFTINV_MASK 0xf
#define CCDC_LSCCFG_GFTINV_SHIFT 4
#define CCDC_LSC_GFTABLE_SEL_MASK 3
#define CCDC_LSC_GFTABLE_EPEL_SHIFT 8
#define CCDC_LSC_GFTABLE_OPEL_SHIFT 10
#define CCDC_LSC_GFTABLE_EPOL_SHIFT 12
#define CCDC_LSC_GFTABLE_OPOL_SHIFT 14
#define CCDC_LSC_GFMODE_MASK 3
#define CCDC_LSC_GFMODE_SHIFT 4
#define CCDC_LSC_DISABLE 0
#define CCDC_LSC_ENABLE 1
#define CCDC_LSC_TABLE1_SLC 0
#define CCDC_LSC_TABLE2_SLC 1
#define CCDC_LSC_TABLE3_SLC 2
#define CCDC_LSC_MEMADDR_RESET (1 << 2)
#define CCDC_LSC_MEMADDR_INCR (0 << 2)
#define CCDC_LSC_FRAC_MASK_T1 0xFF
#define CCDC_LSC_INT_MASK 3
#define CCDC_LSC_FRAC_MASK 0x3FFF
#define CCDC_LSC_CENTRE_MASK 0x3FFF
#define CCDC_LSC_COEF_MASK 0xff
#define CCDC_LSC_COEFL_SHIFT 0
#define CCDC_LSC_COEFU_SHIFT 8
#define CCDC_GAIN_MASK 0x7FF
#define CCDC_SYNCEN_VDHDEN_MASK (1 << 0)
#define CCDC_SYNCEN_WEN_MASK (1 << 1)
#define CCDC_SYNCEN_WEN_SHIFT 1
/* Power on Defaults in hardware */
#define MODESET_DEFAULT 0x200
#define CULH_DEFAULT 0xFFFF
#define CULV_DEFAULT 0xFF
#define GAIN_DEFAULT 256
#define OUTCLIP_DEFAULT 0x3FFF
#define LSCCFG2_DEFAULT 0xE
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2006-2009 Texas Instruments Inc
*
* 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
*/
#ifndef _DM644X_CCDC_REGS_H
#define _DM644X_CCDC_REGS_H
/**************************************************************************\
* Register OFFSET Definitions
\**************************************************************************/
#define CCDC_PID 0x0
#define CCDC_PCR 0x4
#define CCDC_SYN_MODE 0x8
#define CCDC_HD_VD_WID 0xc
#define CCDC_PIX_LINES 0x10
#define CCDC_HORZ_INFO 0x14
#define CCDC_VERT_START 0x18
#define CCDC_VERT_LINES 0x1c
#define CCDC_CULLING 0x20
#define CCDC_HSIZE_OFF 0x24
#define CCDC_SDOFST 0x28
#define CCDC_SDR_ADDR 0x2c
#define CCDC_CLAMP 0x30
#define CCDC_DCSUB 0x34
#define CCDC_COLPTN 0x38
#define CCDC_BLKCMP 0x3c
#define CCDC_FPC 0x40
#define CCDC_FPC_ADDR 0x44
#define CCDC_VDINT 0x48
#define CCDC_ALAW 0x4c
#define CCDC_REC656IF 0x50
#define CCDC_CCDCFG 0x54
#define CCDC_FMTCFG 0x58
#define CCDC_FMT_HORZ 0x5c
#define CCDC_FMT_VERT 0x60
#define CCDC_FMT_ADDR0 0x64
#define CCDC_FMT_ADDR1 0x68
#define CCDC_FMT_ADDR2 0x6c
#define CCDC_FMT_ADDR3 0x70
#define CCDC_FMT_ADDR4 0x74
#define CCDC_FMT_ADDR5 0x78
#define CCDC_FMT_ADDR6 0x7c
#define CCDC_FMT_ADDR7 0x80
#define CCDC_PRGEVEN_0 0x84
#define CCDC_PRGEVEN_1 0x88
#define CCDC_PRGODD_0 0x8c
#define CCDC_PRGODD_1 0x90
#define CCDC_VP_OUT 0x94
#define CCDC_REG_END 0x98
/***************************************************************
* Define for various register bit mask and shifts for CCDC
****************************************************************/
#define CCDC_FID_POL_MASK 1
#define CCDC_FID_POL_SHIFT 4
#define CCDC_HD_POL_MASK 1
#define CCDC_HD_POL_SHIFT 3
#define CCDC_VD_POL_MASK 1
#define CCDC_VD_POL_SHIFT 2
#define CCDC_HSIZE_OFF_MASK 0xffffffe0
#define CCDC_32BYTE_ALIGN_VAL 31
#define CCDC_FRM_FMT_MASK 0x1
#define CCDC_FRM_FMT_SHIFT 7
#define CCDC_DATA_SZ_MASK 7
#define CCDC_DATA_SZ_SHIFT 8
#define CCDC_PIX_FMT_MASK 3
#define CCDC_PIX_FMT_SHIFT 12
#define CCDC_VP2SDR_DISABLE 0xFFFBFFFF
#define CCDC_WEN_ENABLE (1 << 17)
#define CCDC_SDR2RSZ_DISABLE 0xFFF7FFFF
#define CCDC_VDHDEN_ENABLE (1 << 16)
#define CCDC_LPF_ENABLE (1 << 14)
#define CCDC_ALAW_ENABLE (1 << 3)
#define CCDC_ALAW_GAMMA_WD_MASK 7
#define CCDC_BLK_CLAMP_ENABLE (1 << 31)
#define CCDC_BLK_SGAIN_MASK 0x1F
#define CCDC_BLK_ST_PXL_MASK 0x7FFF
#define CCDC_BLK_ST_PXL_SHIFT 10
#define CCDC_BLK_SAMPLE_LN_MASK 7
#define CCDC_BLK_SAMPLE_LN_SHIFT 28
#define CCDC_BLK_SAMPLE_LINE_MASK 7
#define CCDC_BLK_SAMPLE_LINE_SHIFT 25
#define CCDC_BLK_DC_SUB_MASK 0x03FFF
#define CCDC_BLK_COMP_MASK 0xFF
#define CCDC_BLK_COMP_GB_COMP_SHIFT 8
#define CCDC_BLK_COMP_GR_COMP_SHIFT 16
#define CCDC_BLK_COMP_R_COMP_SHIFT 24
#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15)
#define CCDC_FPC_ENABLE (1 << 15)
#define CCDC_FPC_DISABLE 0
#define CCDC_FPC_FPC_NUM_MASK 0x7FFF
#define CCDC_DATA_PACK_ENABLE (1 << 11)
#define CCDC_FMTCFG_VPIN_MASK 7
#define CCDC_FMTCFG_VPIN_SHIFT 12
#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF
#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16
#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF
#define CCDC_FMT_VERT_FMTSLV_SHIFT 16
#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF
#define CCDC_VP_OUT_VERT_NUM_SHIFT 17
#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF
#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4
#define CCDC_VP_OUT_HORZ_ST_MASK 0xF
#define CCDC_HORZ_INFO_SPH_SHIFT 16
#define CCDC_VERT_START_SLV0_SHIFT 16
#define CCDC_VDINT_VDINT0_SHIFT 16
#define CCDC_VDINT_VDINT1_MASK 0xFFFF
#define CCDC_PPC_RAW 1
#define CCDC_DCSUB_DEFAULT_VAL 0
#define CCDC_CLAMP_DEFAULT_VAL 0
#define CCDC_ENABLE_VIDEO_PORT 0x8000
#define CCDC_DISABLE_VIDEO_PORT 0
#define CCDC_COLPTN_VAL 0xBB11BB11
#define CCDC_TWO_BYTES_PER_PIXEL 2
#define CCDC_INTERLACED_IMAGE_INVERT 0x4B6D
#define CCDC_INTERLACED_NO_IMAGE_INVERT 0x0249
#define CCDC_PROGRESSIVE_IMAGE_INVERT 0x4000
#define CCDC_PROGRESSIVE_NO_IMAGE_INVERT 0
#define CCDC_INTERLACED_HEIGHT_SHIFT 1
#define CCDC_SYN_MODE_INPMOD_SHIFT 12
#define CCDC_SYN_MODE_INPMOD_MASK 3
#define CCDC_SYN_MODE_8BITS (7 << 8)
#define CCDC_SYN_MODE_10BITS (6 << 8)
#define CCDC_SYN_MODE_11BITS (5 << 8)
#define CCDC_SYN_MODE_12BITS (4 << 8)
#define CCDC_SYN_MODE_13BITS (3 << 8)
#define CCDC_SYN_MODE_14BITS (2 << 8)
#define CCDC_SYN_MODE_15BITS (1 << 8)
#define CCDC_SYN_MODE_16BITS (0 << 8)
#define CCDC_SYN_FLDMODE_MASK 1
#define CCDC_SYN_FLDMODE_SHIFT 7
#define CCDC_REC656IF_BT656_EN 3
#define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2)
#define CCDC_CCDCFG_Y8POS_SHIFT 11
#define CCDC_CCDCFG_BW656_10BIT (1 << 5)
#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249
#define CCDC_NO_CULLING 0xffff00ff
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,269 @@
/*
* Copyright (C) 2008-2009 Texas Instruments Inc
*
* 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
*/
#ifndef _ISIF_REGS_H
#define _ISIF_REGS_H
/* ISIF registers relative offsets */
#define SYNCEN 0x00
#define MODESET 0x04
#define HDW 0x08
#define VDW 0x0c
#define PPLN 0x10
#define LPFR 0x14
#define SPH 0x18
#define LNH 0x1c
#define SLV0 0x20
#define SLV1 0x24
#define LNV 0x28
#define CULH 0x2c
#define CULV 0x30
#define HSIZE 0x34
#define SDOFST 0x38
#define CADU 0x3c
#define CADL 0x40
#define LINCFG0 0x44
#define LINCFG1 0x48
#define CCOLP 0x4c
#define CRGAIN 0x50
#define CGRGAIN 0x54
#define CGBGAIN 0x58
#define CBGAIN 0x5c
#define COFSTA 0x60
#define FLSHCFG0 0x64
#define FLSHCFG1 0x68
#define FLSHCFG2 0x6c
#define VDINT0 0x70
#define VDINT1 0x74
#define VDINT2 0x78
#define MISC 0x7c
#define CGAMMAWD 0x80
#define REC656IF 0x84
#define CCDCFG 0x88
/*****************************************************
* Defect Correction registers
*****************************************************/
#define DFCCTL 0x8c
#define VDFSATLV 0x90
#define DFCMEMCTL 0x94
#define DFCMEM0 0x98
#define DFCMEM1 0x9c
#define DFCMEM2 0xa0
#define DFCMEM3 0xa4
#define DFCMEM4 0xa8
/****************************************************
* Black Clamp registers
****************************************************/
#define CLAMPCFG 0xac
#define CLDCOFST 0xb0
#define CLSV 0xb4
#define CLHWIN0 0xb8
#define CLHWIN1 0xbc
#define CLHWIN2 0xc0
#define CLVRV 0xc4
#define CLVWIN0 0xc8
#define CLVWIN1 0xcc
#define CLVWIN2 0xd0
#define CLVWIN3 0xd4
/****************************************************
* Lense Shading Correction
****************************************************/
#define DATAHOFST 0xd8
#define DATAVOFST 0xdc
#define LSCHVAL 0xe0
#define LSCVVAL 0xe4
#define TWODLSCCFG 0xe8
#define TWODLSCOFST 0xec
#define TWODLSCINI 0xf0
#define TWODLSCGRBU 0xf4
#define TWODLSCGRBL 0xf8
#define TWODLSCGROF 0xfc
#define TWODLSCORBU 0x100
#define TWODLSCORBL 0x104
#define TWODLSCOROF 0x108
#define TWODLSCIRQEN 0x10c
#define TWODLSCIRQST 0x110
/****************************************************
* Data formatter
****************************************************/
#define FMTCFG 0x114
#define FMTPLEN 0x118
#define FMTSPH 0x11c
#define FMTLNH 0x120
#define FMTSLV 0x124
#define FMTLNV 0x128
#define FMTRLEN 0x12c
#define FMTHCNT 0x130
#define FMTAPTR_BASE 0x134
/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */
#define FMTAPTR(i) (FMTAPTR_BASE + (i * 4))
#define FMTPGMVF0 0x174
#define FMTPGMVF1 0x178
#define FMTPGMAPU0 0x17c
#define FMTPGMAPU1 0x180
#define FMTPGMAPS0 0x184
#define FMTPGMAPS1 0x188
#define FMTPGMAPS2 0x18c
#define FMTPGMAPS3 0x190
#define FMTPGMAPS4 0x194
#define FMTPGMAPS5 0x198
#define FMTPGMAPS6 0x19c
#define FMTPGMAPS7 0x1a0
/************************************************
* Color Space Converter
************************************************/
#define CSCCTL 0x1a4
#define CSCM0 0x1a8
#define CSCM1 0x1ac
#define CSCM2 0x1b0
#define CSCM3 0x1b4
#define CSCM4 0x1b8
#define CSCM5 0x1bc
#define CSCM6 0x1c0
#define CSCM7 0x1c4
#define OBWIN0 0x1c8
#define OBWIN1 0x1cc
#define OBWIN2 0x1d0
#define OBWIN3 0x1d4
#define OBVAL0 0x1d8
#define OBVAL1 0x1dc
#define OBVAL2 0x1e0
#define OBVAL3 0x1e4
#define OBVAL4 0x1e8
#define OBVAL5 0x1ec
#define OBVAL6 0x1f0
#define OBVAL7 0x1f4
#define CLKCTL 0x1f8
/* Masks & Shifts below */
#define START_PX_HOR_MASK 0x7FFF
#define NUM_PX_HOR_MASK 0x7FFF
#define START_VER_ONE_MASK 0x7FFF
#define START_VER_TWO_MASK 0x7FFF
#define NUM_LINES_VER 0x7FFF
/* gain - offset masks */
#define GAIN_INTEGER_SHIFT 9
#define OFFSET_MASK 0xFFF
#define GAIN_SDRAM_EN_SHIFT 12
#define GAIN_IPIPE_EN_SHIFT 13
#define GAIN_H3A_EN_SHIFT 14
#define OFST_SDRAM_EN_SHIFT 8
#define OFST_IPIPE_EN_SHIFT 9
#define OFST_H3A_EN_SHIFT 10
#define GAIN_OFFSET_EN_MASK 0x7700
/* Culling */
#define CULL_PAT_EVEN_LINE_SHIFT 8
/* CCDCFG register */
#define ISIF_YCINSWP_RAW (0x00 << 4)
#define ISIF_YCINSWP_YCBCR (0x01 << 4)
#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6)
#define ISIF_CCDCFG_WENLOG_AND (0x00 << 8)
#define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9)
#define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10)
#define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15)
#define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15)
#define ISIF_DATA_PACK_MASK 3
#define ISIF_DATA_PACK16 0
#define ISIF_DATA_PACK12 1
#define ISIF_DATA_PACK8 2
#define ISIF_PIX_ORDER_SHIFT 11
#define ISIF_BW656_ENABLE (0x01 << 5)
/* MODESET registers */
#define ISIF_VDHDOUT_INPUT (0x00 << 0)
#define ISIF_INPUT_SHIFT 12
#define ISIF_RAW_INPUT_MODE 0
#define ISIF_FID_POL_SHIFT 4
#define ISIF_HD_POL_SHIFT 3
#define ISIF_VD_POL_SHIFT 2
#define ISIF_DATAPOL_NORMAL 0
#define ISIF_DATAPOL_SHIFT 6
#define ISIF_EXWEN_DISABLE 0
#define ISIF_EXWEN_SHIFT 5
#define ISIF_FRM_FMT_SHIFT 7
#define ISIF_DATASFT_SHIFT 8
#define ISIF_LPF_SHIFT 14
#define ISIF_LPF_MASK 1
/* GAMMAWD registers */
#define ISIF_ALAW_GAMMA_WD_MASK 0xF
#define ISIF_ALAW_GAMMA_WD_SHIFT 1
#define ISIF_ALAW_ENABLE 1
#define ISIF_GAMMAWD_CFA_SHIFT 5
/* HSIZE registers */
#define ISIF_HSIZE_FLIP_MASK 1
#define ISIF_HSIZE_FLIP_SHIFT 12
/* MISC registers */
#define ISIF_DPCM_EN_SHIFT 12
#define ISIF_DPCM_PREDICTOR_SHIFT 13
/* Black clamp related */
#define ISIF_BC_MODE_COLOR_SHIFT 4
#define ISIF_HORZ_BC_MODE_SHIFT 1
#define ISIF_HORZ_BC_WIN_SEL_SHIFT 5
#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6
#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8
#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12
#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4
#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8
/* VDFC registers */
#define ISIF_VDFC_EN_SHIFT 4
#define ISIF_VDFC_CORR_MOD_SHIFT 5
#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7
#define ISIF_VDFC_LEVEL_SHFT_SHIFT 8
#define ISIF_VDFC_POS_MASK 0x1FFF
#define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2
/* CSC registers */
#define ISIF_CSC_COEF_INTEG_MASK 7
#define ISIF_CSC_COEF_DECIMAL_MASK 0x1f
#define ISIF_CSC_COEF_INTEG_SHIFT 5
#define ISIF_CSCM_MSB_SHIFT 8
#define ISIF_DF_CSC_SPH_MASK 0x1FFF
#define ISIF_DF_CSC_LNH_MASK 0x1FFF
#define ISIF_DF_CSC_SLV_MASK 0x1FFF
#define ISIF_DF_CSC_LNV_MASK 0x1FFF
#define ISIF_DF_NUMLINES 0x7FFF
#define ISIF_DF_NUMPIX 0x1FFF
/* Offsets for LSC/DFC/Gain */
#define ISIF_DATA_H_OFFSET_MASK 0x1FFF
#define ISIF_DATA_V_OFFSET_MASK 0x1FFF
/* Linearization */
#define ISIF_LIN_CORRSFT_SHIFT 4
#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10
/* Pattern registers */
#define ISIF_PG_EN (1 << 3)
#define ISIF_SEL_PG_SRC (3 << 4)
#define ISIF_PG_VD_POL_SHIFT 0
#define ISIF_PG_HD_POL_SHIFT 1
/*random other junk*/
#define ISIF_SYNCEN_VDHDEN_MASK (1 << 0)
#define ISIF_SYNCEN_WEN_MASK (1 << 1)
#define ISIF_SYNCEN_WEN_SHIFT 1
#endif

View File

@@ -0,0 +1,872 @@
/*
* Copyright (C) 2010 Texas Instruments Inc
*
* 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.
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <media/v4l2-device.h>
#include <media/davinci/vpbe_types.h>
#include <media/davinci/vpbe.h>
#include <media/davinci/vpss.h>
#include <media/davinci/vpbe_venc.h>
#define VPBE_DEFAULT_OUTPUT "Composite"
#define VPBE_DEFAULT_MODE "ntsc"
static char *def_output = VPBE_DEFAULT_OUTPUT;
static char *def_mode = VPBE_DEFAULT_MODE;
static int debug;
module_param(def_output, charp, S_IRUGO);
module_param(def_mode, charp, S_IRUGO);
module_param(debug, int, 0644);
MODULE_PARM_DESC(def_output, "vpbe output name (default:Composite)");
MODULE_PARM_DESC(def_mode, "vpbe output mode name (default:ntsc");
MODULE_PARM_DESC(debug, "Debug level 0-1");
MODULE_DESCRIPTION("TI DMXXX VPBE Display controller");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Texas Instruments");
/**
* vpbe_current_encoder_info - Get config info for current encoder
* @vpbe_dev - vpbe device ptr
*
* Return ptr to current encoder config info
*/
static struct encoder_config_info*
vpbe_current_encoder_info(struct vpbe_device *vpbe_dev)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
int index = vpbe_dev->current_sd_index;
return ((index == 0) ? &cfg->venc :
&cfg->ext_encoders[index-1]);
}
/**
* vpbe_find_encoder_sd_index - Given a name find encoder sd index
*
* @vpbe_config - ptr to vpbe cfg
* @output_index - index used by application
*
* Return sd index of the encoder
*/
static int vpbe_find_encoder_sd_index(struct vpbe_config *cfg,
int index)
{
char *encoder_name = cfg->outputs[index].subdev_name;
int i;
/* Venc is always first */
if (!strcmp(encoder_name, cfg->venc.module_name))
return 0;
for (i = 0; i < cfg->num_ext_encoders; i++) {
if (!strcmp(encoder_name,
cfg->ext_encoders[i].module_name))
return i+1;
}
return -EINVAL;
}
/**
* vpbe_g_cropcap - Get crop capabilities of the display
* @vpbe_dev - vpbe device ptr
* @cropcap - cropcap is a ptr to struct v4l2_cropcap
*
* Update the crop capabilities in crop cap for current
* mode
*/
static int vpbe_g_cropcap(struct vpbe_device *vpbe_dev,
struct v4l2_cropcap *cropcap)
{
if (NULL == cropcap)
return -EINVAL;
cropcap->bounds.left = 0;
cropcap->bounds.top = 0;
cropcap->bounds.width = vpbe_dev->current_timings.xres;
cropcap->bounds.height = vpbe_dev->current_timings.yres;
cropcap->defrect = cropcap->bounds;
return 0;
}
/**
* vpbe_enum_outputs - enumerate outputs
* @vpbe_dev - vpbe device ptr
* @output - ptr to v4l2_output structure
*
* Enumerates the outputs available at the vpbe display
* returns the status, -EINVAL if end of output list
*/
static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
struct v4l2_output *output)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
int temp_index = output->index;
if (temp_index >= cfg->num_outputs)
return -EINVAL;
*output = cfg->outputs[temp_index].output;
output->index = temp_index;
return 0;
}
static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode,
int output_index)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
struct vpbe_enc_mode_info var;
int curr_output = output_index;
int i;
if (NULL == mode)
return -EINVAL;
for (i = 0; i < cfg->outputs[curr_output].num_modes; i++) {
var = cfg->outputs[curr_output].modes[i];
if (!strcmp(mode, var.name)) {
vpbe_dev->current_timings = var;
return 0;
}
}
return -EINVAL;
}
static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
struct vpbe_enc_mode_info *mode_info)
{
if (NULL == mode_info)
return -EINVAL;
*mode_info = vpbe_dev->current_timings;
return 0;
}
/* Get std by std id */
static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
v4l2_std_id std_id)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
struct vpbe_enc_mode_info var;
int curr_output = vpbe_dev->current_out_index;
int i;
for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
var = cfg->outputs[curr_output].modes[i];
if ((var.timings_type & VPBE_ENC_STD) &&
(var.std_id & std_id)) {
vpbe_dev->current_timings = var;
return 0;
}
}
return -EINVAL;
}
static int vpbe_get_std_info_by_name(struct vpbe_device *vpbe_dev,
char *std_name)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
struct vpbe_enc_mode_info var;
int curr_output = vpbe_dev->current_out_index;
int i;
for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
var = cfg->outputs[curr_output].modes[i];
if (!strcmp(var.name, std_name)) {
vpbe_dev->current_timings = var;
return 0;
}
}
return -EINVAL;
}
/**
* vpbe_set_output - Set output
* @vpbe_dev - vpbe device ptr
* @index - index of output
*
* Set vpbe output to the output specified by the index
*/
static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
{
struct encoder_config_info *curr_enc_info =
vpbe_current_encoder_info(vpbe_dev);
struct vpbe_config *cfg = vpbe_dev->cfg;
struct venc_platform_data *venc_device = vpbe_dev->venc_device;
enum v4l2_mbus_pixelcode if_params;
int enc_out_index;
int sd_index;
int ret = 0;
if (index >= cfg->num_outputs)
return -EINVAL;
mutex_lock(&vpbe_dev->lock);
sd_index = vpbe_dev->current_sd_index;
enc_out_index = cfg->outputs[index].output.index;
/*
* Currently we switch the encoder based on output selected
* by the application. If media controller is implemented later
* there is will be an API added to setup_link between venc
* and external encoder. So in that case below comparison always
* match and encoder will not be switched. But if application
* chose not to use media controller, then this provides current
* way of switching encoder at the venc output.
*/
if (strcmp(curr_enc_info->module_name,
cfg->outputs[index].subdev_name)) {
/* Need to switch the encoder at the output */
sd_index = vpbe_find_encoder_sd_index(cfg, index);
if (sd_index < 0) {
ret = -EINVAL;
goto out;
}
if_params = cfg->outputs[index].if_params;
venc_device->setup_if_config(if_params);
if (ret)
goto out;
}
/* Set output at the encoder */
ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
s_routing, 0, enc_out_index, 0);
if (ret)
goto out;
/*
* It is assumed that venc or extenal encoder will set a default
* mode in the sub device. For external encoder or LCD pannel output,
* we also need to set up the lcd port for the required mode. So setup
* the lcd port for the default mode that is configured in the board
* arch/arm/mach-davinci/board-dm355-evm.setup file for the external
* encoder.
*/
ret = vpbe_get_mode_info(vpbe_dev,
cfg->outputs[index].default_mode, index);
if (!ret) {
struct osd_state *osd_device = vpbe_dev->osd_device;
osd_device->ops.set_left_margin(osd_device,
vpbe_dev->current_timings.left_margin);
osd_device->ops.set_top_margin(osd_device,
vpbe_dev->current_timings.upper_margin);
vpbe_dev->current_sd_index = sd_index;
vpbe_dev->current_out_index = index;
}
out:
mutex_unlock(&vpbe_dev->lock);
return ret;
}
static int vpbe_set_default_output(struct vpbe_device *vpbe_dev)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
int ret = 0;
int i;
for (i = 0; i < cfg->num_outputs; i++) {
if (!strcmp(def_output,
cfg->outputs[i].output.name)) {
ret = vpbe_set_output(vpbe_dev, i);
if (!ret)
vpbe_dev->current_out_index = i;
return ret;
}
}
return ret;
}
/**
* vpbe_get_output - Get output
* @vpbe_dev - vpbe device ptr
*
* return current vpbe output to the the index
*/
static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
{
return vpbe_dev->current_out_index;
}
/**
* vpbe_s_dv_timings - Set the given preset timings in the encoder
*
* Sets the timings if supported by the current encoder. Return the status.
* 0 - success & -EINVAL on error
*/
static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
struct v4l2_dv_timings *dv_timings)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
int out_index = vpbe_dev->current_out_index;
struct vpbe_output *output = &cfg->outputs[out_index];
int sd_index = vpbe_dev->current_sd_index;
int ret, i;
if (!(cfg->outputs[out_index].output.capabilities &
V4L2_OUT_CAP_DV_TIMINGS))
return -EINVAL;
for (i = 0; i < output->num_modes; i++) {
if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS &&
!memcmp(&output->modes[i].dv_timings,
dv_timings, sizeof(*dv_timings)))
break;
}
if (i >= output->num_modes)
return -EINVAL;
vpbe_dev->current_timings = output->modes[i];
mutex_lock(&vpbe_dev->lock);
ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
s_dv_timings, dv_timings);
if (!ret && (vpbe_dev->amp != NULL)) {
/* Call amplifier subdevice */
ret = v4l2_subdev_call(vpbe_dev->amp, video,
s_dv_timings, dv_timings);
}
/* set the lcd controller output for the given mode */
if (!ret) {
struct osd_state *osd_device = vpbe_dev->osd_device;
osd_device->ops.set_left_margin(osd_device,
vpbe_dev->current_timings.left_margin);
osd_device->ops.set_top_margin(osd_device,
vpbe_dev->current_timings.upper_margin);
}
mutex_unlock(&vpbe_dev->lock);
return ret;
}
/**
* vpbe_g_dv_timings - Get the timings in the current encoder
*
* Get the timings in the current encoder. Return the status. 0 - success
* -EINVAL on error
*/
static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
struct v4l2_dv_timings *dv_timings)
{
if (vpbe_dev->current_timings.timings_type &
VPBE_ENC_DV_TIMINGS) {
*dv_timings = vpbe_dev->current_timings.dv_timings;
return 0;
}
return -EINVAL;
}
/**
* vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder
*
* Get the timings in the current encoder. Return the status. 0 - success
* -EINVAL on error
*/
static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
struct v4l2_enum_dv_timings *timings)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
int out_index = vpbe_dev->current_out_index;
struct vpbe_output *output = &cfg->outputs[out_index];
int j = 0;
int i;
if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
return -EINVAL;
for (i = 0; i < output->num_modes; i++) {
if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS) {
if (j == timings->index)
break;
j++;
}
}
if (i == output->num_modes)
return -EINVAL;
timings->timings = output->modes[i].dv_timings;
return 0;
}
/**
* vpbe_s_std - Set the given standard in the encoder
*
* Sets the standard if supported by the current encoder. Return the status.
* 0 - success & -EINVAL on error
*/
static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id std_id)
{
struct vpbe_config *cfg = vpbe_dev->cfg;
int out_index = vpbe_dev->current_out_index;
int sd_index = vpbe_dev->current_sd_index;
int ret;
if (!(cfg->outputs[out_index].output.capabilities &
V4L2_OUT_CAP_STD))
return -EINVAL;
ret = vpbe_get_std_info(vpbe_dev, std_id);
if (ret)
return ret;
mutex_lock(&vpbe_dev->lock);
ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
s_std_output, std_id);
/* set the lcd controller output for the given mode */
if (!ret) {
struct osd_state *osd_device = vpbe_dev->osd_device;
osd_device->ops.set_left_margin(osd_device,
vpbe_dev->current_timings.left_margin);
osd_device->ops.set_top_margin(osd_device,
vpbe_dev->current_timings.upper_margin);
}
mutex_unlock(&vpbe_dev->lock);
return ret;
}
/**
* vpbe_g_std - Get the standard in the current encoder
*
* Get the standard in the current encoder. Return the status. 0 - success
* -EINVAL on error
*/
static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
{
struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
if (cur_timings->timings_type & VPBE_ENC_STD) {
*std_id = cur_timings->std_id;
return 0;
}
return -EINVAL;
}
/**
* vpbe_set_mode - Set mode in the current encoder using mode info
*
* Use the mode string to decide what timings to set in the encoder
* This is typically useful when fbset command is used to change the current
* timings by specifying a string to indicate the timings.
*/
static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
struct vpbe_enc_mode_info *mode_info)
{
struct vpbe_enc_mode_info *preset_mode = NULL;
struct vpbe_config *cfg = vpbe_dev->cfg;
struct v4l2_dv_timings dv_timings;
struct osd_state *osd_device;
int out_index = vpbe_dev->current_out_index;
int ret = 0;
int i;
if ((NULL == mode_info) || (NULL == mode_info->name))
return -EINVAL;
for (i = 0; i < cfg->outputs[out_index].num_modes; i++) {
if (!strcmp(mode_info->name,
cfg->outputs[out_index].modes[i].name)) {
preset_mode = &cfg->outputs[out_index].modes[i];
/*
* it may be one of the 3 timings type. Check and
* invoke right API
*/
if (preset_mode->timings_type & VPBE_ENC_STD)
return vpbe_s_std(vpbe_dev,
preset_mode->std_id);
if (preset_mode->timings_type &
VPBE_ENC_DV_TIMINGS) {
dv_timings =
preset_mode->dv_timings;
return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
}
}
}
/* Only custom timing should reach here */
if (preset_mode == NULL)
return -EINVAL;
mutex_lock(&vpbe_dev->lock);
osd_device = vpbe_dev->osd_device;
vpbe_dev->current_timings = *preset_mode;
osd_device->ops.set_left_margin(osd_device,
vpbe_dev->current_timings.left_margin);
osd_device->ops.set_top_margin(osd_device,
vpbe_dev->current_timings.upper_margin);
mutex_unlock(&vpbe_dev->lock);
return ret;
}
static int vpbe_set_default_mode(struct vpbe_device *vpbe_dev)
{
int ret;
ret = vpbe_get_std_info_by_name(vpbe_dev, def_mode);
if (ret)
return ret;
/* set the default mode in the encoder */
return vpbe_set_mode(vpbe_dev, &vpbe_dev->current_timings);
}
static int platform_device_get(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct vpbe_device *vpbe_dev = data;
if (strstr(pdev->name, "vpbe-osd") != NULL)
vpbe_dev->osd_device = platform_get_drvdata(pdev);
if (strstr(pdev->name, "vpbe-venc") != NULL)
vpbe_dev->venc_device = dev_get_platdata(&pdev->dev);
return 0;
}
/**
* vpbe_initialize() - Initialize the vpbe display controller
* @vpbe_dev - vpbe device ptr
*
* Master frame buffer device drivers calls this to initialize vpbe
* display controller. This will then registers v4l2 device and the sub
* devices and sets a current encoder sub device for display. v4l2 display
* device driver is the master and frame buffer display device driver is
* the slave. Frame buffer display driver checks the initialized during
* probe and exit if not initialized. Returns status.
*/
static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
{
struct encoder_config_info *enc_info;
struct amp_config_info *amp_info;
struct v4l2_subdev **enc_subdev;
struct osd_state *osd_device;
struct i2c_adapter *i2c_adap;
int num_encoders;
int ret = 0;
int err;
int i;
/*
* v4l2 abd FBDev frame buffer devices will get the vpbe_dev pointer
* from the platform device by iteration of platform drivers and
* matching with device name
*/
if (NULL == vpbe_dev || NULL == dev) {
printk(KERN_ERR "Null device pointers.\n");
return -ENODEV;
}
if (vpbe_dev->initialized)
return 0;
mutex_lock(&vpbe_dev->lock);
if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
/* We have dac clock available for platform */
vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
if (IS_ERR(vpbe_dev->dac_clk)) {
ret = PTR_ERR(vpbe_dev->dac_clk);
goto fail_mutex_unlock;
}
if (clk_prepare_enable(vpbe_dev->dac_clk)) {
ret = -ENODEV;
goto fail_mutex_unlock;
}
}
/* first enable vpss clocks */
vpss_enable_clock(VPSS_VPBE_CLOCK, 1);
/* First register a v4l2 device */
ret = v4l2_device_register(dev, &vpbe_dev->v4l2_dev);
if (ret) {
v4l2_err(dev->driver,
"Unable to register v4l2 device.\n");
goto fail_clk_put;
}
v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev,
platform_device_get);
if (err < 0) {
ret = err;
goto fail_dev_unregister;
}
vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev,
vpbe_dev->cfg->venc.module_name);
/* register venc sub device */
if (vpbe_dev->venc == NULL) {
v4l2_err(&vpbe_dev->v4l2_dev,
"vpbe unable to init venc sub device\n");
ret = -ENODEV;
goto fail_dev_unregister;
}
/* initialize osd device */
osd_device = vpbe_dev->osd_device;
if (NULL != osd_device->ops.initialize) {
err = osd_device->ops.initialize(osd_device);
if (err) {
v4l2_err(&vpbe_dev->v4l2_dev,
"unable to initialize the OSD device");
err = -ENOMEM;
goto fail_dev_unregister;
}
}
/*
* Register any external encoders that are configured. At index 0 we
* store venc sd index.
*/
num_encoders = vpbe_dev->cfg->num_ext_encoders + 1;
vpbe_dev->encoders = kmalloc(
sizeof(struct v4l2_subdev *)*num_encoders,
GFP_KERNEL);
if (NULL == vpbe_dev->encoders) {
v4l2_err(&vpbe_dev->v4l2_dev,
"unable to allocate memory for encoders sub devices");
ret = -ENOMEM;
goto fail_dev_unregister;
}
i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
for (i = 0; i < (vpbe_dev->cfg->num_ext_encoders + 1); i++) {
if (i == 0) {
/* venc is at index 0 */
enc_subdev = &vpbe_dev->encoders[i];
*enc_subdev = vpbe_dev->venc;
continue;
}
enc_info = &vpbe_dev->cfg->ext_encoders[i];
if (enc_info->is_i2c) {
enc_subdev = &vpbe_dev->encoders[i];
*enc_subdev = v4l2_i2c_new_subdev_board(
&vpbe_dev->v4l2_dev, i2c_adap,
&enc_info->board_info, NULL);
if (*enc_subdev)
v4l2_info(&vpbe_dev->v4l2_dev,
"v4l2 sub device %s registered\n",
enc_info->module_name);
else {
v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s"
" failed to register",
enc_info->module_name);
ret = -ENODEV;
goto fail_kfree_encoders;
}
} else
v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
" currently not supported");
}
/* Add amplifier subdevice for dm365 */
if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) &&
vpbe_dev->cfg->amp != NULL) {
amp_info = vpbe_dev->cfg->amp;
if (amp_info->is_i2c) {
vpbe_dev->amp = v4l2_i2c_new_subdev_board(
&vpbe_dev->v4l2_dev, i2c_adap,
&amp_info->board_info, NULL);
if (!vpbe_dev->amp) {
v4l2_err(&vpbe_dev->v4l2_dev,
"amplifier %s failed to register",
amp_info->module_name);
ret = -ENODEV;
goto fail_kfree_encoders;
}
v4l2_info(&vpbe_dev->v4l2_dev,
"v4l2 sub device %s registered\n",
amp_info->module_name);
} else {
vpbe_dev->amp = NULL;
v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers"
" currently not supported");
}
} else {
vpbe_dev->amp = NULL;
}
/* set the current encoder and output to that of venc by default */
vpbe_dev->current_sd_index = 0;
vpbe_dev->current_out_index = 0;
mutex_unlock(&vpbe_dev->lock);
printk(KERN_NOTICE "Setting default output to %s\n", def_output);
ret = vpbe_set_default_output(vpbe_dev);
if (ret) {
v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
def_output);
return ret;
}
printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
ret = vpbe_set_default_mode(vpbe_dev);
if (ret) {
v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
def_mode);
return ret;
}
vpbe_dev->initialized = 1;
/* TBD handling of bootargs for default output and mode */
return 0;
fail_kfree_encoders:
kfree(vpbe_dev->encoders);
fail_dev_unregister:
v4l2_device_unregister(&vpbe_dev->v4l2_dev);
fail_clk_put:
if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
clk_disable_unprepare(vpbe_dev->dac_clk);
clk_put(vpbe_dev->dac_clk);
}
fail_mutex_unlock:
mutex_unlock(&vpbe_dev->lock);
return ret;
}
/**
* vpbe_deinitialize() - de-initialize the vpbe display controller
* @dev - Master and slave device ptr
*
* vpbe_master and slave frame buffer devices calls this to de-initialize
* the display controller. It is called when master and slave device
* driver modules are removed and no longer requires the display controller.
*/
static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
{
v4l2_device_unregister(&vpbe_dev->v4l2_dev);
if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
clk_disable_unprepare(vpbe_dev->dac_clk);
clk_put(vpbe_dev->dac_clk);
}
kfree(vpbe_dev->amp);
kfree(vpbe_dev->encoders);
vpbe_dev->initialized = 0;
/* disable vpss clocks */
vpss_enable_clock(VPSS_VPBE_CLOCK, 0);
}
static struct vpbe_device_ops vpbe_dev_ops = {
.g_cropcap = vpbe_g_cropcap,
.enum_outputs = vpbe_enum_outputs,
.set_output = vpbe_set_output,
.get_output = vpbe_get_output,
.s_dv_timings = vpbe_s_dv_timings,
.g_dv_timings = vpbe_g_dv_timings,
.enum_dv_timings = vpbe_enum_dv_timings,
.s_std = vpbe_s_std,
.g_std = vpbe_g_std,
.initialize = vpbe_initialize,
.deinitialize = vpbe_deinitialize,
.get_mode_info = vpbe_get_current_mode_info,
.set_mode = vpbe_set_mode,
};
static int vpbe_probe(struct platform_device *pdev)
{
struct vpbe_device *vpbe_dev;
struct vpbe_config *cfg;
int ret = -EINVAL;
if (pdev->dev.platform_data == NULL) {
v4l2_err(pdev->dev.driver, "No platform data\n");
return -ENODEV;
}
cfg = pdev->dev.platform_data;
if (!cfg->module_name[0] ||
!cfg->osd.module_name[0] ||
!cfg->venc.module_name[0]) {
v4l2_err(pdev->dev.driver, "vpbe display module names not"
" defined\n");
return ret;
}
vpbe_dev = kzalloc(sizeof(*vpbe_dev), GFP_KERNEL);
if (vpbe_dev == NULL) {
v4l2_err(pdev->dev.driver, "Unable to allocate memory"
" for vpbe_device\n");
return -ENOMEM;
}
vpbe_dev->cfg = cfg;
vpbe_dev->ops = vpbe_dev_ops;
vpbe_dev->pdev = &pdev->dev;
if (cfg->outputs->num_modes > 0)
vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0];
else {
kfree(vpbe_dev);
return -ENODEV;
}
/* set the driver data in platform device */
platform_set_drvdata(pdev, vpbe_dev);
mutex_init(&vpbe_dev->lock);
return 0;
}
static int vpbe_remove(struct platform_device *device)
{
struct vpbe_device *vpbe_dev = platform_get_drvdata(device);
kfree(vpbe_dev);
return 0;
}
static struct platform_driver vpbe_driver = {
.driver = {
.name = "vpbe_controller",
.owner = THIS_MODULE,
},
.probe = vpbe_probe,
.remove = vpbe_remove,
};
module_platform_driver(vpbe_driver);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,364 @@
/*
* Copyright (C) 2006-2010 Texas Instruments Inc
*
* 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.
*
* 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
*/
#ifndef _VPBE_OSD_REGS_H
#define _VPBE_OSD_REGS_H
/* VPBE Global Registers */
#define VPBE_PID 0x0
#define VPBE_PCR 0x4
/* VPSS CLock Registers */
#define VPSSCLK_PID 0x00
#define VPSSCLK_CLKCTRL 0x04
/* VPSS Buffer Logic Registers */
#define VPSSBL_PID 0x00
#define VPSSBL_PCR 0x04
#define VPSSBL_BCR 0x08
#define VPSSBL_INTSTAT 0x0C
#define VPSSBL_INTSEL 0x10
#define VPSSBL_EVTSEL 0x14
#define VPSSBL_MEMCTRL 0x18
#define VPSSBL_CCDCMUX 0x1C
/* DM365 ISP5 system configuration */
#define ISP5_PID 0x0
#define ISP5_PCCR 0x4
#define ISP5_BCR 0x8
#define ISP5_INTSTAT 0xC
#define ISP5_INTSEL1 0x10
#define ISP5_INTSEL2 0x14
#define ISP5_INTSEL3 0x18
#define ISP5_EVTSEL 0x1c
#define ISP5_CCDCMUX 0x20
/* VPBE On-Screen Display Subsystem Registers (OSD) */
#define OSD_MODE 0x00
#define OSD_VIDWINMD 0x04
#define OSD_OSDWIN0MD 0x08
#define OSD_OSDWIN1MD 0x0C
#define OSD_OSDATRMD 0x0C
#define OSD_RECTCUR 0x10
#define OSD_VIDWIN0OFST 0x18
#define OSD_VIDWIN1OFST 0x1C
#define OSD_OSDWIN0OFST 0x20
#define OSD_OSDWIN1OFST 0x24
#define OSD_VIDWINADH 0x28
#define OSD_VIDWIN0ADL 0x2C
#define OSD_VIDWIN0ADR 0x2C
#define OSD_VIDWIN1ADL 0x30
#define OSD_VIDWIN1ADR 0x30
#define OSD_OSDWINADH 0x34
#define OSD_OSDWIN0ADL 0x38
#define OSD_OSDWIN0ADR 0x38
#define OSD_OSDWIN1ADL 0x3C
#define OSD_OSDWIN1ADR 0x3C
#define OSD_BASEPX 0x40
#define OSD_BASEPY 0x44
#define OSD_VIDWIN0XP 0x48
#define OSD_VIDWIN0YP 0x4C
#define OSD_VIDWIN0XL 0x50
#define OSD_VIDWIN0YL 0x54
#define OSD_VIDWIN1XP 0x58
#define OSD_VIDWIN1YP 0x5C
#define OSD_VIDWIN1XL 0x60
#define OSD_VIDWIN1YL 0x64
#define OSD_OSDWIN0XP 0x68
#define OSD_OSDWIN0YP 0x6C
#define OSD_OSDWIN0XL 0x70
#define OSD_OSDWIN0YL 0x74
#define OSD_OSDWIN1XP 0x78
#define OSD_OSDWIN1YP 0x7C
#define OSD_OSDWIN1XL 0x80
#define OSD_OSDWIN1YL 0x84
#define OSD_CURXP 0x88
#define OSD_CURYP 0x8C
#define OSD_CURXL 0x90
#define OSD_CURYL 0x94
#define OSD_W0BMP01 0xA0
#define OSD_W0BMP23 0xA4
#define OSD_W0BMP45 0xA8
#define OSD_W0BMP67 0xAC
#define OSD_W0BMP89 0xB0
#define OSD_W0BMPAB 0xB4
#define OSD_W0BMPCD 0xB8
#define OSD_W0BMPEF 0xBC
#define OSD_W1BMP01 0xC0
#define OSD_W1BMP23 0xC4
#define OSD_W1BMP45 0xC8
#define OSD_W1BMP67 0xCC
#define OSD_W1BMP89 0xD0
#define OSD_W1BMPAB 0xD4
#define OSD_W1BMPCD 0xD8
#define OSD_W1BMPEF 0xDC
#define OSD_VBNDRY 0xE0
#define OSD_EXTMODE 0xE4
#define OSD_MISCCTL 0xE8
#define OSD_CLUTRAMYCB 0xEC
#define OSD_CLUTRAMCR 0xF0
#define OSD_TRANSPVAL 0xF4
#define OSD_TRANSPVALL 0xF4
#define OSD_TRANSPVALU 0xF8
#define OSD_TRANSPBMPIDX 0xFC
#define OSD_PPVWIN0ADR 0xFC
/* bit definitions */
#define VPBE_PCR_VENC_DIV (1 << 1)
#define VPBE_PCR_CLK_OFF (1 << 0)
#define VPSSBL_INTSTAT_HSSIINT (1 << 14)
#define VPSSBL_INTSTAT_CFALDINT (1 << 13)
#define VPSSBL_INTSTAT_IPIPE_INT5 (1 << 12)
#define VPSSBL_INTSTAT_IPIPE_INT4 (1 << 11)
#define VPSSBL_INTSTAT_IPIPE_INT3 (1 << 10)
#define VPSSBL_INTSTAT_IPIPE_INT2 (1 << 9)
#define VPSSBL_INTSTAT_IPIPE_INT1 (1 << 8)
#define VPSSBL_INTSTAT_IPIPE_INT0 (1 << 7)
#define VPSSBL_INTSTAT_IPIPEIFINT (1 << 6)
#define VPSSBL_INTSTAT_OSDINT (1 << 5)
#define VPSSBL_INTSTAT_VENCINT (1 << 4)
#define VPSSBL_INTSTAT_H3AINT (1 << 3)
#define VPSSBL_INTSTAT_CCDC_VDINT2 (1 << 2)
#define VPSSBL_INTSTAT_CCDC_VDINT1 (1 << 1)
#define VPSSBL_INTSTAT_CCDC_VDINT0 (1 << 0)
/* DM365 ISP5 bit definitions */
#define ISP5_INTSTAT_VENCINT (1 << 21)
#define ISP5_INTSTAT_OSDINT (1 << 20)
/* VMOD TVTYP options for HDMD=0 */
#define SDTV_NTSC 0
#define SDTV_PAL 1
/* VMOD TVTYP options for HDMD=1 */
#define HDTV_525P 0
#define HDTV_625P 1
#define HDTV_1080I 2
#define HDTV_720P 3
#define OSD_MODE_CS (1 << 15)
#define OSD_MODE_OVRSZ (1 << 14)
#define OSD_MODE_OHRSZ (1 << 13)
#define OSD_MODE_EF (1 << 12)
#define OSD_MODE_VVRSZ (1 << 11)
#define OSD_MODE_VHRSZ (1 << 10)
#define OSD_MODE_FSINV (1 << 9)
#define OSD_MODE_BCLUT (1 << 8)
#define OSD_MODE_CABG_SHIFT 0
#define OSD_MODE_CABG (0xff << 0)
#define OSD_VIDWINMD_VFINV (1 << 15)
#define OSD_VIDWINMD_V1EFC (1 << 14)
#define OSD_VIDWINMD_VHZ1_SHIFT 12
#define OSD_VIDWINMD_VHZ1 (3 << 12)
#define OSD_VIDWINMD_VVZ1_SHIFT 10
#define OSD_VIDWINMD_VVZ1 (3 << 10)
#define OSD_VIDWINMD_VFF1 (1 << 9)
#define OSD_VIDWINMD_ACT1 (1 << 8)
#define OSD_VIDWINMD_V0EFC (1 << 6)
#define OSD_VIDWINMD_VHZ0_SHIFT 4
#define OSD_VIDWINMD_VHZ0 (3 << 4)
#define OSD_VIDWINMD_VVZ0_SHIFT 2
#define OSD_VIDWINMD_VVZ0 (3 << 2)
#define OSD_VIDWINMD_VFF0 (1 << 1)
#define OSD_VIDWINMD_ACT0 (1 << 0)
#define OSD_OSDWIN0MD_ATN0E (1 << 14)
#define OSD_OSDWIN0MD_RGB0E (1 << 13)
#define OSD_OSDWIN0MD_BMP0MD_SHIFT 13
#define OSD_OSDWIN0MD_BMP0MD (3 << 13)
#define OSD_OSDWIN0MD_CLUTS0 (1 << 12)
#define OSD_OSDWIN0MD_OHZ0_SHIFT 10
#define OSD_OSDWIN0MD_OHZ0 (3 << 10)
#define OSD_OSDWIN0MD_OVZ0_SHIFT 8
#define OSD_OSDWIN0MD_OVZ0 (3 << 8)
#define OSD_OSDWIN0MD_BMW0_SHIFT 6
#define OSD_OSDWIN0MD_BMW0 (3 << 6)
#define OSD_OSDWIN0MD_BLND0_SHIFT 3
#define OSD_OSDWIN0MD_BLND0 (7 << 3)
#define OSD_OSDWIN0MD_TE0 (1 << 2)
#define OSD_OSDWIN0MD_OFF0 (1 << 1)
#define OSD_OSDWIN0MD_OACT0 (1 << 0)
#define OSD_OSDWIN1MD_OASW (1 << 15)
#define OSD_OSDWIN1MD_ATN1E (1 << 14)
#define OSD_OSDWIN1MD_RGB1E (1 << 13)
#define OSD_OSDWIN1MD_BMP1MD_SHIFT 13
#define OSD_OSDWIN1MD_BMP1MD (3 << 13)
#define OSD_OSDWIN1MD_CLUTS1 (1 << 12)
#define OSD_OSDWIN1MD_OHZ1_SHIFT 10
#define OSD_OSDWIN1MD_OHZ1 (3 << 10)
#define OSD_OSDWIN1MD_OVZ1_SHIFT 8
#define OSD_OSDWIN1MD_OVZ1 (3 << 8)
#define OSD_OSDWIN1MD_BMW1_SHIFT 6
#define OSD_OSDWIN1MD_BMW1 (3 << 6)
#define OSD_OSDWIN1MD_BLND1_SHIFT 3
#define OSD_OSDWIN1MD_BLND1 (7 << 3)
#define OSD_OSDWIN1MD_TE1 (1 << 2)
#define OSD_OSDWIN1MD_OFF1 (1 << 1)
#define OSD_OSDWIN1MD_OACT1 (1 << 0)
#define OSD_OSDATRMD_OASW (1 << 15)
#define OSD_OSDATRMD_OHZA_SHIFT 10
#define OSD_OSDATRMD_OHZA (3 << 10)
#define OSD_OSDATRMD_OVZA_SHIFT 8
#define OSD_OSDATRMD_OVZA (3 << 8)
#define OSD_OSDATRMD_BLNKINT_SHIFT 6
#define OSD_OSDATRMD_BLNKINT (3 << 6)
#define OSD_OSDATRMD_OFFA (1 << 1)
#define OSD_OSDATRMD_BLNK (1 << 0)
#define OSD_RECTCUR_RCAD_SHIFT 8
#define OSD_RECTCUR_RCAD (0xff << 8)
#define OSD_RECTCUR_CLUTSR (1 << 7)
#define OSD_RECTCUR_RCHW_SHIFT 4
#define OSD_RECTCUR_RCHW (7 << 4)
#define OSD_RECTCUR_RCVW_SHIFT 1
#define OSD_RECTCUR_RCVW (7 << 1)
#define OSD_RECTCUR_RCACT (1 << 0)
#define OSD_VIDWIN0OFST_V0LO (0x1ff << 0)
#define OSD_VIDWIN1OFST_V1LO (0x1ff << 0)
#define OSD_OSDWIN0OFST_O0LO (0x1ff << 0)
#define OSD_OSDWIN1OFST_O1LO (0x1ff << 0)
#define OSD_WINOFST_AH_SHIFT 9
#define OSD_VIDWIN0OFST_V0AH (0xf << 9)
#define OSD_VIDWIN1OFST_V1AH (0xf << 9)
#define OSD_OSDWIN0OFST_O0AH (0xf << 9)
#define OSD_OSDWIN1OFST_O1AH (0xf << 9)
#define OSD_VIDWINADH_V1AH_SHIFT 8
#define OSD_VIDWINADH_V1AH (0x7f << 8)
#define OSD_VIDWINADH_V0AH_SHIFT 0
#define OSD_VIDWINADH_V0AH (0x7f << 0)
#define OSD_VIDWIN0ADL_V0AL (0xffff << 0)
#define OSD_VIDWIN1ADL_V1AL (0xffff << 0)
#define OSD_OSDWINADH_O1AH_SHIFT 8
#define OSD_OSDWINADH_O1AH (0x7f << 8)
#define OSD_OSDWINADH_O0AH_SHIFT 0
#define OSD_OSDWINADH_O0AH (0x7f << 0)
#define OSD_OSDWIN0ADL_O0AL (0xffff << 0)
#define OSD_OSDWIN1ADL_O1AL (0xffff << 0)
#define OSD_BASEPX_BPX (0x3ff << 0)
#define OSD_BASEPY_BPY (0x1ff << 0)
#define OSD_VIDWIN0XP_V0X (0x7ff << 0)
#define OSD_VIDWIN0YP_V0Y (0x7ff << 0)
#define OSD_VIDWIN0XL_V0W (0x7ff << 0)
#define OSD_VIDWIN0YL_V0H (0x7ff << 0)
#define OSD_VIDWIN1XP_V1X (0x7ff << 0)
#define OSD_VIDWIN1YP_V1Y (0x7ff << 0)
#define OSD_VIDWIN1XL_V1W (0x7ff << 0)
#define OSD_VIDWIN1YL_V1H (0x7ff << 0)
#define OSD_OSDWIN0XP_W0X (0x7ff << 0)
#define OSD_OSDWIN0YP_W0Y (0x7ff << 0)
#define OSD_OSDWIN0XL_W0W (0x7ff << 0)
#define OSD_OSDWIN0YL_W0H (0x7ff << 0)
#define OSD_OSDWIN1XP_W1X (0x7ff << 0)
#define OSD_OSDWIN1YP_W1Y (0x7ff << 0)
#define OSD_OSDWIN1XL_W1W (0x7ff << 0)
#define OSD_OSDWIN1YL_W1H (0x7ff << 0)
#define OSD_CURXP_RCSX (0x7ff << 0)
#define OSD_CURYP_RCSY (0x7ff << 0)
#define OSD_CURXL_RCSW (0x7ff << 0)
#define OSD_CURYL_RCSH (0x7ff << 0)
#define OSD_EXTMODE_EXPMDSEL (1 << 15)
#define OSD_EXTMODE_SCRNHEXP_SHIFT 13
#define OSD_EXTMODE_SCRNHEXP (3 << 13)
#define OSD_EXTMODE_SCRNVEXP (1 << 12)
#define OSD_EXTMODE_OSD1BLDCHR (1 << 11)
#define OSD_EXTMODE_OSD0BLDCHR (1 << 10)
#define OSD_EXTMODE_ATNOSD1EN (1 << 9)
#define OSD_EXTMODE_ATNOSD0EN (1 << 8)
#define OSD_EXTMODE_OSDHRSZ15 (1 << 7)
#define OSD_EXTMODE_VIDHRSZ15 (1 << 6)
#define OSD_EXTMODE_ZMFILV1HEN (1 << 5)
#define OSD_EXTMODE_ZMFILV1VEN (1 << 4)
#define OSD_EXTMODE_ZMFILV0HEN (1 << 3)
#define OSD_EXTMODE_ZMFILV0VEN (1 << 2)
#define OSD_EXTMODE_EXPFILHEN (1 << 1)
#define OSD_EXTMODE_EXPFILVEN (1 << 0)
#define OSD_MISCCTL_BLDSEL (1 << 15)
#define OSD_MISCCTL_S420D (1 << 14)
#define OSD_MISCCTL_BMAPT (1 << 13)
#define OSD_MISCCTL_DM365M (1 << 12)
#define OSD_MISCCTL_RGBEN (1 << 7)
#define OSD_MISCCTL_RGBWIN (1 << 6)
#define OSD_MISCCTL_DMANG (1 << 6)
#define OSD_MISCCTL_TMON (1 << 5)
#define OSD_MISCCTL_RSEL (1 << 4)
#define OSD_MISCCTL_CPBSY (1 << 3)
#define OSD_MISCCTL_PPSW (1 << 2)
#define OSD_MISCCTL_PPRV (1 << 1)
#define OSD_CLUTRAMYCB_Y_SHIFT 8
#define OSD_CLUTRAMYCB_Y (0xff << 8)
#define OSD_CLUTRAMYCB_CB_SHIFT 0
#define OSD_CLUTRAMYCB_CB (0xff << 0)
#define OSD_CLUTRAMCR_CR_SHIFT 8
#define OSD_CLUTRAMCR_CR (0xff << 8)
#define OSD_CLUTRAMCR_CADDR_SHIFT 0
#define OSD_CLUTRAMCR_CADDR (0xff << 0)
#define OSD_TRANSPVAL_RGBTRANS (0xffff << 0)
#define OSD_TRANSPVALL_RGBL (0xffff << 0)
#define OSD_TRANSPVALU_Y_SHIFT 8
#define OSD_TRANSPVALU_Y (0xff << 8)
#define OSD_TRANSPVALU_RGBU_SHIFT 0
#define OSD_TRANSPVALU_RGBU (0xff << 0)
#define OSD_TRANSPBMPIDX_BMP1_SHIFT 8
#define OSD_TRANSPBMPIDX_BMP1 (0xff << 8)
#define OSD_TRANSPBMPIDX_BMP0_SHIFT 0
#define OSD_TRANSPBMPIDX_BMP0 0xff
#endif /* _DAVINCI_VPBE_H_ */

View File

@@ -0,0 +1,758 @@
/*
* Copyright (C) 2010 Texas Instruments Inc
*
* 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.
*
* 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/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <linux/slab.h>
#include <mach/hardware.h>
#include <mach/mux.h>
#include <linux/platform_data/i2c-davinci.h>
#include <linux/io.h>
#include <media/davinci/vpbe_types.h>
#include <media/davinci/vpbe_venc.h>
#include <media/davinci/vpss.h>
#include <media/v4l2-device.h>
#include "vpbe_venc_regs.h"
#define MODULE_NAME "davinci-vpbe-venc"
static struct platform_device_id vpbe_venc_devtype[] = {
{
.name = DM644X_VPBE_VENC_SUBDEV_NAME,
.driver_data = VPBE_VERSION_1,
}, {
.name = DM365_VPBE_VENC_SUBDEV_NAME,
.driver_data = VPBE_VERSION_2,
}, {
.name = DM355_VPBE_VENC_SUBDEV_NAME,
.driver_data = VPBE_VERSION_3,
},
{
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, vpbe_venc_devtype);
static int debug = 2;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level 0-2");
struct venc_state {
struct v4l2_subdev sd;
struct venc_callback *callback;
struct venc_platform_data *pdata;
struct device *pdev;
u32 output;
v4l2_std_id std;
spinlock_t lock;
void __iomem *venc_base;
void __iomem *vdaccfg_reg;
enum vpbe_version venc_type;
};
static inline struct venc_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct venc_state, sd);
}
static inline u32 venc_read(struct v4l2_subdev *sd, u32 offset)
{
struct venc_state *venc = to_state(sd);
return readl(venc->venc_base + offset);
}
static inline u32 venc_write(struct v4l2_subdev *sd, u32 offset, u32 val)
{
struct venc_state *venc = to_state(sd);
writel(val, (venc->venc_base + offset));
return val;
}
static inline u32 venc_modify(struct v4l2_subdev *sd, u32 offset,
u32 val, u32 mask)
{
u32 new_val = (venc_read(sd, offset) & ~mask) | (val & mask);
venc_write(sd, offset, new_val);
return new_val;
}
static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
{
struct venc_state *venc = to_state(sd);
writel(val, venc->vdaccfg_reg);
val = readl(venc->vdaccfg_reg);
return val;
}
#define VDAC_COMPONENT 0x543
#define VDAC_S_VIDEO 0x210
/* This function sets the dac of the VPBE for various outputs
*/
static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
{
switch (out_index) {
case 0:
v4l2_dbg(debug, 1, sd, "Setting output to Composite\n");
venc_write(sd, VENC_DACSEL, 0);
break;
case 1:
v4l2_dbg(debug, 1, sd, "Setting output to Component\n");
venc_write(sd, VENC_DACSEL, VDAC_COMPONENT);
break;
case 2:
v4l2_dbg(debug, 1, sd, "Setting output to S-video\n");
venc_write(sd, VENC_DACSEL, VDAC_S_VIDEO);
break;
default:
return -EINVAL;
}
return 0;
}
static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
{
struct venc_state *venc = to_state(sd);
v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
if (benable) {
venc_write(sd, VENC_VMOD, 0);
venc_write(sd, VENC_CVBS, 0);
venc_write(sd, VENC_LCDOUT, 0);
venc_write(sd, VENC_HSPLS, 0);
venc_write(sd, VENC_HSTART, 0);
venc_write(sd, VENC_HVALID, 0);
venc_write(sd, VENC_HINT, 0);
venc_write(sd, VENC_VSPLS, 0);
venc_write(sd, VENC_VSTART, 0);
venc_write(sd, VENC_VVALID, 0);
venc_write(sd, VENC_VINT, 0);
venc_write(sd, VENC_YCCCTL, 0);
venc_write(sd, VENC_DACSEL, 0);
} else {
venc_write(sd, VENC_VMOD, 0);
/* disable VCLK output pin enable */
venc_write(sd, VENC_VIDCTL, 0x141);
/* Disable output sync pins */
venc_write(sd, VENC_SYNCCTL, 0);
/* Disable DCLOCK */
venc_write(sd, VENC_DCLKCTL, 0);
venc_write(sd, VENC_DRGBX1, 0x0000057C);
/* Disable LCD output control (accepting default polarity) */
venc_write(sd, VENC_LCDOUT, 0);
if (venc->venc_type != VPBE_VERSION_3)
venc_write(sd, VENC_CMPNT, 0x100);
venc_write(sd, VENC_HSPLS, 0);
venc_write(sd, VENC_HINT, 0);
venc_write(sd, VENC_HSTART, 0);
venc_write(sd, VENC_HVALID, 0);
venc_write(sd, VENC_VSPLS, 0);
venc_write(sd, VENC_VINT, 0);
venc_write(sd, VENC_VSTART, 0);
venc_write(sd, VENC_VVALID, 0);
venc_write(sd, VENC_HSDLY, 0);
venc_write(sd, VENC_VSDLY, 0);
venc_write(sd, VENC_YCCCTL, 0);
venc_write(sd, VENC_VSTARTA, 0);
/* Set OSD clock and OSD Sync Adavance registers */
venc_write(sd, VENC_OSDCLK0, 1);
venc_write(sd, VENC_OSDCLK1, 2);
}
}
static void
venc_enable_vpss_clock(int venc_type,
enum vpbe_enc_timings_type type,
unsigned int pclock)
{
if (venc_type == VPBE_VERSION_1)
return;
if (venc_type == VPBE_VERSION_2 && (type == VPBE_ENC_STD || (type ==
VPBE_ENC_DV_TIMINGS && pclock <= 27000000))) {
vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
vpss_enable_clock(VPSS_VPBE_CLOCK, 1);
return;
}
if (venc_type == VPBE_VERSION_3 && type == VPBE_ENC_STD)
vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 0);
}
#define VDAC_CONFIG_SD_V3 0x0E21A6B6
#define VDAC_CONFIG_SD_V2 0x081141CF
/*
* setting NTSC mode
*/
static int venc_set_ntsc(struct v4l2_subdev *sd)
{
u32 val;
struct venc_state *venc = to_state(sd);
struct venc_platform_data *pdata = venc->pdata;
v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
/* Setup clock at VPSS & VENC for SD */
vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
return -EINVAL;
venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_525_60);
venc_enabledigitaloutput(sd, 0);
if (venc->venc_type == VPBE_VERSION_3) {
venc_write(sd, VENC_CLKCTL, 0x01);
venc_write(sd, VENC_VIDCTL, 0);
val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
} else if (venc->venc_type == VPBE_VERSION_2) {
venc_write(sd, VENC_CLKCTL, 0x01);
venc_write(sd, VENC_VIDCTL, 0);
vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
} else {
/* to set VENC CLK DIV to 1 - final clock is 54 MHz */
venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
/* Set REC656 Mode */
venc_write(sd, VENC_YCCCTL, 0x1);
venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
}
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
VENC_VMOD_TVTYP);
venc_write(sd, VENC_DACTST, 0x0);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
return 0;
}
/*
* setting PAL mode
*/
static int venc_set_pal(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
/* Setup clock at VPSS & VENC for SD */
vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
return -EINVAL;
venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_625_50);
venc_enabledigitaloutput(sd, 0);
if (venc->venc_type == VPBE_VERSION_3) {
venc_write(sd, VENC_CLKCTL, 0x1);
venc_write(sd, VENC_VIDCTL, 0);
vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
} else if (venc->venc_type == VPBE_VERSION_2) {
venc_write(sd, VENC_CLKCTL, 0x1);
venc_write(sd, VENC_VIDCTL, 0);
vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
} else {
/* to set VENC CLK DIV to 1 - final clock is 54 MHz */
venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
/* Set REC656 Mode */
venc_write(sd, VENC_YCCCTL, 0x1);
}
venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
VENC_SYNCCTL_OVD);
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD,
(1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
venc_modify(sd, VENC_VMOD,
(0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
venc_modify(sd, VENC_VMOD,
(1 << VENC_VMOD_TVTYP_SHIFT),
VENC_VMOD_TVTYP);
venc_write(sd, VENC_DACTST, 0x0);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
return 0;
}
#define VDAC_CONFIG_HD_V2 0x081141EF
/*
* venc_set_480p59_94
*
* This function configures the video encoder to EDTV(525p) component setting.
*/
static int venc_set_480p59_94(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
struct venc_platform_data *pdata = venc->pdata;
v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
if (venc->venc_type != VPBE_VERSION_1 &&
venc->venc_type != VPBE_VERSION_2)
return -EINVAL;
/* Setup clock at VPSS & VENC for SD */
if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
return -EINVAL;
venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
venc_enabledigitaloutput(sd, 0);
if (venc->venc_type == VPBE_VERSION_2)
vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
venc_write(sd, VENC_OSDCLK0, 0);
venc_write(sd, VENC_OSDCLK1, 1);
if (venc->venc_type == VPBE_VERSION_1) {
venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
VENC_VDPRO_DAFRQ);
venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
VENC_VDPRO_DAUPS);
}
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
VENC_VMOD_TVTYP);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
return 0;
}
/*
* venc_set_625p
*
* This function configures the video encoder to HDTV(625p) component setting
*/
static int venc_set_576p50(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
struct venc_platform_data *pdata = venc->pdata;
v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
if (venc->venc_type != VPBE_VERSION_1 &&
venc->venc_type != VPBE_VERSION_2)
return -EINVAL;
/* Setup clock at VPSS & VENC for SD */
if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
return -EINVAL;
venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
venc_enabledigitaloutput(sd, 0);
if (venc->venc_type == VPBE_VERSION_2)
vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
venc_write(sd, VENC_OSDCLK0, 0);
venc_write(sd, VENC_OSDCLK1, 1);
if (venc->venc_type == VPBE_VERSION_1) {
venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
VENC_VDPRO_DAFRQ);
venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
VENC_VDPRO_DAUPS);
}
venc_write(sd, VENC_VMOD, 0);
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
VENC_VMOD_TVTYP);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
return 0;
}
/*
* venc_set_720p60_internal - Setup 720p60 in venc for dm365 only
*/
static int venc_set_720p60_internal(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
struct venc_platform_data *pdata = venc->pdata;
if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
return -EINVAL;
venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
venc_enabledigitaloutput(sd, 0);
venc_write(sd, VENC_OSDCLK0, 0);
venc_write(sd, VENC_OSDCLK1, 1);
venc_write(sd, VENC_VMOD, 0);
/* DM365 component HD mode */
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT),
VENC_VMOD_TVTYP);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
venc_write(sd, VENC_XHINTVL, 0);
return 0;
}
/*
* venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only
*/
static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
struct venc_platform_data *pdata = venc->pdata;
if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
return -EINVAL;
venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
venc_enabledigitaloutput(sd, 0);
venc_write(sd, VENC_OSDCLK0, 0);
venc_write(sd, VENC_OSDCLK1, 1);
venc_write(sd, VENC_VMOD, 0);
/* DM365 component HD mode */
venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
VENC_VMOD_VIE);
venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT),
VENC_VMOD_TVTYP);
venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
venc_write(sd, VENC_XHINTVL, 0);
return 0;
}
static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
{
v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
if (norm & V4L2_STD_525_60)
return venc_set_ntsc(sd);
else if (norm & V4L2_STD_625_50)
return venc_set_pal(sd);
return -EINVAL;
}
static int venc_s_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *dv_timings)
{
struct venc_state *venc = to_state(sd);
u32 height = dv_timings->bt.height;
int ret;
v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
if (height == 576)
return venc_set_576p50(sd);
else if (height == 480)
return venc_set_480p59_94(sd);
else if ((height == 720) &&
(venc->venc_type == VPBE_VERSION_2)) {
/* TBD setup internal 720p mode here */
ret = venc_set_720p60_internal(sd);
/* for DM365 VPBE, there is DAC inside */
vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
return ret;
} else if ((height == 1080) &&
(venc->venc_type == VPBE_VERSION_2)) {
/* TBD setup internal 1080i mode here */
ret = venc_set_1080i30_internal(sd);
/* for DM365 VPBE, there is DAC inside */
vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
return ret;
}
return -EINVAL;
}
static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
u32 config)
{
struct venc_state *venc = to_state(sd);
int ret;
v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
ret = venc_set_dac(sd, output);
if (!ret)
venc->output = output;
return ret;
}
static long venc_ioctl(struct v4l2_subdev *sd,
unsigned int cmd,
void *arg)
{
u32 val;
switch (cmd) {
case VENC_GET_FLD:
val = venc_read(sd, VENC_VSTAT);
*((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
VENC_VSTAT_FIDST);
break;
default:
v4l2_err(sd, "Wrong IOCTL cmd\n");
break;
}
return 0;
}
static const struct v4l2_subdev_core_ops venc_core_ops = {
.ioctl = venc_ioctl,
};
static const struct v4l2_subdev_video_ops venc_video_ops = {
.s_routing = venc_s_routing,
.s_std_output = venc_s_std_output,
.s_dv_timings = venc_s_dv_timings,
};
static const struct v4l2_subdev_ops venc_ops = {
.core = &venc_core_ops,
.video = &venc_video_ops,
};
static int venc_initialize(struct v4l2_subdev *sd)
{
struct venc_state *venc = to_state(sd);
int ret;
/* Set default to output to composite and std to NTSC */
venc->output = 0;
venc->std = V4L2_STD_525_60;
ret = venc_s_routing(sd, 0, venc->output, 0);
if (ret < 0) {
v4l2_err(sd, "Error setting output during init\n");
return -EINVAL;
}
ret = venc_s_std_output(sd, venc->std);
if (ret < 0) {
v4l2_err(sd, "Error setting std during init\n");
return -EINVAL;
}
return ret;
}
static int venc_device_get(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
struct venc_state **venc = data;
if (strstr(pdev->name, "vpbe-venc") != NULL)
*venc = platform_get_drvdata(pdev);
return 0;
}
struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
const char *venc_name)
{
struct venc_state *venc;
int err;
err = bus_for_each_dev(&platform_bus_type, NULL, &venc,
venc_device_get);
if (venc == NULL)
return NULL;
v4l2_subdev_init(&venc->sd, &venc_ops);
strcpy(venc->sd.name, venc_name);
if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
v4l2_err(v4l2_dev,
"vpbe unable to register venc sub device\n");
return NULL;
}
if (venc_initialize(&venc->sd)) {
v4l2_err(v4l2_dev,
"vpbe venc initialization failed\n");
return NULL;
}
return &venc->sd;
}
EXPORT_SYMBOL(venc_sub_dev_init);
static int venc_probe(struct platform_device *pdev)
{
const struct platform_device_id *pdev_id;
struct venc_state *venc;
struct resource *res;
int ret;
venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL);
if (venc == NULL)
return -ENOMEM;
pdev_id = platform_get_device_id(pdev);
if (!pdev_id) {
ret = -EINVAL;
goto free_mem;
}
venc->venc_type = pdev_id->driver_data;
venc->pdev = &pdev->dev;
venc->pdata = pdev->dev.platform_data;
if (NULL == venc->pdata) {
dev_err(venc->pdev, "Unable to get platform data for"
" VENC sub device");
ret = -ENOENT;
goto free_mem;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(venc->pdev,
"Unable to get VENC register address map\n");
ret = -ENODEV;
goto free_mem;
}
if (!request_mem_region(res->start, resource_size(res), "venc")) {
dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n");
ret = -ENODEV;
goto free_mem;
}
venc->venc_base = ioremap_nocache(res->start, resource_size(res));
if (!venc->venc_base) {
dev_err(venc->pdev, "Unable to map VENC IO space\n");
ret = -ENODEV;
goto release_venc_mem_region;
}
if (venc->venc_type != VPBE_VERSION_1) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
dev_err(venc->pdev,
"Unable to get VDAC_CONFIG address map\n");
ret = -ENODEV;
goto unmap_venc_io;
}
if (!request_mem_region(res->start,
resource_size(res), "venc")) {
dev_err(venc->pdev,
"Unable to reserve VDAC_CONFIG MMIO region\n");
ret = -ENODEV;
goto unmap_venc_io;
}
venc->vdaccfg_reg = ioremap_nocache(res->start,
resource_size(res));
if (!venc->vdaccfg_reg) {
dev_err(venc->pdev,
"Unable to map VDAC_CONFIG IO space\n");
ret = -ENODEV;
goto release_vdaccfg_mem_region;
}
}
spin_lock_init(&venc->lock);
platform_set_drvdata(pdev, venc);
dev_notice(venc->pdev, "VENC sub device probe success\n");
return 0;
release_vdaccfg_mem_region:
release_mem_region(res->start, resource_size(res));
unmap_venc_io:
iounmap(venc->venc_base);
release_venc_mem_region:
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
free_mem:
kfree(venc);
return ret;
}
static int venc_remove(struct platform_device *pdev)
{
struct venc_state *venc = platform_get_drvdata(pdev);
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iounmap((void *)venc->venc_base);
release_mem_region(res->start, resource_size(res));
if (venc->venc_type != VPBE_VERSION_1) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
iounmap((void *)venc->vdaccfg_reg);
release_mem_region(res->start, resource_size(res));
}
kfree(venc);
return 0;
}
static struct platform_driver venc_driver = {
.probe = venc_probe,
.remove = venc_remove,
.driver = {
.name = MODULE_NAME,
.owner = THIS_MODULE,
},
.id_table = vpbe_venc_devtype
};
module_platform_driver(venc_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VPBE VENC Driver");
MODULE_AUTHOR("Texas Instruments");

View File

@@ -0,0 +1,177 @@
/*
* Copyright (C) 2006-2010 Texas Instruments Inc
*
* 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..
*
* 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
*/
#ifndef _VPBE_VENC_REGS_H
#define _VPBE_VENC_REGS_H
/* VPBE Video Encoder / Digital LCD Subsystem Registers (VENC) */
#define VENC_VMOD 0x00
#define VENC_VIDCTL 0x04
#define VENC_VDPRO 0x08
#define VENC_SYNCCTL 0x0C
#define VENC_HSPLS 0x10
#define VENC_VSPLS 0x14
#define VENC_HINT 0x18
#define VENC_HSTART 0x1C
#define VENC_HVALID 0x20
#define VENC_VINT 0x24
#define VENC_VSTART 0x28
#define VENC_VVALID 0x2C
#define VENC_HSDLY 0x30
#define VENC_VSDLY 0x34
#define VENC_YCCCTL 0x38
#define VENC_RGBCTL 0x3C
#define VENC_RGBCLP 0x40
#define VENC_LINECTL 0x44
#define VENC_CULLLINE 0x48
#define VENC_LCDOUT 0x4C
#define VENC_BRTS 0x50
#define VENC_BRTW 0x54
#define VENC_ACCTL 0x58
#define VENC_PWMP 0x5C
#define VENC_PWMW 0x60
#define VENC_DCLKCTL 0x64
#define VENC_DCLKPTN0 0x68
#define VENC_DCLKPTN1 0x6C
#define VENC_DCLKPTN2 0x70
#define VENC_DCLKPTN3 0x74
#define VENC_DCLKPTN0A 0x78
#define VENC_DCLKPTN1A 0x7C
#define VENC_DCLKPTN2A 0x80
#define VENC_DCLKPTN3A 0x84
#define VENC_DCLKHS 0x88
#define VENC_DCLKHSA 0x8C
#define VENC_DCLKHR 0x90
#define VENC_DCLKVS 0x94
#define VENC_DCLKVR 0x98
#define VENC_CAPCTL 0x9C
#define VENC_CAPDO 0xA0
#define VENC_CAPDE 0xA4
#define VENC_ATR0 0xA8
#define VENC_ATR1 0xAC
#define VENC_ATR2 0xB0
#define VENC_VSTAT 0xB8
#define VENC_RAMADR 0xBC
#define VENC_RAMPORT 0xC0
#define VENC_DACTST 0xC4
#define VENC_YCOLVL 0xC8
#define VENC_SCPROG 0xCC
#define VENC_CVBS 0xDC
#define VENC_CMPNT 0xE0
#define VENC_ETMG0 0xE4
#define VENC_ETMG1 0xE8
#define VENC_ETMG2 0xEC
#define VENC_ETMG3 0xF0
#define VENC_DACSEL 0xF4
#define VENC_ARGBX0 0x100
#define VENC_ARGBX1 0x104
#define VENC_ARGBX2 0x108
#define VENC_ARGBX3 0x10C
#define VENC_ARGBX4 0x110
#define VENC_DRGBX0 0x114
#define VENC_DRGBX1 0x118
#define VENC_DRGBX2 0x11C
#define VENC_DRGBX3 0x120
#define VENC_DRGBX4 0x124
#define VENC_VSTARTA 0x128
#define VENC_OSDCLK0 0x12C
#define VENC_OSDCLK1 0x130
#define VENC_HVLDCL0 0x134
#define VENC_HVLDCL1 0x138
#define VENC_OSDHADV 0x13C
#define VENC_CLKCTL 0x140
#define VENC_GAMCTL 0x144
#define VENC_XHINTVL 0x174
/* bit definitions */
#define VPBE_PCR_VENC_DIV (1 << 1)
#define VPBE_PCR_CLK_OFF (1 << 0)
#define VENC_VMOD_VDMD_SHIFT 12
#define VENC_VMOD_VDMD_YCBCR16 0
#define VENC_VMOD_VDMD_YCBCR8 1
#define VENC_VMOD_VDMD_RGB666 2
#define VENC_VMOD_VDMD_RGB8 3
#define VENC_VMOD_VDMD_EPSON 4
#define VENC_VMOD_VDMD_CASIO 5
#define VENC_VMOD_VDMD_UDISPQVGA 6
#define VENC_VMOD_VDMD_STNLCD 7
#define VENC_VMOD_VIE_SHIFT 1
#define VENC_VMOD_VDMD (7 << 12)
#define VENC_VMOD_ITLCL (1 << 11)
#define VENC_VMOD_ITLC (1 << 10)
#define VENC_VMOD_NSIT (1 << 9)
#define VENC_VMOD_HDMD (1 << 8)
#define VENC_VMOD_TVTYP_SHIFT 6
#define VENC_VMOD_TVTYP (3 << 6)
#define VENC_VMOD_SLAVE (1 << 5)
#define VENC_VMOD_VMD (1 << 4)
#define VENC_VMOD_BLNK (1 << 3)
#define VENC_VMOD_VIE (1 << 1)
#define VENC_VMOD_VENC (1 << 0)
/* VMOD TVTYP options for HDMD=0 */
#define SDTV_NTSC 0
#define SDTV_PAL 1
/* VMOD TVTYP options for HDMD=1 */
#define HDTV_525P 0
#define HDTV_625P 1
#define HDTV_1080I 2
#define HDTV_720P 3
#define VENC_VIDCTL_VCLKP (1 << 14)
#define VENC_VIDCTL_VCLKE_SHIFT 13
#define VENC_VIDCTL_VCLKE (1 << 13)
#define VENC_VIDCTL_VCLKZ_SHIFT 12
#define VENC_VIDCTL_VCLKZ (1 << 12)
#define VENC_VIDCTL_SYDIR_SHIFT 8
#define VENC_VIDCTL_SYDIR (1 << 8)
#define VENC_VIDCTL_DOMD_SHIFT 4
#define VENC_VIDCTL_DOMD (3 << 4)
#define VENC_VIDCTL_YCDIR_SHIFT 0
#define VENC_VIDCTL_YCDIR (1 << 0)
#define VENC_VDPRO_ATYCC_SHIFT 5
#define VENC_VDPRO_ATYCC (1 << 5)
#define VENC_VDPRO_ATCOM_SHIFT 4
#define VENC_VDPRO_ATCOM (1 << 4)
#define VENC_VDPRO_DAFRQ (1 << 3)
#define VENC_VDPRO_DAUPS (1 << 2)
#define VENC_VDPRO_CUPS (1 << 1)
#define VENC_VDPRO_YUPS (1 << 0)
#define VENC_SYNCCTL_VPL_SHIFT 3
#define VENC_SYNCCTL_VPL (1 << 3)
#define VENC_SYNCCTL_HPL_SHIFT 2
#define VENC_SYNCCTL_HPL (1 << 2)
#define VENC_SYNCCTL_SYEV_SHIFT 1
#define VENC_SYNCCTL_SYEV (1 << 1)
#define VENC_SYNCCTL_SYEH_SHIFT 0
#define VENC_SYNCCTL_SYEH (1 << 0)
#define VENC_SYNCCTL_OVD_SHIFT 14
#define VENC_SYNCCTL_OVD (1 << 14)
#define VENC_DCLKCTL_DCKEC_SHIFT 11
#define VENC_DCLKCTL_DCKEC (1 << 11)
#define VENC_DCLKCTL_DCKPW_SHIFT 0
#define VENC_DCLKCTL_DCKPW (0x3f << 0)
#define VENC_VSTAT_FIDST (1 << 4)
#define VENC_CMPNT_MRGB_SHIFT 14
#define VENC_CMPNT_MRGB (1 << 14)
#endif /* _VPBE_VENC_REGS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,508 @@
/*
* vpif - Video Port Interface driver
* VPIF is a receiver and transmitter for video data. It has two channels(0, 1)
* that receiveing video byte stream and two channels(2, 3) for video output.
* The hardware supports SDTV, HDTV formats, raw data capture.
* Currently, the driver supports NTSC and PAL standards.
*
* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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.
*
* This program is distributed .as is. WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/v4l2-dv-timings.h>
#include <mach/hardware.h>
#include "vpif.h"
MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver");
MODULE_LICENSE("GPL");
#define VPIF_CH0_MAX_MODES (22)
#define VPIF_CH1_MAX_MODES (02)
#define VPIF_CH2_MAX_MODES (15)
#define VPIF_CH3_MAX_MODES (02)
static resource_size_t res_len;
static struct resource *res;
spinlock_t vpif_lock;
void __iomem *vpif_base;
EXPORT_SYMBOL_GPL(vpif_base);
/**
* vpif_ch_params: video standard configuration parameters for vpif
* The table must include all presets from supported subdevices.
*/
const struct vpif_channel_config_params vpif_ch_params[] = {
/* HDTV formats */
{
.name = "480p59_94",
.width = 720,
.height = 480,
.frm_fmt = 1,
.ycmux_mode = 0,
.eav2sav = 138-8,
.sav2eav = 720,
.l1 = 1,
.l3 = 43,
.l5 = 523,
.vsize = 525,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_720X480P59_94,
},
{
.name = "576p50",
.width = 720,
.height = 576,
.frm_fmt = 1,
.ycmux_mode = 0,
.eav2sav = 144-8,
.sav2eav = 720,
.l1 = 1,
.l3 = 45,
.l5 = 621,
.vsize = 625,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_720X576P50,
},
{
.name = "720p50",
.width = 1280,
.height = 720,
.frm_fmt = 1,
.ycmux_mode = 0,
.eav2sav = 700-8,
.sav2eav = 1280,
.l1 = 1,
.l3 = 26,
.l5 = 746,
.vsize = 750,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_1280X720P50,
},
{
.name = "720p60",
.width = 1280,
.height = 720,
.frm_fmt = 1,
.ycmux_mode = 0,
.eav2sav = 370 - 8,
.sav2eav = 1280,
.l1 = 1,
.l3 = 26,
.l5 = 746,
.vsize = 750,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_1280X720P60,
},
{
.name = "1080I50",
.width = 1920,
.height = 1080,
.frm_fmt = 0,
.ycmux_mode = 0,
.eav2sav = 720 - 8,
.sav2eav = 1920,
.l1 = 1,
.l3 = 21,
.l5 = 561,
.l7 = 563,
.l9 = 584,
.l11 = 1124,
.vsize = 1125,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_1920X1080I50,
},
{
.name = "1080I60",
.width = 1920,
.height = 1080,
.frm_fmt = 0,
.ycmux_mode = 0,
.eav2sav = 280 - 8,
.sav2eav = 1920,
.l1 = 1,
.l3 = 21,
.l5 = 561,
.l7 = 563,
.l9 = 584,
.l11 = 1124,
.vsize = 1125,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_1920X1080I60,
},
{
.name = "1080p60",
.width = 1920,
.height = 1080,
.frm_fmt = 1,
.ycmux_mode = 0,
.eav2sav = 280 - 8,
.sav2eav = 1920,
.l1 = 1,
.l3 = 42,
.l5 = 1122,
.vsize = 1125,
.capture_format = 0,
.vbi_supported = 0,
.hd_sd = 1,
.dv_timings = V4L2_DV_BT_CEA_1920X1080P60,
},
/* SDTV formats */
{
.name = "NTSC_M",
.width = 720,
.height = 480,
.frm_fmt = 0,
.ycmux_mode = 1,
.eav2sav = 268,
.sav2eav = 1440,
.l1 = 1,
.l3 = 23,
.l5 = 263,
.l7 = 266,
.l9 = 286,
.l11 = 525,
.vsize = 525,
.capture_format = 0,
.vbi_supported = 1,
.hd_sd = 0,
.stdid = V4L2_STD_525_60,
},
{
.name = "PAL_BDGHIK",
.width = 720,
.height = 576,
.frm_fmt = 0,
.ycmux_mode = 1,
.eav2sav = 280,
.sav2eav = 1440,
.l1 = 1,
.l3 = 23,
.l5 = 311,
.l7 = 313,
.l9 = 336,
.l11 = 624,
.vsize = 625,
.capture_format = 0,
.vbi_supported = 1,
.hd_sd = 0,
.stdid = V4L2_STD_625_50,
},
};
EXPORT_SYMBOL_GPL(vpif_ch_params);
const unsigned int vpif_ch_params_count = ARRAY_SIZE(vpif_ch_params);
EXPORT_SYMBOL_GPL(vpif_ch_params_count);
static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
{
if (val)
vpif_set_bit(reg, bit);
else
vpif_clr_bit(reg, bit);
}
/* This structure is used to keep track of VPIF size register's offsets */
struct vpif_registers {
u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl;
u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt;
u32 vanc1_size, width_mask, len_mask;
u8 max_modes;
};
static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = {
/* Channel0 */
{
VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01,
VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL,
VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
VPIF_CH0_MAX_MODES,
},
/* Channel1 */
{
VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01,
VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL,
VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
VPIF_CH1_MAX_MODES,
},
/* Channel2 */
{
VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01,
VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL,
VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE,
VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF,
VPIF_CH2_MAX_MODES
},
/* Channel3 */
{
VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01,
VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL,
VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE,
VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF,
VPIF_CH3_MAX_MODES
},
};
/* vpif_set_mode_info:
* This function is used to set horizontal and vertical config parameters
* As per the standard in the channel, configure the values of L1, L3,
* L5, L7 L9, L11 in VPIF Register , also write width and height
*/
static void vpif_set_mode_info(const struct vpif_channel_config_params *config,
u8 channel_id, u8 config_channel_id)
{
u32 value;
value = (config->eav2sav & vpifregs[config_channel_id].width_mask);
value <<= VPIF_CH_LEN_SHIFT;
value |= (config->sav2eav & vpifregs[config_channel_id].width_mask);
regw(value, vpifregs[channel_id].h_cfg);
value = (config->l1 & vpifregs[config_channel_id].len_mask);
value <<= VPIF_CH_LEN_SHIFT;
value |= (config->l3 & vpifregs[config_channel_id].len_mask);
regw(value, vpifregs[channel_id].v_cfg_00);
value = (config->l5 & vpifregs[config_channel_id].len_mask);
value <<= VPIF_CH_LEN_SHIFT;
value |= (config->l7 & vpifregs[config_channel_id].len_mask);
regw(value, vpifregs[channel_id].v_cfg_01);
value = (config->l9 & vpifregs[config_channel_id].len_mask);
value <<= VPIF_CH_LEN_SHIFT;
value |= (config->l11 & vpifregs[config_channel_id].len_mask);
regw(value, vpifregs[channel_id].v_cfg_02);
value = (config->vsize & vpifregs[config_channel_id].len_mask);
regw(value, vpifregs[channel_id].v_cfg);
}
/* config_vpif_params
* Function to set the parameters of a channel
* Mainly modifies the channel ciontrol register
* It sets frame format, yc mux mode
*/
static void config_vpif_params(struct vpif_params *vpifparams,
u8 channel_id, u8 found)
{
const struct vpif_channel_config_params *config = &vpifparams->std_info;
u32 value, ch_nip, reg;
u8 start, end;
int i;
start = channel_id;
end = channel_id + found;
for (i = start; i < end; i++) {
reg = vpifregs[i].ch_ctrl;
if (channel_id < 2)
ch_nip = VPIF_CAPTURE_CH_NIP;
else
ch_nip = VPIF_DISPLAY_CH_NIP;
vpif_wr_bit(reg, ch_nip, config->frm_fmt);
vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode);
vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT,
vpifparams->video_params.storage_mode);
/* Set raster scanning SDR Format */
vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT);
vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format);
if (channel_id > 1) /* Set the Pixel enable bit */
vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT);
else if (config->capture_format) {
/* Set the polarity of various pins */
vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT,
vpifparams->iface.fid_pol);
vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT,
vpifparams->iface.vd_pol);
vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT,
vpifparams->iface.hd_pol);
value = regr(reg);
/* Set data width */
value &= ~(0x3u <<
VPIF_CH_DATA_WIDTH_BIT);
value |= ((vpifparams->params.data_sz) <<
VPIF_CH_DATA_WIDTH_BIT);
regw(value, reg);
}
/* Write the pitch in the driver */
regw((vpifparams->video_params.hpitch),
vpifregs[i].line_offset);
}
}
/* vpif_set_video_params
* This function is used to set video parameters in VPIF register
*/
int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id)
{
const struct vpif_channel_config_params *config = &vpifparams->std_info;
int found = 1;
vpif_set_mode_info(config, channel_id, channel_id);
if (!config->ycmux_mode) {
/* YC are on separate channels (HDTV formats) */
vpif_set_mode_info(config, channel_id + 1, channel_id);
found = 2;
}
config_vpif_params(vpifparams, channel_id, found);
regw(0x80, VPIF_REQ_SIZE);
regw(0x01, VPIF_EMULATION_CTRL);
return found;
}
EXPORT_SYMBOL(vpif_set_video_params);
void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,
u8 channel_id)
{
u32 value;
value = 0x3F8 & (vbiparams->hstart0);
value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16);
regw(value, vpifregs[channel_id].vanc0_strt);
value = 0x3F8 & (vbiparams->hstart1);
value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16);
regw(value, vpifregs[channel_id].vanc1_strt);
value = 0x3F8 & (vbiparams->hsize0);
value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16);
regw(value, vpifregs[channel_id].vanc0_size);
value = 0x3F8 & (vbiparams->hsize1);
value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16);
regw(value, vpifregs[channel_id].vanc1_size);
}
EXPORT_SYMBOL(vpif_set_vbi_display_params);
int vpif_channel_getfid(u8 channel_id)
{
return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK)
>> VPIF_CH_FID_SHIFT;
}
EXPORT_SYMBOL(vpif_channel_getfid);
static int vpif_probe(struct platform_device *pdev)
{
int status = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
res_len = resource_size(res);
res = request_mem_region(res->start, res_len, res->name);
if (!res)
return -EBUSY;
vpif_base = ioremap(res->start, res_len);
if (!vpif_base) {
status = -EBUSY;
goto fail;
}
pm_runtime_enable(&pdev->dev);
pm_runtime_get(&pdev->dev);
spin_lock_init(&vpif_lock);
dev_info(&pdev->dev, "vpif probe success\n");
return 0;
fail:
release_mem_region(res->start, res_len);
return status;
}
static int vpif_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
iounmap(vpif_base);
release_mem_region(res->start, res_len);
return 0;
}
#ifdef CONFIG_PM
static int vpif_suspend(struct device *dev)
{
pm_runtime_put(dev);
return 0;
}
static int vpif_resume(struct device *dev)
{
pm_runtime_get(dev);
return 0;
}
static const struct dev_pm_ops vpif_pm = {
.suspend = vpif_suspend,
.resume = vpif_resume,
};
#define vpif_pm_ops (&vpif_pm)
#else
#define vpif_pm_ops NULL
#endif
static struct platform_driver vpif_driver = {
.driver = {
.name = "vpif",
.owner = THIS_MODULE,
.pm = vpif_pm_ops,
},
.remove = vpif_remove,
.probe = vpif_probe,
};
static void vpif_exit(void)
{
platform_driver_unregister(&vpif_driver);
}
static int __init vpif_init(void)
{
return platform_driver_register(&vpif_driver);
}
subsys_initcall(vpif_init);
module_exit(vpif_exit);

View File

@@ -0,0 +1,688 @@
/*
* VPIF header file
*
* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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.
*
* This program is distributed .as is. WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef VPIF_H
#define VPIF_H
#include <linux/io.h>
#include <linux/videodev2.h>
#include <media/davinci/vpif_types.h>
/* Maximum channel allowed */
#define VPIF_NUM_CHANNELS (4)
#define VPIF_CAPTURE_NUM_CHANNELS (2)
#define VPIF_DISPLAY_NUM_CHANNELS (2)
/* Macros to read/write registers */
extern void __iomem *vpif_base;
extern spinlock_t vpif_lock;
#define regr(reg) readl((reg) + vpif_base)
#define regw(value, reg) writel(value, (reg + vpif_base))
/* Register Address Offsets */
#define VPIF_PID (0x0000)
#define VPIF_CH0_CTRL (0x0004)
#define VPIF_CH1_CTRL (0x0008)
#define VPIF_CH2_CTRL (0x000C)
#define VPIF_CH3_CTRL (0x0010)
#define VPIF_INTEN (0x0020)
#define VPIF_INTEN_SET (0x0024)
#define VPIF_INTEN_CLR (0x0028)
#define VPIF_STATUS (0x002C)
#define VPIF_STATUS_CLR (0x0030)
#define VPIF_EMULATION_CTRL (0x0034)
#define VPIF_REQ_SIZE (0x0038)
#define VPIF_CH0_TOP_STRT_ADD_LUMA (0x0040)
#define VPIF_CH0_BTM_STRT_ADD_LUMA (0x0044)
#define VPIF_CH0_TOP_STRT_ADD_CHROMA (0x0048)
#define VPIF_CH0_BTM_STRT_ADD_CHROMA (0x004c)
#define VPIF_CH0_TOP_STRT_ADD_HANC (0x0050)
#define VPIF_CH0_BTM_STRT_ADD_HANC (0x0054)
#define VPIF_CH0_TOP_STRT_ADD_VANC (0x0058)
#define VPIF_CH0_BTM_STRT_ADD_VANC (0x005c)
#define VPIF_CH0_SP_CFG (0x0060)
#define VPIF_CH0_IMG_ADD_OFST (0x0064)
#define VPIF_CH0_HANC_ADD_OFST (0x0068)
#define VPIF_CH0_H_CFG (0x006c)
#define VPIF_CH0_V_CFG_00 (0x0070)
#define VPIF_CH0_V_CFG_01 (0x0074)
#define VPIF_CH0_V_CFG_02 (0x0078)
#define VPIF_CH0_V_CFG_03 (0x007c)
#define VPIF_CH1_TOP_STRT_ADD_LUMA (0x0080)
#define VPIF_CH1_BTM_STRT_ADD_LUMA (0x0084)
#define VPIF_CH1_TOP_STRT_ADD_CHROMA (0x0088)
#define VPIF_CH1_BTM_STRT_ADD_CHROMA (0x008c)
#define VPIF_CH1_TOP_STRT_ADD_HANC (0x0090)
#define VPIF_CH1_BTM_STRT_ADD_HANC (0x0094)
#define VPIF_CH1_TOP_STRT_ADD_VANC (0x0098)
#define VPIF_CH1_BTM_STRT_ADD_VANC (0x009c)
#define VPIF_CH1_SP_CFG (0x00a0)
#define VPIF_CH1_IMG_ADD_OFST (0x00a4)
#define VPIF_CH1_HANC_ADD_OFST (0x00a8)
#define VPIF_CH1_H_CFG (0x00ac)
#define VPIF_CH1_V_CFG_00 (0x00b0)
#define VPIF_CH1_V_CFG_01 (0x00b4)
#define VPIF_CH1_V_CFG_02 (0x00b8)
#define VPIF_CH1_V_CFG_03 (0x00bc)
#define VPIF_CH2_TOP_STRT_ADD_LUMA (0x00c0)
#define VPIF_CH2_BTM_STRT_ADD_LUMA (0x00c4)
#define VPIF_CH2_TOP_STRT_ADD_CHROMA (0x00c8)
#define VPIF_CH2_BTM_STRT_ADD_CHROMA (0x00cc)
#define VPIF_CH2_TOP_STRT_ADD_HANC (0x00d0)
#define VPIF_CH2_BTM_STRT_ADD_HANC (0x00d4)
#define VPIF_CH2_TOP_STRT_ADD_VANC (0x00d8)
#define VPIF_CH2_BTM_STRT_ADD_VANC (0x00dc)
#define VPIF_CH2_SP_CFG (0x00e0)
#define VPIF_CH2_IMG_ADD_OFST (0x00e4)
#define VPIF_CH2_HANC_ADD_OFST (0x00e8)
#define VPIF_CH2_H_CFG (0x00ec)
#define VPIF_CH2_V_CFG_00 (0x00f0)
#define VPIF_CH2_V_CFG_01 (0x00f4)
#define VPIF_CH2_V_CFG_02 (0x00f8)
#define VPIF_CH2_V_CFG_03 (0x00fc)
#define VPIF_CH2_HANC0_STRT (0x0100)
#define VPIF_CH2_HANC0_SIZE (0x0104)
#define VPIF_CH2_HANC1_STRT (0x0108)
#define VPIF_CH2_HANC1_SIZE (0x010c)
#define VPIF_CH2_VANC0_STRT (0x0110)
#define VPIF_CH2_VANC0_SIZE (0x0114)
#define VPIF_CH2_VANC1_STRT (0x0118)
#define VPIF_CH2_VANC1_SIZE (0x011c)
#define VPIF_CH3_TOP_STRT_ADD_LUMA (0x0140)
#define VPIF_CH3_BTM_STRT_ADD_LUMA (0x0144)
#define VPIF_CH3_TOP_STRT_ADD_CHROMA (0x0148)
#define VPIF_CH3_BTM_STRT_ADD_CHROMA (0x014c)
#define VPIF_CH3_TOP_STRT_ADD_HANC (0x0150)
#define VPIF_CH3_BTM_STRT_ADD_HANC (0x0154)
#define VPIF_CH3_TOP_STRT_ADD_VANC (0x0158)
#define VPIF_CH3_BTM_STRT_ADD_VANC (0x015c)
#define VPIF_CH3_SP_CFG (0x0160)
#define VPIF_CH3_IMG_ADD_OFST (0x0164)
#define VPIF_CH3_HANC_ADD_OFST (0x0168)
#define VPIF_CH3_H_CFG (0x016c)
#define VPIF_CH3_V_CFG_00 (0x0170)
#define VPIF_CH3_V_CFG_01 (0x0174)
#define VPIF_CH3_V_CFG_02 (0x0178)
#define VPIF_CH3_V_CFG_03 (0x017c)
#define VPIF_CH3_HANC0_STRT (0x0180)
#define VPIF_CH3_HANC0_SIZE (0x0184)
#define VPIF_CH3_HANC1_STRT (0x0188)
#define VPIF_CH3_HANC1_SIZE (0x018c)
#define VPIF_CH3_VANC0_STRT (0x0190)
#define VPIF_CH3_VANC0_SIZE (0x0194)
#define VPIF_CH3_VANC1_STRT (0x0198)
#define VPIF_CH3_VANC1_SIZE (0x019c)
#define VPIF_IODFT_CTRL (0x01c0)
/* Functions for bit Manipulation */
static inline void vpif_set_bit(u32 reg, u32 bit)
{
regw((regr(reg)) | (0x01 << bit), reg);
}
static inline void vpif_clr_bit(u32 reg, u32 bit)
{
regw(((regr(reg)) & ~(0x01 << bit)), reg);
}
/* Macro for Generating mask */
#ifdef GENERATE_MASK
#undef GENERATE_MASK
#endif
#define GENERATE_MASK(bits, pos) \
((((0xFFFFFFFF) << (32 - bits)) >> (32 - bits)) << pos)
/* Bit positions in the channel control registers */
#define VPIF_CH_DATA_MODE_BIT (2)
#define VPIF_CH_YC_MUX_BIT (3)
#define VPIF_CH_SDR_FMT_BIT (4)
#define VPIF_CH_HANC_EN_BIT (8)
#define VPIF_CH_VANC_EN_BIT (9)
#define VPIF_CAPTURE_CH_NIP (10)
#define VPIF_DISPLAY_CH_NIP (11)
#define VPIF_DISPLAY_PIX_EN_BIT (10)
#define VPIF_CH_INPUT_FIELD_FRAME_BIT (12)
#define VPIF_CH_FID_POLARITY_BIT (15)
#define VPIF_CH_V_VALID_POLARITY_BIT (14)
#define VPIF_CH_H_VALID_POLARITY_BIT (13)
#define VPIF_CH_DATA_WIDTH_BIT (28)
#define VPIF_CH_CLK_EDGE_CTRL_BIT (31)
/* Mask various length */
#define VPIF_CH_EAVSAV_MASK GENERATE_MASK(13, 0)
#define VPIF_CH_LEN_MASK GENERATE_MASK(12, 0)
#define VPIF_CH_WIDTH_MASK GENERATE_MASK(13, 0)
#define VPIF_CH_LEN_SHIFT (16)
/* VPIF masks for registers */
#define VPIF_REQ_SIZE_MASK (0x1ff)
/* bit posotion of interrupt vpif_ch_intr register */
#define VPIF_INTEN_FRAME_CH0 (0x00000001)
#define VPIF_INTEN_FRAME_CH1 (0x00000002)
#define VPIF_INTEN_FRAME_CH2 (0x00000004)
#define VPIF_INTEN_FRAME_CH3 (0x00000008)
/* bit position of clock and channel enable in vpif_chn_ctrl register */
#define VPIF_CH0_CLK_EN (0x00000002)
#define VPIF_CH0_EN (0x00000001)
#define VPIF_CH1_CLK_EN (0x00000002)
#define VPIF_CH1_EN (0x00000001)
#define VPIF_CH2_CLK_EN (0x00000002)
#define VPIF_CH2_EN (0x00000001)
#define VPIF_CH3_CLK_EN (0x00000002)
#define VPIF_CH3_EN (0x00000001)
#define VPIF_CH_CLK_EN (0x00000002)
#define VPIF_CH_EN (0x00000001)
#define VPIF_INT_TOP (0x00)
#define VPIF_INT_BOTTOM (0x01)
#define VPIF_INT_BOTH (0x02)
#define VPIF_CH0_INT_CTRL_SHIFT (6)
#define VPIF_CH1_INT_CTRL_SHIFT (6)
#define VPIF_CH2_INT_CTRL_SHIFT (6)
#define VPIF_CH3_INT_CTRL_SHIFT (6)
#define VPIF_CH_INT_CTRL_SHIFT (6)
#define VPIF_CH2_CLIP_ANC_EN 14
#define VPIF_CH2_CLIP_ACTIVE_EN 13
#define VPIF_CH3_CLIP_ANC_EN 14
#define VPIF_CH3_CLIP_ACTIVE_EN 13
/* enabled interrupt on both the fields on vpid_ch0_ctrl register */
#define channel0_intr_assert() (regw((regr(VPIF_CH0_CTRL)|\
(VPIF_INT_BOTH << VPIF_CH0_INT_CTRL_SHIFT)), VPIF_CH0_CTRL))
/* enabled interrupt on both the fields on vpid_ch1_ctrl register */
#define channel1_intr_assert() (regw((regr(VPIF_CH1_CTRL)|\
(VPIF_INT_BOTH << VPIF_CH1_INT_CTRL_SHIFT)), VPIF_CH1_CTRL))
/* enabled interrupt on both the fields on vpid_ch0_ctrl register */
#define channel2_intr_assert() (regw((regr(VPIF_CH2_CTRL)|\
(VPIF_INT_BOTH << VPIF_CH2_INT_CTRL_SHIFT)), VPIF_CH2_CTRL))
/* enabled interrupt on both the fields on vpid_ch1_ctrl register */
#define channel3_intr_assert() (regw((regr(VPIF_CH3_CTRL)|\
(VPIF_INT_BOTH << VPIF_CH3_INT_CTRL_SHIFT)), VPIF_CH3_CTRL))
#define VPIF_CH_FID_MASK (0x20)
#define VPIF_CH_FID_SHIFT (5)
#define VPIF_NTSC_VBI_START_FIELD0 (1)
#define VPIF_NTSC_VBI_START_FIELD1 (263)
#define VPIF_PAL_VBI_START_FIELD0 (624)
#define VPIF_PAL_VBI_START_FIELD1 (311)
#define VPIF_NTSC_HBI_START_FIELD0 (1)
#define VPIF_NTSC_HBI_START_FIELD1 (263)
#define VPIF_PAL_HBI_START_FIELD0 (624)
#define VPIF_PAL_HBI_START_FIELD1 (311)
#define VPIF_NTSC_VBI_COUNT_FIELD0 (20)
#define VPIF_NTSC_VBI_COUNT_FIELD1 (19)
#define VPIF_PAL_VBI_COUNT_FIELD0 (24)
#define VPIF_PAL_VBI_COUNT_FIELD1 (25)
#define VPIF_NTSC_HBI_COUNT_FIELD0 (263)
#define VPIF_NTSC_HBI_COUNT_FIELD1 (262)
#define VPIF_PAL_HBI_COUNT_FIELD0 (312)
#define VPIF_PAL_HBI_COUNT_FIELD1 (313)
#define VPIF_NTSC_VBI_SAMPLES_PER_LINE (720)
#define VPIF_PAL_VBI_SAMPLES_PER_LINE (720)
#define VPIF_NTSC_HBI_SAMPLES_PER_LINE (268)
#define VPIF_PAL_HBI_SAMPLES_PER_LINE (280)
#define VPIF_CH_VANC_EN (0x20)
#define VPIF_DMA_REQ_SIZE (0x080)
#define VPIF_EMULATION_DISABLE (0x01)
extern u8 irq_vpif_capture_channel[VPIF_NUM_CHANNELS];
/* inline function to enable/disable channel0 */
static inline void enable_channel0(int enable)
{
if (enable)
regw((regr(VPIF_CH0_CTRL) | (VPIF_CH0_EN)), VPIF_CH0_CTRL);
else
regw((regr(VPIF_CH0_CTRL) & (~VPIF_CH0_EN)), VPIF_CH0_CTRL);
}
/* inline function to enable/disable channel1 */
static inline void enable_channel1(int enable)
{
if (enable)
regw((regr(VPIF_CH1_CTRL) | (VPIF_CH1_EN)), VPIF_CH1_CTRL);
else
regw((regr(VPIF_CH1_CTRL) & (~VPIF_CH1_EN)), VPIF_CH1_CTRL);
}
/* inline function to enable interrupt for channel0 */
static inline void channel0_intr_enable(int enable)
{
unsigned long flags;
spin_lock_irqsave(&vpif_lock, flags);
if (enable) {
regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH0), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0),
VPIF_INTEN_SET);
} else {
regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH0)), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0),
VPIF_INTEN_SET);
}
spin_unlock_irqrestore(&vpif_lock, flags);
}
/* inline function to enable interrupt for channel1 */
static inline void channel1_intr_enable(int enable)
{
unsigned long flags;
spin_lock_irqsave(&vpif_lock, flags);
if (enable) {
regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH1), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1),
VPIF_INTEN_SET);
} else {
regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH1)), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1),
VPIF_INTEN_SET);
}
spin_unlock_irqrestore(&vpif_lock, flags);
}
/* inline function to set buffer addresses in case of Y/C non mux mode */
static inline void ch0_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA);
regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA);
regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA);
regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA);
}
/* inline function to set buffer addresses in VPIF registers for video data */
static inline void ch0_set_videobuf_addr(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA);
regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA);
regw(top_strt_chroma, VPIF_CH0_TOP_STRT_ADD_CHROMA);
regw(btm_strt_chroma, VPIF_CH0_BTM_STRT_ADD_CHROMA);
}
static inline void ch1_set_videobuf_addr(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH1_TOP_STRT_ADD_LUMA);
regw(btm_strt_luma, VPIF_CH1_BTM_STRT_ADD_LUMA);
regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA);
regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA);
}
static inline void ch0_set_vbi_addr(unsigned long top_vbi,
unsigned long btm_vbi, unsigned long a, unsigned long b)
{
regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_VANC);
regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_VANC);
}
static inline void ch0_set_hbi_addr(unsigned long top_vbi,
unsigned long btm_vbi, unsigned long a, unsigned long b)
{
regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_HANC);
regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_HANC);
}
static inline void ch1_set_vbi_addr(unsigned long top_vbi,
unsigned long btm_vbi, unsigned long a, unsigned long b)
{
regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_VANC);
regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_VANC);
}
static inline void ch1_set_hbi_addr(unsigned long top_vbi,
unsigned long btm_vbi, unsigned long a, unsigned long b)
{
regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_HANC);
regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_HANC);
}
/* Inline function to enable raw vbi in the given channel */
static inline void disable_raw_feature(u8 channel_id, u8 index)
{
u32 ctrl_reg;
if (0 == channel_id)
ctrl_reg = VPIF_CH0_CTRL;
else
ctrl_reg = VPIF_CH1_CTRL;
if (1 == index)
vpif_clr_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT);
else
vpif_clr_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT);
}
static inline void enable_raw_feature(u8 channel_id, u8 index)
{
u32 ctrl_reg;
if (0 == channel_id)
ctrl_reg = VPIF_CH0_CTRL;
else
ctrl_reg = VPIF_CH1_CTRL;
if (1 == index)
vpif_set_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT);
else
vpif_set_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT);
}
/* inline function to enable/disable channel2 */
static inline void enable_channel2(int enable)
{
if (enable) {
regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL);
regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_EN)), VPIF_CH2_CTRL);
} else {
regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL);
regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_EN)), VPIF_CH2_CTRL);
}
}
/* inline function to enable/disable channel3 */
static inline void enable_channel3(int enable)
{
if (enable) {
regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL);
regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_EN)), VPIF_CH3_CTRL);
} else {
regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL);
regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_EN)), VPIF_CH3_CTRL);
}
}
/* inline function to enable interrupt for channel2 */
static inline void channel2_intr_enable(int enable)
{
unsigned long flags;
spin_lock_irqsave(&vpif_lock, flags);
if (enable) {
regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH2), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2),
VPIF_INTEN_SET);
} else {
regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH2)), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2),
VPIF_INTEN_SET);
}
spin_unlock_irqrestore(&vpif_lock, flags);
}
/* inline function to enable interrupt for channel3 */
static inline void channel3_intr_enable(int enable)
{
unsigned long flags;
spin_lock_irqsave(&vpif_lock, flags);
if (enable) {
regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH3), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3),
VPIF_INTEN_SET);
} else {
regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH3)), VPIF_INTEN);
regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3),
VPIF_INTEN_SET);
}
spin_unlock_irqrestore(&vpif_lock, flags);
}
/* inline function to enable raw vbi data for channel2 */
static inline void channel2_raw_enable(int enable, u8 index)
{
u32 mask;
if (1 == index)
mask = VPIF_CH_VANC_EN_BIT;
else
mask = VPIF_CH_HANC_EN_BIT;
if (enable)
vpif_set_bit(VPIF_CH2_CTRL, mask);
else
vpif_clr_bit(VPIF_CH2_CTRL, mask);
}
/* inline function to enable raw vbi data for channel3*/
static inline void channel3_raw_enable(int enable, u8 index)
{
u32 mask;
if (1 == index)
mask = VPIF_CH_VANC_EN_BIT;
else
mask = VPIF_CH_HANC_EN_BIT;
if (enable)
vpif_set_bit(VPIF_CH3_CTRL, mask);
else
vpif_clr_bit(VPIF_CH3_CTRL, mask);
}
/* function to enable clipping (for both active and blanking regions) on ch 2 */
static inline void channel2_clipping_enable(int enable)
{
if (enable) {
vpif_set_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ANC_EN);
vpif_set_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ACTIVE_EN);
} else {
vpif_clr_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ANC_EN);
vpif_clr_bit(VPIF_CH2_CTRL, VPIF_CH2_CLIP_ACTIVE_EN);
}
}
/* function to enable clipping (for both active and blanking regions) on ch 3 */
static inline void channel3_clipping_enable(int enable)
{
if (enable) {
vpif_set_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ANC_EN);
vpif_set_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ACTIVE_EN);
} else {
vpif_clr_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ANC_EN);
vpif_clr_bit(VPIF_CH3_CTRL, VPIF_CH3_CLIP_ACTIVE_EN);
}
}
/* inline function to set buffer addresses in case of Y/C non mux mode */
static inline void ch2_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA);
regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA);
regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA);
regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA);
}
/* inline function to set buffer addresses in VPIF registers for video data */
static inline void ch2_set_videobuf_addr(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA);
regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA);
regw(top_strt_chroma, VPIF_CH2_TOP_STRT_ADD_CHROMA);
regw(btm_strt_chroma, VPIF_CH2_BTM_STRT_ADD_CHROMA);
}
static inline void ch3_set_videobuf_addr(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_LUMA);
regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_LUMA);
regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA);
regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA);
}
/* inline function to set buffer addresses in VPIF registers for vbi data */
static inline void ch2_set_vbi_addr(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_VANC);
regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_VANC);
}
static inline void ch3_set_vbi_addr(unsigned long top_strt_luma,
unsigned long btm_strt_luma,
unsigned long top_strt_chroma,
unsigned long btm_strt_chroma)
{
regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_VANC);
regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_VANC);
}
static inline int vpif_intr_status(int channel)
{
int status = 0;
int mask;
if (channel < 0 || channel > 3)
return 0;
mask = 1 << channel;
status = regr(VPIF_STATUS) & mask;
regw(status, VPIF_STATUS_CLR);
return status;
}
#define VPIF_MAX_NAME (30)
/* This structure will store size parameters as per the mode selected by user */
struct vpif_channel_config_params {
char name[VPIF_MAX_NAME]; /* Name of the mode */
u16 width; /* Indicates width of the image */
u16 height; /* Indicates height of the image */
u8 frm_fmt; /* Interlaced (0) or progressive (1) */
u8 ycmux_mode; /* This mode requires one (0) or two (1)
channels */
u16 eav2sav; /* length of eav 2 sav */
u16 sav2eav; /* length of sav 2 eav */
u16 l1, l3, l5, l7, l9, l11; /* Other parameter configurations */
u16 vsize; /* Vertical size of the image */
u8 capture_format; /* Indicates whether capture format
* is in BT or in CCD/CMOS */
u8 vbi_supported; /* Indicates whether this mode
* supports capturing vbi or not */
u8 hd_sd; /* HDTV (1) or SDTV (0) format */
v4l2_std_id stdid; /* SDTV format */
struct v4l2_dv_timings dv_timings; /* HDTV format */
};
extern const unsigned int vpif_ch_params_count;
extern const struct vpif_channel_config_params vpif_ch_params[];
struct vpif_video_params;
struct vpif_params;
struct vpif_vbi_params;
int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id);
void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,
u8 channel_id);
int vpif_channel_getfid(u8 channel_id);
enum data_size {
_8BITS = 0,
_10BITS,
_12BITS,
};
/* Structure for vpif parameters for raw vbi data */
struct vpif_vbi_params {
__u32 hstart0; /* Horizontal start of raw vbi data for first field */
__u32 vstart0; /* Vertical start of raw vbi data for first field */
__u32 hsize0; /* Horizontal size of raw vbi data for first field */
__u32 vsize0; /* Vertical size of raw vbi data for first field */
__u32 hstart1; /* Horizontal start of raw vbi data for second field */
__u32 vstart1; /* Vertical start of raw vbi data for second field */
__u32 hsize1; /* Horizontal size of raw vbi data for second field */
__u32 vsize1; /* Vertical size of raw vbi data for second field */
};
/* structure for vpif parameters */
struct vpif_video_params {
__u8 storage_mode; /* Indicates field or frame mode */
unsigned long hpitch;
v4l2_std_id stdid;
};
struct vpif_params {
struct vpif_interface iface;
struct vpif_video_params video_params;
struct vpif_channel_config_params std_info;
union param {
struct vpif_vbi_params vbi_params;
enum data_size data_sz;
} params;
};
#endif /* End of #ifndef VPIF_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2009 Texas Instruments Inc
*
* 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
*/
#ifndef VPIF_CAPTURE_H
#define VPIF_CAPTURE_H
#ifdef __KERNEL__
/* Header files */
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/videobuf2-dma-contig.h>
#include <media/davinci/vpif_types.h>
#include "vpif.h"
/* Macros */
#define VPIF_CAPTURE_VERSION "0.0.2"
#define VPIF_VALID_FIELD(field) (((V4L2_FIELD_ANY == field) || \
(V4L2_FIELD_NONE == field)) || \
(((V4L2_FIELD_INTERLACED == field) || \
(V4L2_FIELD_SEQ_TB == field)) || \
(V4L2_FIELD_SEQ_BT == field)))
#define VPIF_CAPTURE_MAX_DEVICES 2
#define VPIF_VIDEO_INDEX 0
#define VPIF_NUMBER_OF_OBJECTS 1
/* Enumerated data type to give id to each device per channel */
enum vpif_channel_id {
VPIF_CHANNEL0_VIDEO = 0,
VPIF_CHANNEL1_VIDEO,
};
struct video_obj {
enum v4l2_field buf_field;
/* Currently selected or default standard */
v4l2_std_id stdid;
struct v4l2_dv_timings dv_timings;
};
struct vpif_cap_buffer {
struct vb2_buffer vb;
struct list_head list;
};
struct common_obj {
/* Pointer pointing to current v4l2_buffer */
struct vpif_cap_buffer *cur_frm;
/* Pointer pointing to current v4l2_buffer */
struct vpif_cap_buffer *next_frm;
/*
* This field keeps track of type of buffer exchange mechanism
* user has selected
*/
enum v4l2_memory memory;
/* Used to store pixel format */
struct v4l2_format fmt;
/* Buffer queue used in video-buf */
struct vb2_queue buffer_queue;
/* allocator-specific contexts for each plane */
struct vb2_alloc_ctx *alloc_ctx;
/* Queue of filled frames */
struct list_head dma_queue;
/* Used in video-buf */
spinlock_t irqlock;
/* lock used to access this structure */
struct mutex lock;
/* number of users performing IO */
u32 io_usrs;
/* Indicates whether streaming started */
u8 started;
/* Function pointer to set the addresses */
void (*set_addr) (unsigned long, unsigned long, unsigned long,
unsigned long);
/* offset where Y top starts from the starting of the buffer */
u32 ytop_off;
/* offset where Y bottom starts from the starting of the buffer */
u32 ybtm_off;
/* offset where C top starts from the starting of the buffer */
u32 ctop_off;
/* offset where C bottom starts from the starting of the buffer */
u32 cbtm_off;
/* Indicates width of the image data */
u32 width;
/* Indicates height of the image data */
u32 height;
};
struct channel_obj {
/* Identifies video device for this channel */
struct video_device *video_dev;
/* Used to keep track of state of the priority */
struct v4l2_prio_state prio;
/* number of open instances of the channel */
int usrs;
/* Indicates id of the field which is being displayed */
u32 field_id;
/* flag to indicate whether decoder is initialized */
u8 initialized;
/* Identifies channel */
enum vpif_channel_id channel_id;
/* Current input */
u32 input_idx;
/* subdev corresponding to the current input, may be NULL */
struct v4l2_subdev *sd;
/* vpif configuration params */
struct vpif_params vpifparams;
/* common object array */
struct common_obj common[VPIF_NUMBER_OF_OBJECTS];
/* video object */
struct video_obj video;
};
/* File handle structure */
struct vpif_fh {
/* pointer to channel object for opened device */
struct channel_obj *channel;
/* Indicates whether this file handle is doing IO */
u8 io_allowed[VPIF_NUMBER_OF_OBJECTS];
/* Used to keep track priority of this instance */
enum v4l2_priority prio;
/* Used to indicate channel is initialize or not */
u8 initialized;
};
struct vpif_device {
struct v4l2_device v4l2_dev;
struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS];
struct v4l2_subdev **sd;
};
struct vpif_config_params {
u8 min_numbuffers;
u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS];
s8 device_type;
u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
u8 default_device[VPIF_CAPTURE_NUM_CHANNELS];
u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
u8 max_device_type;
};
#endif /* End of __KERNEL__ */
#endif /* VPIF_CAPTURE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,165 @@
/*
* VPIF display header file
*
* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.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.
*
* This program is distributed .as is. WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef DAVINCIHD_DISPLAY_H
#define DAVINCIHD_DISPLAY_H
/* Header files */
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/videobuf2-dma-contig.h>
#include <media/davinci/vpif_types.h>
#include "vpif.h"
/* Macros */
#define VPIF_DISPLAY_VERSION "0.0.2"
#define VPIF_VALID_FIELD(field) \
(((V4L2_FIELD_ANY == field) || (V4L2_FIELD_NONE == field)) || \
(((V4L2_FIELD_INTERLACED == field) || (V4L2_FIELD_SEQ_TB == field)) || \
(V4L2_FIELD_SEQ_BT == field)))
#define VPIF_DISPLAY_MAX_DEVICES (2)
#define VPIF_SLICED_BUF_SIZE (256)
#define VPIF_SLICED_MAX_SERVICES (3)
#define VPIF_VIDEO_INDEX (0)
#define VPIF_VBI_INDEX (1)
#define VPIF_HBI_INDEX (2)
/* Setting it to 1 as HBI/VBI support yet to be added , else 3*/
#define VPIF_NUMOBJECTS (1)
/* Macros */
#define ISALIGNED(a) (0 == ((a) & 7))
/* enumerated data types */
/* Enumerated data type to give id to each device per channel */
enum vpif_channel_id {
VPIF_CHANNEL2_VIDEO = 0, /* Channel2 Video */
VPIF_CHANNEL3_VIDEO, /* Channel3 Video */
};
/* structures */
struct video_obj {
enum v4l2_field buf_field;
u32 latest_only; /* indicate whether to return
* most recent displayed frame only */
v4l2_std_id stdid; /* Currently selected or default
* standard */
struct v4l2_dv_timings dv_timings;
};
struct vpif_disp_buffer {
struct vb2_buffer vb;
struct list_head list;
};
struct common_obj {
/* Buffer specific parameters */
u8 *fbuffers[VIDEO_MAX_FRAME]; /* List of buffer pointers for
* storing frames */
u32 numbuffers; /* number of buffers */
struct vpif_disp_buffer *cur_frm; /* Pointer pointing to current
* vb2_buffer */
struct vpif_disp_buffer *next_frm; /* Pointer pointing to next
* vb2_buffer */
enum v4l2_memory memory; /* This field keeps track of
* type of buffer exchange
* method user has selected */
struct v4l2_format fmt; /* Used to store the format */
struct vb2_queue buffer_queue; /* Buffer queue used in
* video-buf */
/* allocator-specific contexts for each plane */
struct vb2_alloc_ctx *alloc_ctx;
struct list_head dma_queue; /* Queue of filled frames */
spinlock_t irqlock; /* Used in video-buf */
/* channel specific parameters */
struct mutex lock; /* lock used to access this
* structure */
u32 io_usrs; /* number of users performing
* IO */
u8 started; /* Indicates whether streaming
* started */
u32 ytop_off; /* offset of Y top from the
* starting of the buffer */
u32 ybtm_off; /* offset of Y bottom from the
* starting of the buffer */
u32 ctop_off; /* offset of C top from the
* starting of the buffer */
u32 cbtm_off; /* offset of C bottom from the
* starting of the buffer */
/* Function pointer to set the addresses */
void (*set_addr) (unsigned long, unsigned long,
unsigned long, unsigned long);
u32 height;
u32 width;
};
struct channel_obj {
/* V4l2 specific parameters */
struct video_device *video_dev; /* Identifies video device for
* this channel */
struct v4l2_prio_state prio; /* Used to keep track of state of
* the priority */
atomic_t usrs; /* number of open instances of
* the channel */
u32 field_id; /* Indicates id of the field
* which is being displayed */
u8 initialized; /* flag to indicate whether
* encoder is initialized */
u32 output_idx; /* Current output index */
struct v4l2_subdev *sd; /* Current output subdev(may be NULL) */
enum vpif_channel_id channel_id;/* Identifies channel */
struct vpif_params vpifparams;
struct common_obj common[VPIF_NUMOBJECTS];
struct video_obj video;
};
/* File handle structure */
struct vpif_fh {
struct channel_obj *channel; /* pointer to channel object for
* opened device */
u8 io_allowed[VPIF_NUMOBJECTS]; /* Indicates whether this file handle
* is doing IO */
enum v4l2_priority prio; /* Used to keep track priority of
* this instance */
u8 initialized; /* Used to keep track of whether this
* file handle has initialized
* channel or not */
};
/* vpif device structure */
struct vpif_device {
struct v4l2_device v4l2_dev;
struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
struct v4l2_subdev **sd;
};
struct vpif_config_params {
u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS];
u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS];
u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS];
u32 video_limit[VPIF_DISPLAY_NUM_CHANNELS];
u8 min_numbuffers;
};
#endif /* DAVINCIHD_DISPLAY_H */

View File

@@ -0,0 +1,569 @@
/*
* Copyright (C) 2009 Texas Instruments.
*
* 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.
*
* common vpss system module platform driver for all video drivers.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <media/davinci/vpss.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VPSS Driver");
MODULE_AUTHOR("Texas Instruments");
/* DM644x defines */
#define DM644X_SBL_PCR_VPSS (4)
#define DM355_VPSSBL_INTSEL 0x10
#define DM355_VPSSBL_EVTSEL 0x14
/* vpss BL register offsets */
#define DM355_VPSSBL_CCDCMUX 0x1c
/* vpss CLK register offsets */
#define DM355_VPSSCLK_CLKCTRL 0x04
/* masks and shifts */
#define VPSS_HSSISEL_SHIFT 4
/*
* VDINT0 - vpss_int0, VDINT1 - vpss_int1, H3A - vpss_int4,
* IPIPE_INT1_SDR - vpss_int5
*/
#define DM355_VPSSBL_INTSEL_DEFAULT 0xff83ff10
/* VENCINT - vpss_int8 */
#define DM355_VPSSBL_EVTSEL_DEFAULT 0x4
#define DM365_ISP5_PCCR 0x04
#define DM365_ISP5_PCCR_BL_CLK_ENABLE BIT(0)
#define DM365_ISP5_PCCR_ISIF_CLK_ENABLE BIT(1)
#define DM365_ISP5_PCCR_H3A_CLK_ENABLE BIT(2)
#define DM365_ISP5_PCCR_RSZ_CLK_ENABLE BIT(3)
#define DM365_ISP5_PCCR_IPIPE_CLK_ENABLE BIT(4)
#define DM365_ISP5_PCCR_IPIPEIF_CLK_ENABLE BIT(5)
#define DM365_ISP5_PCCR_RSV BIT(6)
#define DM365_ISP5_BCR 0x08
#define DM365_ISP5_BCR_ISIF_OUT_ENABLE BIT(1)
#define DM365_ISP5_INTSEL1 0x10
#define DM365_ISP5_INTSEL2 0x14
#define DM365_ISP5_INTSEL3 0x18
#define DM365_ISP5_CCDCMUX 0x20
#define DM365_ISP5_PG_FRAME_SIZE 0x28
#define DM365_VPBE_CLK_CTRL 0x00
#define VPSS_CLK_CTRL 0x01c40044
#define VPSS_CLK_CTRL_VENCCLKEN BIT(3)
#define VPSS_CLK_CTRL_DACCLKEN BIT(4)
/*
* vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1,
* AF - vpss_int3
*/
#define DM365_ISP5_INTSEL1_DEFAULT 0x0b1f0100
/* AEW - vpss_int6, RSZ_INT_DMA - vpss_int5 */
#define DM365_ISP5_INTSEL2_DEFAULT 0x1f0a0f1f
/* VENC - vpss_int8 */
#define DM365_ISP5_INTSEL3_DEFAULT 0x00000015
/* masks and shifts for DM365*/
#define DM365_CCDC_PG_VD_POL_SHIFT 0
#define DM365_CCDC_PG_HD_POL_SHIFT 1
#define CCD_SRC_SEL_MASK (BIT_MASK(5) | BIT_MASK(4))
#define CCD_SRC_SEL_SHIFT 4
/* Different SoC platforms supported by this driver */
enum vpss_platform_type {
DM644X,
DM355,
DM365,
};
/*
* vpss operations. Depends on platform. Not all functions are available
* on all platforms. The api, first check if a function is available before
* invoking it. In the probe, the function ptrs are initialized based on
* vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
*/
struct vpss_hw_ops {
/* enable clock */
int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
/* select input to ccdc */
void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
/* clear wbl overflow bit */
int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
/* set sync polarity */
void (*set_sync_pol)(struct vpss_sync_pol);
/* set the PG_FRAME_SIZE register*/
void (*set_pg_frame_size)(struct vpss_pg_frame_size);
/* check and clear interrupt if occurred */
int (*dma_complete_interrupt)(void);
};
/* vpss configuration */
struct vpss_oper_config {
__iomem void *vpss_regs_base0;
__iomem void *vpss_regs_base1;
resource_size_t *vpss_regs_base2;
enum vpss_platform_type platform;
spinlock_t vpss_lock;
struct vpss_hw_ops hw_ops;
};
static struct vpss_oper_config oper_cfg;
/* register access routines */
static inline u32 bl_regr(u32 offset)
{
return __raw_readl(oper_cfg.vpss_regs_base0 + offset);
}
static inline void bl_regw(u32 val, u32 offset)
{
__raw_writel(val, oper_cfg.vpss_regs_base0 + offset);
}
static inline u32 vpss_regr(u32 offset)
{
return __raw_readl(oper_cfg.vpss_regs_base1 + offset);
}
static inline void vpss_regw(u32 val, u32 offset)
{
__raw_writel(val, oper_cfg.vpss_regs_base1 + offset);
}
/* For DM365 only */
static inline u32 isp5_read(u32 offset)
{
return __raw_readl(oper_cfg.vpss_regs_base0 + offset);
}
/* For DM365 only */
static inline void isp5_write(u32 val, u32 offset)
{
__raw_writel(val, oper_cfg.vpss_regs_base0 + offset);
}
static void dm365_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
{
u32 temp = isp5_read(DM365_ISP5_CCDCMUX) & ~CCD_SRC_SEL_MASK;
/* if we are using pattern generator, enable it */
if (src_sel == VPSS_PGLPBK || src_sel == VPSS_CCDCPG)
temp |= 0x08;
temp |= (src_sel << CCD_SRC_SEL_SHIFT);
isp5_write(temp, DM365_ISP5_CCDCMUX);
}
static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
{
bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
}
int vpss_dma_complete_interrupt(void)
{
if (!oper_cfg.hw_ops.dma_complete_interrupt)
return 2;
return oper_cfg.hw_ops.dma_complete_interrupt();
}
EXPORT_SYMBOL(vpss_dma_complete_interrupt);
int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
{
if (!oper_cfg.hw_ops.select_ccdc_source)
return -EINVAL;
oper_cfg.hw_ops.select_ccdc_source(src_sel);
return 0;
}
EXPORT_SYMBOL(vpss_select_ccdc_source);
static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
{
u32 mask = 1, val;
if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
wbl_sel > VPSS_PCR_CCDC_WBL_O)
return -EINVAL;
/* writing a 0 clear the overflow */
mask = ~(mask << wbl_sel);
val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
bl_regw(val, DM644X_SBL_PCR_VPSS);
return 0;
}
void vpss_set_sync_pol(struct vpss_sync_pol sync)
{
if (!oper_cfg.hw_ops.set_sync_pol)
return;
oper_cfg.hw_ops.set_sync_pol(sync);
}
EXPORT_SYMBOL(vpss_set_sync_pol);
int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
{
if (!oper_cfg.hw_ops.clear_wbl_overflow)
return -EINVAL;
return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
}
EXPORT_SYMBOL(vpss_clear_wbl_overflow);
/*
* dm355_enable_clock - Enable VPSS Clock
* @clock_sel: Clock to be enabled/disabled
* @en: enable/disable flag
*
* This is called to enable or disable a vpss clock
*/
static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
{
unsigned long flags;
u32 utemp, mask = 0x1, shift = 0;
switch (clock_sel) {
case VPSS_VPBE_CLOCK:
/* nothing since lsb */
break;
case VPSS_VENC_CLOCK_SEL:
shift = 2;
break;
case VPSS_CFALD_CLOCK:
shift = 3;
break;
case VPSS_H3A_CLOCK:
shift = 4;
break;
case VPSS_IPIPE_CLOCK:
shift = 5;
break;
case VPSS_CCDC_CLOCK:
shift = 6;
break;
default:
printk(KERN_ERR "dm355_enable_clock:"
" Invalid selector: %d\n", clock_sel);
return -EINVAL;
}
spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
if (!en)
utemp &= ~(mask << shift);
else
utemp |= (mask << shift);
vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
return 0;
}
static int dm365_enable_clock(enum vpss_clock_sel clock_sel, int en)
{
unsigned long flags;
u32 utemp, mask = 0x1, shift = 0, offset = DM365_ISP5_PCCR;
u32 (*read)(u32 offset) = isp5_read;
void(*write)(u32 val, u32 offset) = isp5_write;
switch (clock_sel) {
case VPSS_BL_CLOCK:
break;
case VPSS_CCDC_CLOCK:
shift = 1;
break;
case VPSS_H3A_CLOCK:
shift = 2;
break;
case VPSS_RSZ_CLOCK:
shift = 3;
break;
case VPSS_IPIPE_CLOCK:
shift = 4;
break;
case VPSS_IPIPEIF_CLOCK:
shift = 5;
break;
case VPSS_PCLK_INTERNAL:
shift = 6;
break;
case VPSS_PSYNC_CLOCK_SEL:
shift = 7;
break;
case VPSS_VPBE_CLOCK:
read = vpss_regr;
write = vpss_regw;
offset = DM365_VPBE_CLK_CTRL;
break;
case VPSS_VENC_CLOCK_SEL:
shift = 2;
read = vpss_regr;
write = vpss_regw;
offset = DM365_VPBE_CLK_CTRL;
break;
case VPSS_LDC_CLOCK:
shift = 3;
read = vpss_regr;
write = vpss_regw;
offset = DM365_VPBE_CLK_CTRL;
break;
case VPSS_FDIF_CLOCK:
shift = 4;
read = vpss_regr;
write = vpss_regw;
offset = DM365_VPBE_CLK_CTRL;
break;
case VPSS_OSD_CLOCK_SEL:
shift = 6;
read = vpss_regr;
write = vpss_regw;
offset = DM365_VPBE_CLK_CTRL;
break;
case VPSS_LDC_CLOCK_SEL:
shift = 7;
read = vpss_regr;
write = vpss_regw;
offset = DM365_VPBE_CLK_CTRL;
break;
default:
printk(KERN_ERR "dm365_enable_clock: Invalid selector: %d\n",
clock_sel);
return -1;
}
spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
utemp = read(offset);
if (!en) {
mask = ~mask;
utemp &= (mask << shift);
} else
utemp |= (mask << shift);
write(utemp, offset);
spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
return 0;
}
int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
{
if (!oper_cfg.hw_ops.enable_clock)
return -EINVAL;
return oper_cfg.hw_ops.enable_clock(clock_sel, en);
}
EXPORT_SYMBOL(vpss_enable_clock);
void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync)
{
int val = 0;
val = isp5_read(DM365_ISP5_CCDCMUX);
val |= (sync.ccdpg_hdpol << DM365_CCDC_PG_HD_POL_SHIFT);
val |= (sync.ccdpg_vdpol << DM365_CCDC_PG_VD_POL_SHIFT);
isp5_write(val, DM365_ISP5_CCDCMUX);
}
EXPORT_SYMBOL(dm365_vpss_set_sync_pol);
void vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
{
if (!oper_cfg.hw_ops.set_pg_frame_size)
return;
oper_cfg.hw_ops.set_pg_frame_size(frame_size);
}
EXPORT_SYMBOL(vpss_set_pg_frame_size);
void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
{
int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16;
current_reg |= (frame_size.pplen - 1);
isp5_write(current_reg, DM365_ISP5_PG_FRAME_SIZE);
}
EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size);
static int vpss_probe(struct platform_device *pdev)
{
struct resource *r1, *r2;
char *platform_name;
int status;
if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "no platform data\n");
return -ENOENT;
}
platform_name = pdev->dev.platform_data;
if (!strcmp(platform_name, "dm355_vpss"))
oper_cfg.platform = DM355;
else if (!strcmp(platform_name, "dm365_vpss"))
oper_cfg.platform = DM365;
else if (!strcmp(platform_name, "dm644x_vpss"))
oper_cfg.platform = DM644X;
else {
dev_err(&pdev->dev, "vpss driver not supported on"
" this platform\n");
return -ENODEV;
}
dev_info(&pdev->dev, "%s vpss probed\n", platform_name);
r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r1)
return -ENOENT;
r1 = request_mem_region(r1->start, resource_size(r1), r1->name);
if (!r1)
return -EBUSY;
oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1));
if (!oper_cfg.vpss_regs_base0) {
status = -EBUSY;
goto fail1;
}
if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!r2) {
status = -ENOENT;
goto fail2;
}
r2 = request_mem_region(r2->start, resource_size(r2), r2->name);
if (!r2) {
status = -EBUSY;
goto fail2;
}
oper_cfg.vpss_regs_base1 = ioremap(r2->start,
resource_size(r2));
if (!oper_cfg.vpss_regs_base1) {
status = -EBUSY;
goto fail3;
}
}
if (oper_cfg.platform == DM355) {
oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
/* Setup vpss interrupts */
bl_regw(DM355_VPSSBL_INTSEL_DEFAULT, DM355_VPSSBL_INTSEL);
bl_regw(DM355_VPSSBL_EVTSEL_DEFAULT, DM355_VPSSBL_EVTSEL);
} else if (oper_cfg.platform == DM365) {
oper_cfg.hw_ops.enable_clock = dm365_enable_clock;
oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source;
/* Setup vpss interrupts */
isp5_write((isp5_read(DM365_ISP5_PCCR) |
DM365_ISP5_PCCR_BL_CLK_ENABLE |
DM365_ISP5_PCCR_ISIF_CLK_ENABLE |
DM365_ISP5_PCCR_H3A_CLK_ENABLE |
DM365_ISP5_PCCR_RSZ_CLK_ENABLE |
DM365_ISP5_PCCR_IPIPE_CLK_ENABLE |
DM365_ISP5_PCCR_IPIPEIF_CLK_ENABLE |
DM365_ISP5_PCCR_RSV), DM365_ISP5_PCCR);
isp5_write((isp5_read(DM365_ISP5_BCR) |
DM365_ISP5_BCR_ISIF_OUT_ENABLE), DM365_ISP5_BCR);
isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1);
isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2);
isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3);
} else
oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
pm_runtime_enable(&pdev->dev);
pm_runtime_get(&pdev->dev);
spin_lock_init(&oper_cfg.vpss_lock);
dev_info(&pdev->dev, "%s vpss probe success\n", platform_name);
return 0;
fail3:
release_mem_region(r2->start, resource_size(r2));
fail2:
iounmap(oper_cfg.vpss_regs_base0);
fail1:
release_mem_region(r1->start, resource_size(r1));
return status;
}
static int vpss_remove(struct platform_device *pdev)
{
struct resource *res;
pm_runtime_disable(&pdev->dev);
iounmap(oper_cfg.vpss_regs_base0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
iounmap(oper_cfg.vpss_regs_base1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
release_mem_region(res->start, resource_size(res));
}
return 0;
}
static int vpss_suspend(struct device *dev)
{
pm_runtime_put(dev);
return 0;
}
static int vpss_resume(struct device *dev)
{
pm_runtime_get(dev);
return 0;
}
static const struct dev_pm_ops vpss_pm_ops = {
.suspend = vpss_suspend,
.resume = vpss_resume,
};
static struct platform_driver vpss_driver = {
.driver = {
.name = "vpss",
.owner = THIS_MODULE,
.pm = &vpss_pm_ops,
},
.remove = vpss_remove,
.probe = vpss_probe,
};
static void vpss_exit(void)
{
iounmap(oper_cfg.vpss_regs_base2);
release_mem_region(VPSS_CLK_CTRL, 4);
platform_driver_unregister(&vpss_driver);
}
static int __init vpss_init(void)
{
if (!request_mem_region(VPSS_CLK_CTRL, 4, "vpss_clock_control"))
return -EBUSY;
oper_cfg.vpss_regs_base2 = ioremap(VPSS_CLK_CTRL, 4);
writel(VPSS_CLK_CTRL_VENCCLKEN |
VPSS_CLK_CTRL_DACCLKEN, oper_cfg.vpss_regs_base2);
return platform_driver_register(&vpss_driver);
}
subsys_initcall(vpss_init);
module_exit(vpss_exit);