aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/davinci
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/media/video/davinci
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/media/video/davinci')
-rw-r--r--drivers/media/video/davinci/Kconfig116
-rw-r--r--drivers/media/video/davinci/Makefile20
-rw-r--r--drivers/media/video/davinci/ccdc_hw_device.h110
-rw-r--r--drivers/media/video/davinci/dm355_ccdc.c1082
-rw-r--r--drivers/media/video/davinci/dm355_ccdc_regs.h310
-rw-r--r--drivers/media/video/davinci/dm644x_ccdc.c1091
-rw-r--r--drivers/media/video/davinci/dm644x_ccdc_regs.h153
-rw-r--r--drivers/media/video/davinci/isif.c1172
-rw-r--r--drivers/media/video/davinci/isif_regs.h269
-rw-r--r--drivers/media/video/davinci/vpbe.c864
-rw-r--r--drivers/media/video/davinci/vpbe_display.c1860
-rw-r--r--drivers/media/video/davinci/vpbe_osd.c1231
-rw-r--r--drivers/media/video/davinci/vpbe_osd_regs.h364
-rw-r--r--drivers/media/video/davinci/vpbe_venc.c566
-rw-r--r--drivers/media/video/davinci/vpbe_venc_regs.h177
-rw-r--r--drivers/media/video/davinci/vpfe_capture.c2095
-rw-r--r--drivers/media/video/davinci/vpif.c473
-rw-r--r--drivers/media/video/davinci/vpif.h644
-rw-r--r--drivers/media/video/davinci/vpif_capture.c2412
-rw-r--r--drivers/media/video/davinci/vpif_capture.h162
-rw-r--r--drivers/media/video/davinci/vpif_display.c1914
-rw-r--r--drivers/media/video/davinci/vpif_display.h171
-rw-r--r--drivers/media/video/davinci/vpss.c482
23 files changed, 17738 insertions, 0 deletions
diff --git a/drivers/media/video/davinci/Kconfig b/drivers/media/video/davinci/Kconfig
new file mode 100644
index 00000000000..60a456ebdc7
--- /dev/null
+++ b/drivers/media/video/davinci/Kconfig
@@ -0,0 +1,116 @@
1config DISPLAY_DAVINCI_DM646X_EVM
2 tristate "DM646x EVM Video Display"
3 depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
4 select VIDEOBUF_DMA_CONTIG
5 select VIDEO_DAVINCI_VPIF
6 select VIDEO_ADV7343
7 select VIDEO_THS7303
8 help
9 Support for DM6467 based display device.
10
11 To compile this driver as a module, choose M here: the
12 module will be called vpif_display.
13
14config CAPTURE_DAVINCI_DM646X_EVM
15 tristate "DM646x EVM Video Capture"
16 depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
17 select VIDEOBUF_DMA_CONTIG
18 select VIDEO_DAVINCI_VPIF
19 help
20 Support for DM6467 based capture device.
21
22 To compile this driver as a module, choose M here: the
23 module will be called vpif_capture.
24
25config VIDEO_DAVINCI_VPIF
26 tristate "DaVinci VPIF Driver"
27 depends on DISPLAY_DAVINCI_DM646X_EVM
28 help
29 Support for DaVinci VPIF Driver.
30
31 To compile this driver as a module, choose M here: the
32 module will be called vpif.
33
34config VIDEO_VPSS_SYSTEM
35 tristate "VPSS System module driver"
36 depends on ARCH_DAVINCI
37 help
38 Support for vpss system module for video driver
39
40config VIDEO_VPFE_CAPTURE
41 tristate "VPFE Video Capture Driver"
42 depends on VIDEO_V4L2 && (ARCH_DAVINCI || ARCH_OMAP3)
43 select VIDEOBUF_DMA_CONTIG
44 help
45 Support for DMx/AMx VPFE based frame grabber. This is the
46 common V4L2 module for following DMx/AMx SoCs from Texas
47 Instruments:- DM6446, DM365, DM355 & AM3517/05.
48
49 To compile this driver as a module, choose M here: the
50 module will be called vpfe-capture.
51
52config VIDEO_DM6446_CCDC
53 tristate "DM6446 CCDC HW module"
54 depends on VIDEO_VPFE_CAPTURE
55 select VIDEO_VPSS_SYSTEM
56 default y
57 help
58 Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
59 with decoder modules such as TVP5146 over BT656 or
60 sensor module such as MT9T001 over a raw interface. This
61 module configures the interface and CCDC/ISIF to do
62 video frame capture from slave decoders.
63
64 To compile this driver as a module, choose M here: the
65 module will be called vpfe.
66
67config VIDEO_DM355_CCDC
68 tristate "DM355 CCDC HW module"
69 depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE
70 select VIDEO_VPSS_SYSTEM
71 default y
72 help
73 Enables DM355 CCD hw module. DM355 CCDC hw interfaces
74 with decoder modules such as TVP5146 over BT656 or
75 sensor module such as MT9T001 over a raw interface. This
76 module configures the interface and CCDC/ISIF to do
77 video frame capture from a slave decoders
78
79 To compile this driver as a module, choose M here: the
80 module will be called vpfe.
81
82config VIDEO_ISIF
83 tristate "ISIF HW module"
84 depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE
85 select VIDEO_VPSS_SYSTEM
86 default y
87 help
88 Enables ISIF hw module. This is the hardware module for
89 configuring ISIF in VPFE to capture Raw Bayer RGB data from
90 a image sensor or YUV data from a YUV source.
91
92 To compile this driver as a module, choose M here: the
93 module will be called vpfe.
94
95config VIDEO_DM644X_VPBE
96 tristate "DM644X VPBE HW module"
97 depends on ARCH_DAVINCI_DM644x
98 select VIDEO_VPSS_SYSTEM
99 select VIDEOBUF_DMA_CONTIG
100 help
101 Enables VPBE modules used for display on a DM644x
102 SoC.
103
104 To compile this driver as a module, choose M here: the
105 module will be called vpbe.
106
107
108config VIDEO_VPBE_DISPLAY
109 tristate "VPBE V4L2 Display driver"
110 depends on ARCH_DAVINCI_DM644x
111 select VIDEO_DM644X_VPBE
112 help
113 Enables VPBE V4L2 Display driver on a DM644x device
114
115 To compile this driver as a module, choose M here: the
116 module will be called vpbe_display.
diff --git a/drivers/media/video/davinci/Makefile b/drivers/media/video/davinci/Makefile
new file mode 100644
index 00000000000..ae7dafb689a
--- /dev/null
+++ b/drivers/media/video/davinci/Makefile
@@ -0,0 +1,20 @@
1#
2# Makefile for the davinci video device drivers.
3#
4
5# VPIF
6obj-$(CONFIG_VIDEO_DAVINCI_VPIF) += vpif.o
7
8#DM646x EVM Display driver
9obj-$(CONFIG_DISPLAY_DAVINCI_DM646X_EVM) += vpif_display.o
10#DM646x EVM Capture driver
11obj-$(CONFIG_CAPTURE_DAVINCI_DM646X_EVM) += vpif_capture.o
12
13# Capture: DM6446 and DM355
14obj-$(CONFIG_VIDEO_VPSS_SYSTEM) += vpss.o
15obj-$(CONFIG_VIDEO_VPFE_CAPTURE) += vpfe_capture.o
16obj-$(CONFIG_VIDEO_DM6446_CCDC) += dm644x_ccdc.o
17obj-$(CONFIG_VIDEO_DM355_CCDC) += dm355_ccdc.o
18obj-$(CONFIG_VIDEO_ISIF) += isif.o
19obj-$(CONFIG_VIDEO_DM644X_VPBE) += vpbe.o vpbe_osd.o vpbe_venc.o
20obj-$(CONFIG_VIDEO_VPBE_DISPLAY) += vpbe_display.o
diff --git a/drivers/media/video/davinci/ccdc_hw_device.h b/drivers/media/video/davinci/ccdc_hw_device.h
new file mode 100644
index 00000000000..86b9b351896
--- /dev/null
+++ b/drivers/media/video/davinci/ccdc_hw_device.h
@@ -0,0 +1,110 @@
1/*
2 * Copyright (C) 2008-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * ccdc device API
19 */
20#ifndef _CCDC_HW_DEVICE_H
21#define _CCDC_HW_DEVICE_H
22
23#ifdef __KERNEL__
24#include <linux/videodev2.h>
25#include <linux/device.h>
26#include <media/davinci/vpfe_types.h>
27#include <media/davinci/ccdc_types.h>
28
29/*
30 * ccdc hw operations
31 */
32struct ccdc_hw_ops {
33 /* Pointer to initialize function to initialize ccdc device */
34 int (*open) (struct device *dev);
35 /* Pointer to deinitialize function */
36 int (*close) (struct device *dev);
37 /* set ccdc base address */
38 void (*set_ccdc_base)(void *base, int size);
39 /* Pointer to function to enable or disable ccdc */
40 void (*enable) (int en);
41 /* reset sbl. only for 6446 */
42 void (*reset) (void);
43 /* enable output to sdram */
44 void (*enable_out_to_sdram) (int en);
45 /* Pointer to function to set hw parameters */
46 int (*set_hw_if_params) (struct vpfe_hw_if_param *param);
47 /* get interface parameters */
48 int (*get_hw_if_params) (struct vpfe_hw_if_param *param);
49 /*
50 * Pointer to function to set parameters. Used
51 * for implementing VPFE_S_CCDC_PARAMS
52 */
53 int (*set_params) (void *params);
54 /*
55 * Pointer to function to get parameter. Used
56 * for implementing VPFE_G_CCDC_PARAMS
57 */
58 int (*get_params) (void *params);
59 /* Pointer to function to configure ccdc */
60 int (*configure) (void);
61
62 /* Pointer to function to set buffer type */
63 int (*set_buftype) (enum ccdc_buftype buf_type);
64 /* Pointer to function to get buffer type */
65 enum ccdc_buftype (*get_buftype) (void);
66 /* Pointer to function to set frame format */
67 int (*set_frame_format) (enum ccdc_frmfmt frm_fmt);
68 /* Pointer to function to get frame format */
69 enum ccdc_frmfmt (*get_frame_format) (void);
70 /* enumerate hw pix formats */
71 int (*enum_pix)(u32 *hw_pix, int i);
72 /* Pointer to function to set buffer type */
73 u32 (*get_pixel_format) (void);
74 /* Pointer to function to get pixel format. */
75 int (*set_pixel_format) (u32 pixfmt);
76 /* Pointer to function to set image window */
77 int (*set_image_window) (struct v4l2_rect *win);
78 /* Pointer to function to set image window */
79 void (*get_image_window) (struct v4l2_rect *win);
80 /* Pointer to function to get line length */
81 unsigned int (*get_line_length) (void);
82
83 /* Query CCDC control IDs */
84 int (*queryctrl)(struct v4l2_queryctrl *qctrl);
85 /* Set CCDC control */
86 int (*set_control)(struct v4l2_control *ctrl);
87 /* Get CCDC control */
88 int (*get_control)(struct v4l2_control *ctrl);
89
90 /* Pointer to function to set frame buffer address */
91 void (*setfbaddr) (unsigned long addr);
92 /* Pointer to function to get field id */
93 int (*getfid) (void);
94};
95
96struct ccdc_hw_device {
97 /* ccdc device name */
98 char name[32];
99 /* module owner */
100 struct module *owner;
101 /* hw ops */
102 struct ccdc_hw_ops hw_ops;
103};
104
105/* Used by CCDC module to register & unregister with vpfe capture driver */
106int vpfe_register_ccdc_device(struct ccdc_hw_device *dev);
107void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev);
108
109#endif
110#endif
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c
new file mode 100644
index 00000000000..c29ac88ffd7
--- /dev/null
+++ b/drivers/media/video/davinci/dm355_ccdc.c
@@ -0,0 +1,1082 @@
1/*
2 * Copyright (C) 2005-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * CCDC hardware module for DM355
19 * ------------------------------
20 *
21 * This module is for configuring DM355 CCD controller of VPFE to capture
22 * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules
23 * such as Defect Pixel Correction, Color Space Conversion etc to
24 * pre-process the Bayer RGB data, before writing it to SDRAM. This
25 * module also allows application to configure individual
26 * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL.
27 * To do so, application include dm355_ccdc.h and vpfe_capture.h header
28 * files. The setparams() API is called by vpfe_capture driver
29 * to configure module parameters
30 *
31 * TODO: 1) Raw bayer parameter settings and bayer capture
32 * 2) Split module parameter structure to module specific ioctl structs
33 * 3) add support for lense shading correction
34 * 4) investigate if enum used for user space type definition
35 * to be replaced by #defines or integer
36 */
37#include <linux/platform_device.h>
38#include <linux/uaccess.h>
39#include <linux/videodev2.h>
40#include <linux/clk.h>
41#include <linux/err.h>
42
43#include <media/davinci/dm355_ccdc.h>
44#include <media/davinci/vpss.h>
45
46#include "dm355_ccdc_regs.h"
47#include "ccdc_hw_device.h"
48
49MODULE_LICENSE("GPL");
50MODULE_DESCRIPTION("CCDC Driver for DM355");
51MODULE_AUTHOR("Texas Instruments");
52
53static struct ccdc_oper_config {
54 struct device *dev;
55 /* CCDC interface type */
56 enum vpfe_hw_if_type if_type;
57 /* Raw Bayer configuration */
58 struct ccdc_params_raw bayer;
59 /* YCbCr configuration */
60 struct ccdc_params_ycbcr ycbcr;
61 /* Master clock */
62 struct clk *mclk;
63 /* slave clock */
64 struct clk *sclk;
65 /* ccdc base address */
66 void __iomem *base_addr;
67} ccdc_cfg = {
68 /* Raw configurations */
69 .bayer = {
70 .pix_fmt = CCDC_PIXFMT_RAW,
71 .frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
72 .win = CCDC_WIN_VGA,
73 .fid_pol = VPFE_PINPOL_POSITIVE,
74 .vd_pol = VPFE_PINPOL_POSITIVE,
75 .hd_pol = VPFE_PINPOL_POSITIVE,
76 .gain = {
77 .r_ye = 256,
78 .gb_g = 256,
79 .gr_cy = 256,
80 .b_mg = 256
81 },
82 .config_params = {
83 .datasft = 2,
84 .mfilt1 = CCDC_NO_MEDIAN_FILTER1,
85 .mfilt2 = CCDC_NO_MEDIAN_FILTER2,
86 .alaw = {
87 .gama_wd = 2,
88 },
89 .blk_clamp = {
90 .sample_pixel = 1,
91 .dc_sub = 25
92 },
93 .col_pat_field0 = {
94 .olop = CCDC_GREEN_BLUE,
95 .olep = CCDC_BLUE,
96 .elop = CCDC_RED,
97 .elep = CCDC_GREEN_RED
98 },
99 .col_pat_field1 = {
100 .olop = CCDC_GREEN_BLUE,
101 .olep = CCDC_BLUE,
102 .elop = CCDC_RED,
103 .elep = CCDC_GREEN_RED
104 },
105 },
106 },
107 /* YCbCr configuration */
108 .ycbcr = {
109 .win = CCDC_WIN_PAL,
110 .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
111 .frm_fmt = CCDC_FRMFMT_INTERLACED,
112 .fid_pol = VPFE_PINPOL_POSITIVE,
113 .vd_pol = VPFE_PINPOL_POSITIVE,
114 .hd_pol = VPFE_PINPOL_POSITIVE,
115 .bt656_enable = 1,
116 .pix_order = CCDC_PIXORDER_CBYCRY,
117 .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
118 },
119};
120
121
122/* Raw Bayer formats */
123static u32 ccdc_raw_bayer_pix_formats[] =
124 {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
125
126/* Raw YUV formats */
127static u32 ccdc_raw_yuv_pix_formats[] =
128 {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
129
130/* register access routines */
131static inline u32 regr(u32 offset)
132{
133 return __raw_readl(ccdc_cfg.base_addr + offset);
134}
135
136static inline void regw(u32 val, u32 offset)
137{
138 __raw_writel(val, ccdc_cfg.base_addr + offset);
139}
140
141static void ccdc_enable(int en)
142{
143 unsigned int temp;
144 temp = regr(SYNCEN);
145 temp &= (~CCDC_SYNCEN_VDHDEN_MASK);
146 temp |= (en & CCDC_SYNCEN_VDHDEN_MASK);
147 regw(temp, SYNCEN);
148}
149
150static void ccdc_enable_output_to_sdram(int en)
151{
152 unsigned int temp;
153 temp = regr(SYNCEN);
154 temp &= (~(CCDC_SYNCEN_WEN_MASK));
155 temp |= ((en << CCDC_SYNCEN_WEN_SHIFT) & CCDC_SYNCEN_WEN_MASK);
156 regw(temp, SYNCEN);
157}
158
159static void ccdc_config_gain_offset(void)
160{
161 /* configure gain */
162 regw(ccdc_cfg.bayer.gain.r_ye, RYEGAIN);
163 regw(ccdc_cfg.bayer.gain.gr_cy, GRCYGAIN);
164 regw(ccdc_cfg.bayer.gain.gb_g, GBGGAIN);
165 regw(ccdc_cfg.bayer.gain.b_mg, BMGGAIN);
166 /* configure offset */
167 regw(ccdc_cfg.bayer.ccdc_offset, OFFSET);
168}
169
170/*
171 * ccdc_restore_defaults()
172 * This function restore power on defaults in the ccdc registers
173 */
174static int ccdc_restore_defaults(void)
175{
176 int i;
177
178 dev_dbg(ccdc_cfg.dev, "\nstarting ccdc_restore_defaults...");
179 /* set all registers to zero */
180 for (i = 0; i <= CCDC_REG_LAST; i += 4)
181 regw(0, i);
182
183 /* now override the values with power on defaults in registers */
184 regw(MODESET_DEFAULT, MODESET);
185 /* no culling support */
186 regw(CULH_DEFAULT, CULH);
187 regw(CULV_DEFAULT, CULV);
188 /* Set default Gain and Offset */
189 ccdc_cfg.bayer.gain.r_ye = GAIN_DEFAULT;
190 ccdc_cfg.bayer.gain.gb_g = GAIN_DEFAULT;
191 ccdc_cfg.bayer.gain.gr_cy = GAIN_DEFAULT;
192 ccdc_cfg.bayer.gain.b_mg = GAIN_DEFAULT;
193 ccdc_config_gain_offset();
194 regw(OUTCLIP_DEFAULT, OUTCLIP);
195 regw(LSCCFG2_DEFAULT, LSCCFG2);
196 /* select ccdc input */
197 if (vpss_select_ccdc_source(VPSS_CCDCIN)) {
198 dev_dbg(ccdc_cfg.dev, "\ncouldn't select ccdc input source");
199 return -EFAULT;
200 }
201 /* select ccdc clock */
202 if (vpss_enable_clock(VPSS_CCDC_CLOCK, 1) < 0) {
203 dev_dbg(ccdc_cfg.dev, "\ncouldn't enable ccdc clock");
204 return -EFAULT;
205 }
206 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_restore_defaults...");
207 return 0;
208}
209
210static int ccdc_open(struct device *device)
211{
212 return ccdc_restore_defaults();
213}
214
215static int ccdc_close(struct device *device)
216{
217 /* disable clock */
218 vpss_enable_clock(VPSS_CCDC_CLOCK, 0);
219 /* do nothing for now */
220 return 0;
221}
222/*
223 * ccdc_setwin()
224 * This function will configure the window size to
225 * be capture in CCDC reg.
226 */
227static void ccdc_setwin(struct v4l2_rect *image_win,
228 enum ccdc_frmfmt frm_fmt, int ppc)
229{
230 int horz_start, horz_nr_pixels;
231 int vert_start, vert_nr_lines;
232 int mid_img = 0;
233
234 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin...");
235
236 /*
237 * ppc - per pixel count. indicates how many pixels per cell
238 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
239 * raw capture this is 1
240 */
241 horz_start = image_win->left << (ppc - 1);
242 horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1;
243
244 /* Writing the horizontal info into the registers */
245 regw(horz_start, SPH);
246 regw(horz_nr_pixels, NPH);
247 vert_start = image_win->top;
248
249 if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
250 vert_nr_lines = (image_win->height >> 1) - 1;
251 vert_start >>= 1;
252 /* Since first line doesn't have any data */
253 vert_start += 1;
254 /* configure VDINT0 and VDINT1 */
255 regw(vert_start, VDINT0);
256 } else {
257 /* Since first line doesn't have any data */
258 vert_start += 1;
259 vert_nr_lines = image_win->height - 1;
260 /* configure VDINT0 and VDINT1 */
261 mid_img = vert_start + (image_win->height / 2);
262 regw(vert_start, VDINT0);
263 regw(mid_img, VDINT1);
264 }
265 regw(vert_start & CCDC_START_VER_ONE_MASK, SLV0);
266 regw(vert_start & CCDC_START_VER_TWO_MASK, SLV1);
267 regw(vert_nr_lines & CCDC_NUM_LINES_VER, NLV);
268 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin...");
269}
270
271static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
272{
273 if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT ||
274 ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) {
275 dev_dbg(ccdc_cfg.dev, "Invalid value of data shift\n");
276 return -EINVAL;
277 }
278
279 if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 ||
280 ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) {
281 dev_dbg(ccdc_cfg.dev, "Invalid value of median filter1\n");
282 return -EINVAL;
283 }
284
285 if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 ||
286 ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) {
287 dev_dbg(ccdc_cfg.dev, "Invalid value of median filter2\n");
288 return -EINVAL;
289 }
290
291 if ((ccdcparam->med_filt_thres < 0) ||
292 (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) {
293 dev_dbg(ccdc_cfg.dev,
294 "Invalid value of median filter thresold\n");
295 return -EINVAL;
296 }
297
298 if (ccdcparam->data_sz < CCDC_DATA_16BITS ||
299 ccdcparam->data_sz > CCDC_DATA_8BITS) {
300 dev_dbg(ccdc_cfg.dev, "Invalid value of data size\n");
301 return -EINVAL;
302 }
303
304 if (ccdcparam->alaw.enable) {
305 if (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_13_4 ||
306 ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) {
307 dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n");
308 return -EINVAL;
309 }
310 }
311
312 if (ccdcparam->blk_clamp.b_clamp_enable) {
313 if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS ||
314 ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) {
315 dev_dbg(ccdc_cfg.dev,
316 "Invalid value of sample pixel\n");
317 return -EINVAL;
318 }
319 if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES ||
320 ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) {
321 dev_dbg(ccdc_cfg.dev,
322 "Invalid value of sample lines\n");
323 return -EINVAL;
324 }
325 }
326 return 0;
327}
328
329/* Parameter operations */
330static int ccdc_set_params(void __user *params)
331{
332 struct ccdc_config_params_raw ccdc_raw_params;
333 int x;
334
335 /* only raw module parameters can be set through the IOCTL */
336 if (ccdc_cfg.if_type != VPFE_RAW_BAYER)
337 return -EINVAL;
338
339 x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
340 if (x) {
341 dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdc"
342 "params, %d\n", x);
343 return -EFAULT;
344 }
345
346 if (!validate_ccdc_param(&ccdc_raw_params)) {
347 memcpy(&ccdc_cfg.bayer.config_params,
348 &ccdc_raw_params,
349 sizeof(ccdc_raw_params));
350 return 0;
351 }
352 return -EINVAL;
353}
354
355/* This function will configure CCDC for YCbCr video capture */
356static void ccdc_config_ycbcr(void)
357{
358 struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr;
359 u32 temp;
360
361 /* first set the CCDC power on defaults values in all registers */
362 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr...");
363 ccdc_restore_defaults();
364
365 /* configure pixel format & video frame format */
366 temp = (((params->pix_fmt & CCDC_INPUT_MODE_MASK) <<
367 CCDC_INPUT_MODE_SHIFT) |
368 ((params->frm_fmt & CCDC_FRM_FMT_MASK) <<
369 CCDC_FRM_FMT_SHIFT));
370
371 /* setup BT.656 sync mode */
372 if (params->bt656_enable) {
373 regw(CCDC_REC656IF_BT656_EN, REC656IF);
374 /*
375 * configure the FID, VD, HD pin polarity fld,hd pol positive,
376 * vd negative, 8-bit pack mode
377 */
378 temp |= CCDC_VD_POL_NEGATIVE;
379 } else { /* y/c external sync mode */
380 temp |= (((params->fid_pol & CCDC_FID_POL_MASK) <<
381 CCDC_FID_POL_SHIFT) |
382 ((params->hd_pol & CCDC_HD_POL_MASK) <<
383 CCDC_HD_POL_SHIFT) |
384 ((params->vd_pol & CCDC_VD_POL_MASK) <<
385 CCDC_VD_POL_SHIFT));
386 }
387
388 /* pack the data to 8-bit */
389 temp |= CCDC_DATA_PACK_ENABLE;
390
391 regw(temp, MODESET);
392
393 /* configure video window */
394 ccdc_setwin(&params->win, params->frm_fmt, 2);
395
396 /* configure the order of y cb cr in SD-RAM */
397 temp = (params->pix_order << CCDC_Y8POS_SHIFT);
398 temp |= CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC;
399 regw(temp, CCDCFG);
400
401 /*
402 * configure the horizontal line offset. This is done by rounding up
403 * width to a multiple of 16 pixels and multiply by two to account for
404 * y:cb:cr 4:2:2 data
405 */
406 regw(((params->win.width * 2 + 31) >> 5), HSIZE);
407
408 /* configure the memory line offset */
409 if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
410 /* two fields are interleaved in memory */
411 regw(CCDC_SDOFST_FIELD_INTERLEAVED, SDOFST);
412 }
413
414 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n");
415}
416
417/*
418 * ccdc_config_black_clamp()
419 * configure parameters for Optical Black Clamp
420 */
421static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp)
422{
423 u32 val;
424
425 if (!bclamp->b_clamp_enable) {
426 /* configure DCSub */
427 regw(bclamp->dc_sub & CCDC_BLK_DC_SUB_MASK, DCSUB);
428 regw(0x0000, CLAMP);
429 return;
430 }
431 /* Enable the Black clamping, set sample lines and pixels */
432 val = (bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) |
433 ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) <<
434 CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE;
435 regw(val, CLAMP);
436
437 /* If Black clamping is enable then make dcsub 0 */
438 val = (bclamp->sample_ln & CCDC_NUM_LINE_CALC_MASK)
439 << CCDC_NUM_LINE_CALC_SHIFT;
440 regw(val, DCSUB);
441}
442
443/*
444 * ccdc_config_black_compense()
445 * configure parameters for Black Compensation
446 */
447static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp)
448{
449 u32 val;
450
451 val = (bcomp->b & CCDC_BLK_COMP_MASK) |
452 ((bcomp->gb & CCDC_BLK_COMP_MASK) <<
453 CCDC_BLK_COMP_GB_COMP_SHIFT);
454 regw(val, BLKCMP1);
455
456 val = ((bcomp->gr & CCDC_BLK_COMP_MASK) <<
457 CCDC_BLK_COMP_GR_COMP_SHIFT) |
458 ((bcomp->r & CCDC_BLK_COMP_MASK) <<
459 CCDC_BLK_COMP_R_COMP_SHIFT);
460 regw(val, BLKCMP0);
461}
462
463/*
464 * ccdc_write_dfc_entry()
465 * write an entry in the dfc table.
466 */
467int ccdc_write_dfc_entry(int index, struct ccdc_vertical_dft *dfc)
468{
469/* TODO This is to be re-visited and adjusted */
470#define DFC_WRITE_WAIT_COUNT 1000
471 u32 val, count = DFC_WRITE_WAIT_COUNT;
472
473 regw(dfc->dft_corr_vert[index], DFCMEM0);
474 regw(dfc->dft_corr_horz[index], DFCMEM1);
475 regw(dfc->dft_corr_sub1[index], DFCMEM2);
476 regw(dfc->dft_corr_sub2[index], DFCMEM3);
477 regw(dfc->dft_corr_sub3[index], DFCMEM4);
478 /* set WR bit to write */
479 val = regr(DFCMEMCTL) | CCDC_DFCMEMCTL_DFCMWR_MASK;
480 regw(val, DFCMEMCTL);
481
482 /*
483 * Assume, it is very short. If we get an error, we need to
484 * adjust this value
485 */
486 while (regr(DFCMEMCTL) & CCDC_DFCMEMCTL_DFCMWR_MASK)
487 count--;
488 /*
489 * TODO We expect the count to be non-zero to be successful. Adjust
490 * the count if write requires more time
491 */
492
493 if (count) {
494 dev_err(ccdc_cfg.dev, "defect table write timeout !!!\n");
495 return -1;
496 }
497 return 0;
498}
499
500/*
501 * ccdc_config_vdfc()
502 * configure parameters for Vertical Defect Correction
503 */
504static int ccdc_config_vdfc(struct ccdc_vertical_dft *dfc)
505{
506 u32 val;
507 int i;
508
509 /* Configure General Defect Correction. The table used is from IPIPE */
510 val = dfc->gen_dft_en & CCDC_DFCCTL_GDFCEN_MASK;
511
512 /* Configure Vertical Defect Correction if needed */
513 if (!dfc->ver_dft_en) {
514 /* Enable only General Defect Correction */
515 regw(val, DFCCTL);
516 return 0;
517 }
518
519 if (dfc->table_size > CCDC_DFT_TABLE_SIZE)
520 return -EINVAL;
521
522 val |= CCDC_DFCCTL_VDFC_DISABLE;
523 val |= (dfc->dft_corr_ctl.vdfcsl & CCDC_DFCCTL_VDFCSL_MASK) <<
524 CCDC_DFCCTL_VDFCSL_SHIFT;
525 val |= (dfc->dft_corr_ctl.vdfcuda & CCDC_DFCCTL_VDFCUDA_MASK) <<
526 CCDC_DFCCTL_VDFCUDA_SHIFT;
527 val |= (dfc->dft_corr_ctl.vdflsft & CCDC_DFCCTL_VDFLSFT_MASK) <<
528 CCDC_DFCCTL_VDFLSFT_SHIFT;
529 regw(val , DFCCTL);
530
531 /* clear address ptr to offset 0 */
532 val = CCDC_DFCMEMCTL_DFCMARST_MASK << CCDC_DFCMEMCTL_DFCMARST_SHIFT;
533
534 /* write defect table entries */
535 for (i = 0; i < dfc->table_size; i++) {
536 /* increment address for non zero index */
537 if (i != 0)
538 val = CCDC_DFCMEMCTL_INC_ADDR;
539 regw(val, DFCMEMCTL);
540 if (ccdc_write_dfc_entry(i, dfc) < 0)
541 return -EFAULT;
542 }
543
544 /* update saturation level and enable dfc */
545 regw(dfc->saturation_ctl & CCDC_VDC_DFCVSAT_MASK, DFCVSAT);
546 val = regr(DFCCTL) | (CCDC_DFCCTL_VDFCEN_MASK <<
547 CCDC_DFCCTL_VDFCEN_SHIFT);
548 regw(val, DFCCTL);
549 return 0;
550}
551
552/*
553 * ccdc_config_csc()
554 * configure parameters for color space conversion
555 * Each register CSCM0-7 has two values in S8Q5 format.
556 */
557static void ccdc_config_csc(struct ccdc_csc *csc)
558{
559 u32 val1, val2;
560 int i;
561
562 if (!csc->enable)
563 return;
564
565 /* Enable the CSC sub-module */
566 regw(CCDC_CSC_ENABLE, CSCCTL);
567
568 /* Converting the co-eff as per the format of the register */
569 for (i = 0; i < CCDC_CSC_COEFF_TABLE_SIZE; i++) {
570 if ((i % 2) == 0) {
571 /* CSCM - LSB */
572 val1 = (csc->coeff[i].integer &
573 CCDC_CSC_COEF_INTEG_MASK)
574 << CCDC_CSC_COEF_INTEG_SHIFT;
575 /*
576 * convert decimal part to binary. Use 2 decimal
577 * precision, user values range from .00 - 0.99
578 */
579 val1 |= (((csc->coeff[i].decimal &
580 CCDC_CSC_COEF_DECIMAL_MASK) *
581 CCDC_CSC_DEC_MAX) / 100);
582 } else {
583
584 /* CSCM - MSB */
585 val2 = (csc->coeff[i].integer &
586 CCDC_CSC_COEF_INTEG_MASK)
587 << CCDC_CSC_COEF_INTEG_SHIFT;
588 val2 |= (((csc->coeff[i].decimal &
589 CCDC_CSC_COEF_DECIMAL_MASK) *
590 CCDC_CSC_DEC_MAX) / 100);
591 val2 <<= CCDC_CSCM_MSB_SHIFT;
592 val2 |= val1;
593 regw(val2, (CSCM0 + ((i - 1) << 1)));
594 }
595 }
596}
597
598/*
599 * ccdc_config_color_patterns()
600 * configure parameters for color patterns
601 */
602static void ccdc_config_color_patterns(struct ccdc_col_pat *pat0,
603 struct ccdc_col_pat *pat1)
604{
605 u32 val;
606
607 val = (pat0->olop | (pat0->olep << 2) | (pat0->elop << 4) |
608 (pat0->elep << 6) | (pat1->olop << 8) | (pat1->olep << 10) |
609 (pat1->elop << 12) | (pat1->elep << 14));
610 regw(val, COLPTN);
611}
612
613/* This function will configure CCDC for Raw mode image capture */
614static int ccdc_config_raw(void)
615{
616 struct ccdc_params_raw *params = &ccdc_cfg.bayer;
617 struct ccdc_config_params_raw *config_params =
618 &ccdc_cfg.bayer.config_params;
619 unsigned int val;
620
621 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw...");
622
623 /* restore power on defaults to register */
624 ccdc_restore_defaults();
625
626 /* CCDCFG register:
627 * set CCD Not to swap input since input is RAW data
628 * set FID detection function to Latch at V-Sync
629 * set WENLOG - ccdc valid area to AND
630 * set TRGSEL to WENBIT
631 * set EXTRG to DISABLE
632 * disable latching function on VSYNC - shadowed registers
633 */
634 regw(CCDC_YCINSWP_RAW | CCDC_CCDCFG_FIDMD_LATCH_VSYNC |
635 CCDC_CCDCFG_WENLOG_AND | CCDC_CCDCFG_TRGSEL_WEN |
636 CCDC_CCDCFG_EXTRG_DISABLE | CCDC_LATCH_ON_VSYNC_DISABLE, CCDCFG);
637
638 /*
639 * Set VDHD direction to input, input type to raw input
640 * normal data polarity, do not use external WEN
641 */
642 val = (CCDC_VDHDOUT_INPUT | CCDC_RAW_IP_MODE | CCDC_DATAPOL_NORMAL |
643 CCDC_EXWEN_DISABLE);
644
645 /*
646 * Configure the vertical sync polarity (MODESET.VDPOL), horizontal
647 * sync polarity (MODESET.HDPOL), field id polarity (MODESET.FLDPOL),
648 * frame format(progressive or interlace), & pixel format (Input mode)
649 */
650 val |= (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
651 ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
652 ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
653 ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
654 ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT));
655
656 /* set pack for alaw compression */
657 if ((config_params->data_sz == CCDC_DATA_8BITS) ||
658 config_params->alaw.enable)
659 val |= CCDC_DATA_PACK_ENABLE;
660
661 /* Configure for LPF */
662 if (config_params->lpf_enable)
663 val |= (config_params->lpf_enable & CCDC_LPF_MASK) <<
664 CCDC_LPF_SHIFT;
665
666 /* Configure the data shift */
667 val |= (config_params->datasft & CCDC_DATASFT_MASK) <<
668 CCDC_DATASFT_SHIFT;
669 regw(val , MODESET);
670 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to MODESET...\n", val);
671
672 /* Configure the Median Filter threshold */
673 regw((config_params->med_filt_thres) & CCDC_MED_FILT_THRESH, MEDFILT);
674
675 /* Configure GAMMAWD register. defaur 11-2, and Mosaic cfa pattern */
676 val = CCDC_GAMMA_BITS_11_2 << CCDC_GAMMAWD_INPUT_SHIFT |
677 CCDC_CFA_MOSAIC;
678
679 /* Enable and configure aLaw register if needed */
680 if (config_params->alaw.enable) {
681 val |= (CCDC_ALAW_ENABLE |
682 ((config_params->alaw.gama_wd &
683 CCDC_ALAW_GAMA_WD_MASK) <<
684 CCDC_GAMMAWD_INPUT_SHIFT));
685 }
686
687 /* Configure Median filter1 & filter2 */
688 val |= ((config_params->mfilt1 << CCDC_MFILT1_SHIFT) |
689 (config_params->mfilt2 << CCDC_MFILT2_SHIFT));
690
691 regw(val, GAMMAWD);
692 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to GAMMAWD...\n", val);
693
694 /* configure video window */
695 ccdc_setwin(&params->win, params->frm_fmt, 1);
696
697 /* Optical Clamp Averaging */
698 ccdc_config_black_clamp(&config_params->blk_clamp);
699
700 /* Black level compensation */
701 ccdc_config_black_compense(&config_params->blk_comp);
702
703 /* Vertical Defect Correction if needed */
704 if (ccdc_config_vdfc(&config_params->vertical_dft) < 0)
705 return -EFAULT;
706
707 /* color space conversion */
708 ccdc_config_csc(&config_params->csc);
709
710 /* color pattern */
711 ccdc_config_color_patterns(&config_params->col_pat_field0,
712 &config_params->col_pat_field1);
713
714 /* Configure the Gain & offset control */
715 ccdc_config_gain_offset();
716
717 dev_dbg(ccdc_cfg.dev, "\nWriting %x to COLPTN...\n", val);
718
719 /* Configure DATAOFST register */
720 val = (config_params->data_offset.horz_offset & CCDC_DATAOFST_MASK) <<
721 CCDC_DATAOFST_H_SHIFT;
722 val |= (config_params->data_offset.vert_offset & CCDC_DATAOFST_MASK) <<
723 CCDC_DATAOFST_V_SHIFT;
724 regw(val, DATAOFST);
725
726 /* configuring HSIZE register */
727 val = (params->horz_flip_enable & CCDC_HSIZE_FLIP_MASK) <<
728 CCDC_HSIZE_FLIP_SHIFT;
729
730 /* If pack 8 is enable then 1 pixel will take 1 byte */
731 if ((config_params->data_sz == CCDC_DATA_8BITS) ||
732 config_params->alaw.enable) {
733 val |= (((params->win.width) + 31) >> 5) &
734 CCDC_HSIZE_VAL_MASK;
735
736 /* adjust to multiple of 32 */
737 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n",
738 (((params->win.width) + 31) >> 5) &
739 CCDC_HSIZE_VAL_MASK);
740 } else {
741 /* else one pixel will take 2 byte */
742 val |= (((params->win.width * 2) + 31) >> 5) &
743 CCDC_HSIZE_VAL_MASK;
744
745 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to HSIZE...\n",
746 (((params->win.width * 2) + 31) >> 5) &
747 CCDC_HSIZE_VAL_MASK);
748 }
749 regw(val, HSIZE);
750
751 /* Configure SDOFST register */
752 if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
753 if (params->image_invert_enable) {
754 /* For interlace inverse mode */
755 regw(CCDC_SDOFST_INTERLACE_INVERSE, SDOFST);
756 dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n",
757 CCDC_SDOFST_INTERLACE_INVERSE);
758 } else {
759 /* For interlace non inverse mode */
760 regw(CCDC_SDOFST_INTERLACE_NORMAL, SDOFST);
761 dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n",
762 CCDC_SDOFST_INTERLACE_NORMAL);
763 }
764 } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
765 if (params->image_invert_enable) {
766 /* For progessive inverse mode */
767 regw(CCDC_SDOFST_PROGRESSIVE_INVERSE, SDOFST);
768 dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n",
769 CCDC_SDOFST_PROGRESSIVE_INVERSE);
770 } else {
771 /* For progessive non inverse mode */
772 regw(CCDC_SDOFST_PROGRESSIVE_NORMAL, SDOFST);
773 dev_dbg(ccdc_cfg.dev, "\nWriting %x to SDOFST...\n",
774 CCDC_SDOFST_PROGRESSIVE_NORMAL);
775 }
776 }
777 dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw...");
778 return 0;
779}
780
781static int ccdc_configure(void)
782{
783 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
784 return ccdc_config_raw();
785 else
786 ccdc_config_ycbcr();
787 return 0;
788}
789
790static int ccdc_set_buftype(enum ccdc_buftype buf_type)
791{
792 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
793 ccdc_cfg.bayer.buf_type = buf_type;
794 else
795 ccdc_cfg.ycbcr.buf_type = buf_type;
796 return 0;
797}
798static enum ccdc_buftype ccdc_get_buftype(void)
799{
800 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
801 return ccdc_cfg.bayer.buf_type;
802 return ccdc_cfg.ycbcr.buf_type;
803}
804
805static int ccdc_enum_pix(u32 *pix, int i)
806{
807 int ret = -EINVAL;
808 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
809 if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
810 *pix = ccdc_raw_bayer_pix_formats[i];
811 ret = 0;
812 }
813 } else {
814 if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
815 *pix = ccdc_raw_yuv_pix_formats[i];
816 ret = 0;
817 }
818 }
819 return ret;
820}
821
822static int ccdc_set_pixel_format(u32 pixfmt)
823{
824 struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw;
825
826 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
827 ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
828 if (pixfmt == V4L2_PIX_FMT_SBGGR8)
829 alaw->enable = 1;
830 else if (pixfmt != V4L2_PIX_FMT_SBGGR16)
831 return -EINVAL;
832 } else {
833 if (pixfmt == V4L2_PIX_FMT_YUYV)
834 ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
835 else if (pixfmt == V4L2_PIX_FMT_UYVY)
836 ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
837 else
838 return -EINVAL;
839 }
840 return 0;
841}
842static u32 ccdc_get_pixel_format(void)
843{
844 struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw;
845 u32 pixfmt;
846
847 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
848 if (alaw->enable)
849 pixfmt = V4L2_PIX_FMT_SBGGR8;
850 else
851 pixfmt = V4L2_PIX_FMT_SBGGR16;
852 else {
853 if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
854 pixfmt = V4L2_PIX_FMT_YUYV;
855 else
856 pixfmt = V4L2_PIX_FMT_UYVY;
857 }
858 return pixfmt;
859}
860static int ccdc_set_image_window(struct v4l2_rect *win)
861{
862 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
863 ccdc_cfg.bayer.win = *win;
864 else
865 ccdc_cfg.ycbcr.win = *win;
866 return 0;
867}
868
869static void ccdc_get_image_window(struct v4l2_rect *win)
870{
871 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
872 *win = ccdc_cfg.bayer.win;
873 else
874 *win = ccdc_cfg.ycbcr.win;
875}
876
877static unsigned int ccdc_get_line_length(void)
878{
879 struct ccdc_config_params_raw *config_params =
880 &ccdc_cfg.bayer.config_params;
881 unsigned int len;
882
883 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
884 if ((config_params->alaw.enable) ||
885 (config_params->data_sz == CCDC_DATA_8BITS))
886 len = ccdc_cfg.bayer.win.width;
887 else
888 len = ccdc_cfg.bayer.win.width * 2;
889 } else
890 len = ccdc_cfg.ycbcr.win.width * 2;
891 return ALIGN(len, 32);
892}
893
894static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
895{
896 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
897 ccdc_cfg.bayer.frm_fmt = frm_fmt;
898 else
899 ccdc_cfg.ycbcr.frm_fmt = frm_fmt;
900 return 0;
901}
902
903static enum ccdc_frmfmt ccdc_get_frame_format(void)
904{
905 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
906 return ccdc_cfg.bayer.frm_fmt;
907 else
908 return ccdc_cfg.ycbcr.frm_fmt;
909}
910
911static int ccdc_getfid(void)
912{
913 return (regr(MODESET) >> 15) & 1;
914}
915
916/* misc operations */
917static inline void ccdc_setfbaddr(unsigned long addr)
918{
919 regw((addr >> 21) & 0x007f, STADRH);
920 regw((addr >> 5) & 0x0ffff, STADRL);
921}
922
923static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
924{
925 ccdc_cfg.if_type = params->if_type;
926
927 switch (params->if_type) {
928 case VPFE_BT656:
929 case VPFE_YCBCR_SYNC_16:
930 case VPFE_YCBCR_SYNC_8:
931 ccdc_cfg.ycbcr.vd_pol = params->vdpol;
932 ccdc_cfg.ycbcr.hd_pol = params->hdpol;
933 break;
934 default:
935 /* TODO add support for raw bayer here */
936 return -EINVAL;
937 }
938 return 0;
939}
940
941static struct ccdc_hw_device ccdc_hw_dev = {
942 .name = "DM355 CCDC",
943 .owner = THIS_MODULE,
944 .hw_ops = {
945 .open = ccdc_open,
946 .close = ccdc_close,
947 .enable = ccdc_enable,
948 .enable_out_to_sdram = ccdc_enable_output_to_sdram,
949 .set_hw_if_params = ccdc_set_hw_if_params,
950 .set_params = ccdc_set_params,
951 .configure = ccdc_configure,
952 .set_buftype = ccdc_set_buftype,
953 .get_buftype = ccdc_get_buftype,
954 .enum_pix = ccdc_enum_pix,
955 .set_pixel_format = ccdc_set_pixel_format,
956 .get_pixel_format = ccdc_get_pixel_format,
957 .set_frame_format = ccdc_set_frame_format,
958 .get_frame_format = ccdc_get_frame_format,
959 .set_image_window = ccdc_set_image_window,
960 .get_image_window = ccdc_get_image_window,
961 .get_line_length = ccdc_get_line_length,
962 .setfbaddr = ccdc_setfbaddr,
963 .getfid = ccdc_getfid,
964 },
965};
966
967static int __init dm355_ccdc_probe(struct platform_device *pdev)
968{
969 void (*setup_pinmux)(void);
970 struct resource *res;
971 int status = 0;
972
973 /*
974 * first try to register with vpfe. If not correct platform, then we
975 * don't have to iomap
976 */
977 status = vpfe_register_ccdc_device(&ccdc_hw_dev);
978 if (status < 0)
979 return status;
980
981 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
982 if (!res) {
983 status = -ENODEV;
984 goto fail_nores;
985 }
986
987 res = request_mem_region(res->start, resource_size(res), res->name);
988 if (!res) {
989 status = -EBUSY;
990 goto fail_nores;
991 }
992
993 ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res));
994 if (!ccdc_cfg.base_addr) {
995 status = -ENOMEM;
996 goto fail_nomem;
997 }
998
999 /* Get and enable Master clock */
1000 ccdc_cfg.mclk = clk_get(&pdev->dev, "master");
1001 if (IS_ERR(ccdc_cfg.mclk)) {
1002 status = PTR_ERR(ccdc_cfg.mclk);
1003 goto fail_nomap;
1004 }
1005 if (clk_enable(ccdc_cfg.mclk)) {
1006 status = -ENODEV;
1007 goto fail_mclk;
1008 }
1009
1010 /* Get and enable Slave clock */
1011 ccdc_cfg.sclk = clk_get(&pdev->dev, "slave");
1012 if (IS_ERR(ccdc_cfg.sclk)) {
1013 status = PTR_ERR(ccdc_cfg.sclk);
1014 goto fail_mclk;
1015 }
1016 if (clk_enable(ccdc_cfg.sclk)) {
1017 status = -ENODEV;
1018 goto fail_sclk;
1019 }
1020
1021 /* Platform data holds setup_pinmux function ptr */
1022 if (NULL == pdev->dev.platform_data) {
1023 status = -ENODEV;
1024 goto fail_sclk;
1025 }
1026 setup_pinmux = pdev->dev.platform_data;
1027 /*
1028 * setup Mux configuration for ccdc which may be different for
1029 * different SoCs using this CCDC
1030 */
1031 setup_pinmux();
1032 ccdc_cfg.dev = &pdev->dev;
1033 printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
1034 return 0;
1035fail_sclk:
1036 clk_put(ccdc_cfg.sclk);
1037fail_mclk:
1038 clk_put(ccdc_cfg.mclk);
1039fail_nomap:
1040 iounmap(ccdc_cfg.base_addr);
1041fail_nomem:
1042 release_mem_region(res->start, resource_size(res));
1043fail_nores:
1044 vpfe_unregister_ccdc_device(&ccdc_hw_dev);
1045 return status;
1046}
1047
1048static int dm355_ccdc_remove(struct platform_device *pdev)
1049{
1050 struct resource *res;
1051
1052 clk_put(ccdc_cfg.mclk);
1053 clk_put(ccdc_cfg.sclk);
1054 iounmap(ccdc_cfg.base_addr);
1055 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1056 if (res)
1057 release_mem_region(res->start, resource_size(res));
1058 vpfe_unregister_ccdc_device(&ccdc_hw_dev);
1059 return 0;
1060}
1061
1062static struct platform_driver dm355_ccdc_driver = {
1063 .driver = {
1064 .name = "dm355_ccdc",
1065 .owner = THIS_MODULE,
1066 },
1067 .remove = __devexit_p(dm355_ccdc_remove),
1068 .probe = dm355_ccdc_probe,
1069};
1070
1071static int __init dm355_ccdc_init(void)
1072{
1073 return platform_driver_register(&dm355_ccdc_driver);
1074}
1075
1076static void __exit dm355_ccdc_exit(void)
1077{
1078 platform_driver_unregister(&dm355_ccdc_driver);
1079}
1080
1081module_init(dm355_ccdc_init);
1082module_exit(dm355_ccdc_exit);
diff --git a/drivers/media/video/davinci/dm355_ccdc_regs.h b/drivers/media/video/davinci/dm355_ccdc_regs.h
new file mode 100644
index 00000000000..d6d2ef0533b
--- /dev/null
+++ b/drivers/media/video/davinci/dm355_ccdc_regs.h
@@ -0,0 +1,310 @@
1/*
2 * Copyright (C) 2005-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _DM355_CCDC_REGS_H
19#define _DM355_CCDC_REGS_H
20
21/**************************************************************************\
22* Register OFFSET Definitions
23\**************************************************************************/
24#define SYNCEN 0x00
25#define MODESET 0x04
26#define HDWIDTH 0x08
27#define VDWIDTH 0x0c
28#define PPLN 0x10
29#define LPFR 0x14
30#define SPH 0x18
31#define NPH 0x1c
32#define SLV0 0x20
33#define SLV1 0x24
34#define NLV 0x28
35#define CULH 0x2c
36#define CULV 0x30
37#define HSIZE 0x34
38#define SDOFST 0x38
39#define STADRH 0x3c
40#define STADRL 0x40
41#define CLAMP 0x44
42#define DCSUB 0x48
43#define COLPTN 0x4c
44#define BLKCMP0 0x50
45#define BLKCMP1 0x54
46#define MEDFILT 0x58
47#define RYEGAIN 0x5c
48#define GRCYGAIN 0x60
49#define GBGGAIN 0x64
50#define BMGGAIN 0x68
51#define OFFSET 0x6c
52#define OUTCLIP 0x70
53#define VDINT0 0x74
54#define VDINT1 0x78
55#define RSV0 0x7c
56#define GAMMAWD 0x80
57#define REC656IF 0x84
58#define CCDCFG 0x88
59#define FMTCFG 0x8c
60#define FMTPLEN 0x90
61#define FMTSPH 0x94
62#define FMTLNH 0x98
63#define FMTSLV 0x9c
64#define FMTLNV 0xa0
65#define FMTRLEN 0xa4
66#define FMTHCNT 0xa8
67#define FMT_ADDR_PTR_B 0xac
68#define FMT_ADDR_PTR(i) (FMT_ADDR_PTR_B + (i * 4))
69#define FMTPGM_VF0 0xcc
70#define FMTPGM_VF1 0xd0
71#define FMTPGM_AP0 0xd4
72#define FMTPGM_AP1 0xd8
73#define FMTPGM_AP2 0xdc
74#define FMTPGM_AP3 0xe0
75#define FMTPGM_AP4 0xe4
76#define FMTPGM_AP5 0xe8
77#define FMTPGM_AP6 0xec
78#define FMTPGM_AP7 0xf0
79#define LSCCFG1 0xf4
80#define LSCCFG2 0xf8
81#define LSCH0 0xfc
82#define LSCV0 0x100
83#define LSCKH 0x104
84#define LSCKV 0x108
85#define LSCMEMCTL 0x10c
86#define LSCMEMD 0x110
87#define LSCMEMQ 0x114
88#define DFCCTL 0x118
89#define DFCVSAT 0x11c
90#define DFCMEMCTL 0x120
91#define DFCMEM0 0x124
92#define DFCMEM1 0x128
93#define DFCMEM2 0x12c
94#define DFCMEM3 0x130
95#define DFCMEM4 0x134
96#define CSCCTL 0x138
97#define CSCM0 0x13c
98#define CSCM1 0x140
99#define CSCM2 0x144
100#define CSCM3 0x148
101#define CSCM4 0x14c
102#define CSCM5 0x150
103#define CSCM6 0x154
104#define CSCM7 0x158
105#define DATAOFST 0x15c
106#define CCDC_REG_LAST DATAOFST
107/**************************************************************
108* Define for various register bit mask and shifts for CCDC
109*
110**************************************************************/
111#define CCDC_RAW_IP_MODE 0
112#define CCDC_VDHDOUT_INPUT 0
113#define CCDC_YCINSWP_RAW (0 << 4)
114#define CCDC_EXWEN_DISABLE 0
115#define CCDC_DATAPOL_NORMAL 0
116#define CCDC_CCDCFG_FIDMD_LATCH_VSYNC 0
117#define CCDC_CCDCFG_FIDMD_NO_LATCH_VSYNC (1 << 6)
118#define CCDC_CCDCFG_WENLOG_AND 0
119#define CCDC_CCDCFG_TRGSEL_WEN 0
120#define CCDC_CCDCFG_EXTRG_DISABLE 0
121#define CCDC_CFA_MOSAIC 0
122#define CCDC_Y8POS_SHIFT 11
123
124#define CCDC_VDC_DFCVSAT_MASK 0x3fff
125#define CCDC_DATAOFST_MASK 0x0ff
126#define CCDC_DATAOFST_H_SHIFT 0
127#define CCDC_DATAOFST_V_SHIFT 8
128#define CCDC_GAMMAWD_CFA_MASK 1
129#define CCDC_GAMMAWD_CFA_SHIFT 5
130#define CCDC_GAMMAWD_INPUT_SHIFT 2
131#define CCDC_FID_POL_MASK 1
132#define CCDC_FID_POL_SHIFT 4
133#define CCDC_HD_POL_MASK 1
134#define CCDC_HD_POL_SHIFT 3
135#define CCDC_VD_POL_MASK 1
136#define CCDC_VD_POL_SHIFT 2
137#define CCDC_VD_POL_NEGATIVE (1 << 2)
138#define CCDC_FRM_FMT_MASK 1
139#define CCDC_FRM_FMT_SHIFT 7
140#define CCDC_DATA_SZ_MASK 7
141#define CCDC_DATA_SZ_SHIFT 8
142#define CCDC_VDHDOUT_MASK 1
143#define CCDC_VDHDOUT_SHIFT 0
144#define CCDC_EXWEN_MASK 1
145#define CCDC_EXWEN_SHIFT 5
146#define CCDC_INPUT_MODE_MASK 3
147#define CCDC_INPUT_MODE_SHIFT 12
148#define CCDC_PIX_FMT_MASK 3
149#define CCDC_PIX_FMT_SHIFT 12
150#define CCDC_DATAPOL_MASK 1
151#define CCDC_DATAPOL_SHIFT 6
152#define CCDC_WEN_ENABLE (1 << 1)
153#define CCDC_VDHDEN_ENABLE (1 << 16)
154#define CCDC_LPF_ENABLE (1 << 14)
155#define CCDC_ALAW_ENABLE 1
156#define CCDC_ALAW_GAMA_WD_MASK 7
157#define CCDC_REC656IF_BT656_EN 3
158
159#define CCDC_FMTCFG_FMTMODE_MASK 3
160#define CCDC_FMTCFG_FMTMODE_SHIFT 1
161#define CCDC_FMTCFG_LNUM_MASK 3
162#define CCDC_FMTCFG_LNUM_SHIFT 4
163#define CCDC_FMTCFG_ADDRINC_MASK 7
164#define CCDC_FMTCFG_ADDRINC_SHIFT 8
165
166#define CCDC_CCDCFG_FIDMD_SHIFT 6
167#define CCDC_CCDCFG_WENLOG_SHIFT 8
168#define CCDC_CCDCFG_TRGSEL_SHIFT 9
169#define CCDC_CCDCFG_EXTRG_SHIFT 10
170#define CCDC_CCDCFG_MSBINVI_SHIFT 13
171
172#define CCDC_HSIZE_FLIP_SHIFT 12
173#define CCDC_HSIZE_FLIP_MASK 1
174#define CCDC_HSIZE_VAL_MASK 0xFFF
175#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249
176#define CCDC_SDOFST_INTERLACE_INVERSE 0x4B6D
177#define CCDC_SDOFST_INTERLACE_NORMAL 0x0B6D
178#define CCDC_SDOFST_PROGRESSIVE_INVERSE 0x4000
179#define CCDC_SDOFST_PROGRESSIVE_NORMAL 0
180#define CCDC_START_PX_HOR_MASK 0x7FFF
181#define CCDC_NUM_PX_HOR_MASK 0x7FFF
182#define CCDC_START_VER_ONE_MASK 0x7FFF
183#define CCDC_START_VER_TWO_MASK 0x7FFF
184#define CCDC_NUM_LINES_VER 0x7FFF
185
186#define CCDC_BLK_CLAMP_ENABLE (1 << 15)
187#define CCDC_BLK_SGAIN_MASK 0x1F
188#define CCDC_BLK_ST_PXL_MASK 0x1FFF
189#define CCDC_BLK_SAMPLE_LN_MASK 3
190#define CCDC_BLK_SAMPLE_LN_SHIFT 13
191
192#define CCDC_NUM_LINE_CALC_MASK 3
193#define CCDC_NUM_LINE_CALC_SHIFT 14
194
195#define CCDC_BLK_DC_SUB_MASK 0x3FFF
196#define CCDC_BLK_COMP_MASK 0xFF
197#define CCDC_BLK_COMP_GB_COMP_SHIFT 8
198#define CCDC_BLK_COMP_GR_COMP_SHIFT 0
199#define CCDC_BLK_COMP_R_COMP_SHIFT 8
200#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15)
201#define CCDC_LATCH_ON_VSYNC_ENABLE (0 << 15)
202#define CCDC_FPC_ENABLE (1 << 15)
203#define CCDC_FPC_FPC_NUM_MASK 0x7FFF
204#define CCDC_DATA_PACK_ENABLE (1 << 11)
205#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
206#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF
207#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16
208#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
209#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF
210#define CCDC_FMT_VERT_FMTSLV_SHIFT 16
211#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF
212#define CCDC_VP_OUT_VERT_NUM_SHIFT 17
213#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF
214#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4
215#define CCDC_VP_OUT_HORZ_ST_MASK 0xF
216
217#define CCDC_CSC_COEF_INTEG_MASK 7
218#define CCDC_CSC_COEF_DECIMAL_MASK 0x1f
219#define CCDC_CSC_COEF_INTEG_SHIFT 5
220#define CCDC_CSCM_MSB_SHIFT 8
221#define CCDC_CSC_ENABLE 1
222#define CCDC_CSC_DEC_MAX 32
223
224#define CCDC_MFILT1_SHIFT 10
225#define CCDC_MFILT2_SHIFT 8
226#define CCDC_MED_FILT_THRESH 0x3FFF
227#define CCDC_LPF_MASK 1
228#define CCDC_LPF_SHIFT 14
229#define CCDC_OFFSET_MASK 0x3FF
230#define CCDC_DATASFT_MASK 7
231#define CCDC_DATASFT_SHIFT 8
232
233#define CCDC_DF_ENABLE 1
234
235#define CCDC_FMTPLEN_P0_MASK 0xF
236#define CCDC_FMTPLEN_P1_MASK 0xF
237#define CCDC_FMTPLEN_P2_MASK 7
238#define CCDC_FMTPLEN_P3_MASK 7
239#define CCDC_FMTPLEN_P0_SHIFT 0
240#define CCDC_FMTPLEN_P1_SHIFT 4
241#define CCDC_FMTPLEN_P2_SHIFT 8
242#define CCDC_FMTPLEN_P3_SHIFT 12
243
244#define CCDC_FMTSPH_MASK 0x1FFF
245#define CCDC_FMTLNH_MASK 0x1FFF
246#define CCDC_FMTSLV_MASK 0x1FFF
247#define CCDC_FMTLNV_MASK 0x7FFF
248#define CCDC_FMTRLEN_MASK 0x1FFF
249#define CCDC_FMTHCNT_MASK 0x1FFF
250
251#define CCDC_ADP_INIT_MASK 0x1FFF
252#define CCDC_ADP_LINE_SHIFT 13
253#define CCDC_ADP_LINE_MASK 3
254#define CCDC_FMTPGN_APTR_MASK 7
255
256#define CCDC_DFCCTL_GDFCEN_MASK 1
257#define CCDC_DFCCTL_VDFCEN_MASK 1
258#define CCDC_DFCCTL_VDFC_DISABLE (0 << 4)
259#define CCDC_DFCCTL_VDFCEN_SHIFT 4
260#define CCDC_DFCCTL_VDFCSL_MASK 3
261#define CCDC_DFCCTL_VDFCSL_SHIFT 5
262#define CCDC_DFCCTL_VDFCUDA_MASK 1
263#define CCDC_DFCCTL_VDFCUDA_SHIFT 7
264#define CCDC_DFCCTL_VDFLSFT_MASK 3
265#define CCDC_DFCCTL_VDFLSFT_SHIFT 8
266#define CCDC_DFCMEMCTL_DFCMARST_MASK 1
267#define CCDC_DFCMEMCTL_DFCMARST_SHIFT 2
268#define CCDC_DFCMEMCTL_DFCMWR_MASK 1
269#define CCDC_DFCMEMCTL_DFCMWR_SHIFT 0
270#define CCDC_DFCMEMCTL_INC_ADDR (0 << 2)
271
272#define CCDC_LSCCFG_GFTSF_MASK 7
273#define CCDC_LSCCFG_GFTSF_SHIFT 1
274#define CCDC_LSCCFG_GFTINV_MASK 0xf
275#define CCDC_LSCCFG_GFTINV_SHIFT 4
276#define CCDC_LSC_GFTABLE_SEL_MASK 3
277#define CCDC_LSC_GFTABLE_EPEL_SHIFT 8
278#define CCDC_LSC_GFTABLE_OPEL_SHIFT 10
279#define CCDC_LSC_GFTABLE_EPOL_SHIFT 12
280#define CCDC_LSC_GFTABLE_OPOL_SHIFT 14
281#define CCDC_LSC_GFMODE_MASK 3
282#define CCDC_LSC_GFMODE_SHIFT 4
283#define CCDC_LSC_DISABLE 0
284#define CCDC_LSC_ENABLE 1
285#define CCDC_LSC_TABLE1_SLC 0
286#define CCDC_LSC_TABLE2_SLC 1
287#define CCDC_LSC_TABLE3_SLC 2
288#define CCDC_LSC_MEMADDR_RESET (1 << 2)
289#define CCDC_LSC_MEMADDR_INCR (0 << 2)
290#define CCDC_LSC_FRAC_MASK_T1 0xFF
291#define CCDC_LSC_INT_MASK 3
292#define CCDC_LSC_FRAC_MASK 0x3FFF
293#define CCDC_LSC_CENTRE_MASK 0x3FFF
294#define CCDC_LSC_COEF_MASK 0xff
295#define CCDC_LSC_COEFL_SHIFT 0
296#define CCDC_LSC_COEFU_SHIFT 8
297#define CCDC_GAIN_MASK 0x7FF
298#define CCDC_SYNCEN_VDHDEN_MASK (1 << 0)
299#define CCDC_SYNCEN_WEN_MASK (1 << 1)
300#define CCDC_SYNCEN_WEN_SHIFT 1
301
302/* Power on Defaults in hardware */
303#define MODESET_DEFAULT 0x200
304#define CULH_DEFAULT 0xFFFF
305#define CULV_DEFAULT 0xFF
306#define GAIN_DEFAULT 256
307#define OUTCLIP_DEFAULT 0x3FFF
308#define LSCCFG2_DEFAULT 0xE
309
310#endif
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c
new file mode 100644
index 00000000000..c8b32c1c738
--- /dev/null
+++ b/drivers/media/video/davinci/dm644x_ccdc.c
@@ -0,0 +1,1091 @@
1/*
2 * Copyright (C) 2006-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * CCDC hardware module for DM6446
19 * ------------------------------
20 *
21 * This module is for configuring CCD controller of DM6446 VPFE to capture
22 * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules
23 * such as Defect Pixel Correction, Color Space Conversion etc to
24 * pre-process the Raw Bayer RGB data, before writing it to SDRAM. This
25 * module also allows application to configure individual
26 * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL.
27 * To do so, application includes dm644x_ccdc.h and vpfe_capture.h header
28 * files. The setparams() API is called by vpfe_capture driver
29 * to configure module parameters. This file is named DM644x so that other
30 * variants such DM6443 may be supported using the same module.
31 *
32 * TODO: Test Raw bayer parameter settings and bayer capture
33 * Split module parameter structure to module specific ioctl structs
34 * investigate if enum used for user space type definition
35 * to be replaced by #defines or integer
36 */
37#include <linux/platform_device.h>
38#include <linux/uaccess.h>
39#include <linux/videodev2.h>
40#include <linux/gfp.h>
41#include <linux/clk.h>
42#include <linux/err.h>
43
44#include <media/davinci/dm644x_ccdc.h>
45#include <media/davinci/vpss.h>
46
47#include "dm644x_ccdc_regs.h"
48#include "ccdc_hw_device.h"
49
50MODULE_LICENSE("GPL");
51MODULE_DESCRIPTION("CCDC Driver for DM6446");
52MODULE_AUTHOR("Texas Instruments");
53
54static struct ccdc_oper_config {
55 struct device *dev;
56 /* CCDC interface type */
57 enum vpfe_hw_if_type if_type;
58 /* Raw Bayer configuration */
59 struct ccdc_params_raw bayer;
60 /* YCbCr configuration */
61 struct ccdc_params_ycbcr ycbcr;
62 /* Master clock */
63 struct clk *mclk;
64 /* slave clock */
65 struct clk *sclk;
66 /* ccdc base address */
67 void __iomem *base_addr;
68} ccdc_cfg = {
69 /* Raw configurations */
70 .bayer = {
71 .pix_fmt = CCDC_PIXFMT_RAW,
72 .frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
73 .win = CCDC_WIN_VGA,
74 .fid_pol = VPFE_PINPOL_POSITIVE,
75 .vd_pol = VPFE_PINPOL_POSITIVE,
76 .hd_pol = VPFE_PINPOL_POSITIVE,
77 .config_params = {
78 .data_sz = CCDC_DATA_10BITS,
79 },
80 },
81 .ycbcr = {
82 .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
83 .frm_fmt = CCDC_FRMFMT_INTERLACED,
84 .win = CCDC_WIN_PAL,
85 .fid_pol = VPFE_PINPOL_POSITIVE,
86 .vd_pol = VPFE_PINPOL_POSITIVE,
87 .hd_pol = VPFE_PINPOL_POSITIVE,
88 .bt656_enable = 1,
89 .pix_order = CCDC_PIXORDER_CBYCRY,
90 .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
91 },
92};
93
94#define CCDC_MAX_RAW_YUV_FORMATS 2
95
96/* Raw Bayer formats */
97static u32 ccdc_raw_bayer_pix_formats[] =
98 {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
99
100/* Raw YUV formats */
101static u32 ccdc_raw_yuv_pix_formats[] =
102 {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
103
104/* CCDC Save/Restore context */
105static u32 ccdc_ctx[CCDC_REG_END / sizeof(u32)];
106
107/* register access routines */
108static inline u32 regr(u32 offset)
109{
110 return __raw_readl(ccdc_cfg.base_addr + offset);
111}
112
113static inline void regw(u32 val, u32 offset)
114{
115 __raw_writel(val, ccdc_cfg.base_addr + offset);
116}
117
118static void ccdc_enable(int flag)
119{
120 regw(flag, CCDC_PCR);
121}
122
123static void ccdc_enable_vport(int flag)
124{
125 if (flag)
126 /* enable video port */
127 regw(CCDC_ENABLE_VIDEO_PORT, CCDC_FMTCFG);
128 else
129 regw(CCDC_DISABLE_VIDEO_PORT, CCDC_FMTCFG);
130}
131
132/*
133 * ccdc_setwin()
134 * This function will configure the window size
135 * to be capture in CCDC reg
136 */
137void ccdc_setwin(struct v4l2_rect *image_win,
138 enum ccdc_frmfmt frm_fmt,
139 int ppc)
140{
141 int horz_start, horz_nr_pixels;
142 int vert_start, vert_nr_lines;
143 int val = 0, mid_img = 0;
144
145 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin...");
146 /*
147 * ppc - per pixel count. indicates how many pixels per cell
148 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
149 * raw capture this is 1
150 */
151 horz_start = image_win->left << (ppc - 1);
152 horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
153 regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels,
154 CCDC_HORZ_INFO);
155
156 vert_start = image_win->top;
157
158 if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
159 vert_nr_lines = (image_win->height >> 1) - 1;
160 vert_start >>= 1;
161 /* Since first line doesn't have any data */
162 vert_start += 1;
163 /* configure VDINT0 */
164 val = (vert_start << CCDC_VDINT_VDINT0_SHIFT);
165 regw(val, CCDC_VDINT);
166
167 } else {
168 /* Since first line doesn't have any data */
169 vert_start += 1;
170 vert_nr_lines = image_win->height - 1;
171 /*
172 * configure VDINT0 and VDINT1. VDINT1 will be at half
173 * of image height
174 */
175 mid_img = vert_start + (image_win->height / 2);
176 val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) |
177 (mid_img & CCDC_VDINT_VDINT1_MASK);
178 regw(val, CCDC_VDINT);
179
180 }
181 regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start,
182 CCDC_VERT_START);
183 regw(vert_nr_lines, CCDC_VERT_LINES);
184 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin...");
185}
186
187static void ccdc_readregs(void)
188{
189 unsigned int val = 0;
190
191 val = regr(CCDC_ALAW);
192 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to ALAW...\n", val);
193 val = regr(CCDC_CLAMP);
194 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to CLAMP...\n", val);
195 val = regr(CCDC_DCSUB);
196 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to DCSUB...\n", val);
197 val = regr(CCDC_BLKCMP);
198 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to BLKCMP...\n", val);
199 val = regr(CCDC_FPC_ADDR);
200 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC_ADDR...\n", val);
201 val = regr(CCDC_FPC);
202 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC...\n", val);
203 val = regr(CCDC_FMTCFG);
204 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMTCFG...\n", val);
205 val = regr(CCDC_COLPTN);
206 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to COLPTN...\n", val);
207 val = regr(CCDC_FMT_HORZ);
208 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_HORZ...\n", val);
209 val = regr(CCDC_FMT_VERT);
210 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_VERT...\n", val);
211 val = regr(CCDC_HSIZE_OFF);
212 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HSIZE_OFF...\n", val);
213 val = regr(CCDC_SDOFST);
214 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SDOFST...\n", val);
215 val = regr(CCDC_VP_OUT);
216 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VP_OUT...\n", val);
217 val = regr(CCDC_SYN_MODE);
218 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SYN_MODE...\n", val);
219 val = regr(CCDC_HORZ_INFO);
220 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HORZ_INFO...\n", val);
221 val = regr(CCDC_VERT_START);
222 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_START...\n", val);
223 val = regr(CCDC_VERT_LINES);
224 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val);
225}
226
227static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
228{
229 if (ccdcparam->alaw.enable) {
230 if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) ||
231 (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) ||
232 (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) {
233 dev_dbg(ccdc_cfg.dev, "\nInvalid data line select");
234 return -1;
235 }
236 }
237 return 0;
238}
239
240static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params)
241{
242 struct ccdc_config_params_raw *config_params =
243 &ccdc_cfg.bayer.config_params;
244 unsigned int *fpc_virtaddr = NULL;
245 unsigned int *fpc_physaddr = NULL;
246
247 memcpy(config_params, raw_params, sizeof(*raw_params));
248 /*
249 * allocate memory for fault pixel table and copy the user
250 * values to the table
251 */
252 if (!config_params->fault_pxl.enable)
253 return 0;
254
255 fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr;
256 fpc_virtaddr = (unsigned int *)phys_to_virt(
257 (unsigned long)fpc_physaddr);
258 /*
259 * Allocate memory for FPC table if current
260 * FPC table buffer is not big enough to
261 * accommodate FPC Number requested
262 */
263 if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) {
264 if (fpc_physaddr != NULL) {
265 free_pages((unsigned long)fpc_physaddr,
266 get_order
267 (config_params->fault_pxl.fp_num *
268 FP_NUM_BYTES));
269 }
270
271 /* Allocate memory for FPC table */
272 fpc_virtaddr =
273 (unsigned int *)__get_free_pages(GFP_KERNEL | GFP_DMA,
274 get_order(raw_params->
275 fault_pxl.fp_num *
276 FP_NUM_BYTES));
277
278 if (fpc_virtaddr == NULL) {
279 dev_dbg(ccdc_cfg.dev,
280 "\nUnable to allocate memory for FPC");
281 return -EFAULT;
282 }
283 fpc_physaddr =
284 (unsigned int *)virt_to_phys((void *)fpc_virtaddr);
285 }
286
287 /* Copy number of fault pixels and FPC table */
288 config_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num;
289 if (copy_from_user(fpc_virtaddr,
290 (void __user *)raw_params->fault_pxl.fpc_table_addr,
291 config_params->fault_pxl.fp_num * FP_NUM_BYTES)) {
292 dev_dbg(ccdc_cfg.dev, "\n copy_from_user failed");
293 return -EFAULT;
294 }
295 config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr;
296 return 0;
297}
298
299static int ccdc_close(struct device *dev)
300{
301 struct ccdc_config_params_raw *config_params =
302 &ccdc_cfg.bayer.config_params;
303 unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL;
304
305 fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr;
306
307 if (fpc_physaddr != NULL) {
308 fpc_virtaddr = (unsigned int *)
309 phys_to_virt((unsigned long)fpc_physaddr);
310 free_pages((unsigned long)fpc_virtaddr,
311 get_order(config_params->fault_pxl.fp_num *
312 FP_NUM_BYTES));
313 }
314 return 0;
315}
316
317/*
318 * ccdc_restore_defaults()
319 * This function will write defaults to all CCDC registers
320 */
321static void ccdc_restore_defaults(void)
322{
323 int i;
324
325 /* disable CCDC */
326 ccdc_enable(0);
327 /* set all registers to default value */
328 for (i = 4; i <= 0x94; i += 4)
329 regw(0, i);
330 regw(CCDC_NO_CULLING, CCDC_CULLING);
331 regw(CCDC_GAMMA_BITS_11_2, CCDC_ALAW);
332}
333
334static int ccdc_open(struct device *device)
335{
336 ccdc_restore_defaults();
337 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
338 ccdc_enable_vport(1);
339 return 0;
340}
341
342static void ccdc_sbl_reset(void)
343{
344 vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O);
345}
346
347/* Parameter operations */
348static int ccdc_set_params(void __user *params)
349{
350 struct ccdc_config_params_raw ccdc_raw_params;
351 int x;
352
353 if (ccdc_cfg.if_type != VPFE_RAW_BAYER)
354 return -EINVAL;
355
356 x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
357 if (x) {
358 dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying"
359 "ccdc params, %d\n", x);
360 return -EFAULT;
361 }
362
363 if (!validate_ccdc_param(&ccdc_raw_params)) {
364 if (!ccdc_update_raw_params(&ccdc_raw_params))
365 return 0;
366 }
367 return -EINVAL;
368}
369
370/*
371 * ccdc_config_ycbcr()
372 * This function will configure CCDC for YCbCr video capture
373 */
374void ccdc_config_ycbcr(void)
375{
376 struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr;
377 u32 syn_mode;
378
379 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr...");
380 /*
381 * first restore the CCDC registers to default values
382 * This is important since we assume default values to be set in
383 * a lot of registers that we didn't touch
384 */
385 ccdc_restore_defaults();
386
387 /*
388 * configure pixel format, frame format, configure video frame
389 * format, enable output to SDRAM, enable internal timing generator
390 * and 8bit pack mode
391 */
392 syn_mode = (((params->pix_fmt & CCDC_SYN_MODE_INPMOD_MASK) <<
393 CCDC_SYN_MODE_INPMOD_SHIFT) |
394 ((params->frm_fmt & CCDC_SYN_FLDMODE_MASK) <<
395 CCDC_SYN_FLDMODE_SHIFT) | CCDC_VDHDEN_ENABLE |
396 CCDC_WEN_ENABLE | CCDC_DATA_PACK_ENABLE);
397
398 /* setup BT.656 sync mode */
399 if (params->bt656_enable) {
400 regw(CCDC_REC656IF_BT656_EN, CCDC_REC656IF);
401
402 /*
403 * configure the FID, VD, HD pin polarity,
404 * fld,hd pol positive, vd negative, 8-bit data
405 */
406 syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE;
407 if (ccdc_cfg.if_type == VPFE_BT656_10BIT)
408 syn_mode |= CCDC_SYN_MODE_10BITS;
409 else
410 syn_mode |= CCDC_SYN_MODE_8BITS;
411 } else {
412 /* y/c external sync mode */
413 syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) <<
414 CCDC_FID_POL_SHIFT) |
415 ((params->hd_pol & CCDC_HD_POL_MASK) <<
416 CCDC_HD_POL_SHIFT) |
417 ((params->vd_pol & CCDC_VD_POL_MASK) <<
418 CCDC_VD_POL_SHIFT));
419 }
420 regw(syn_mode, CCDC_SYN_MODE);
421
422 /* configure video window */
423 ccdc_setwin(&params->win, params->frm_fmt, 2);
424
425 /*
426 * configure the order of y cb cr in SDRAM, and disable latch
427 * internal register on vsync
428 */
429 if (ccdc_cfg.if_type == VPFE_BT656_10BIT)
430 regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) |
431 CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_BW656_10BIT,
432 CCDC_CCDCFG);
433 else
434 regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) |
435 CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
436
437 /*
438 * configure the horizontal line offset. This should be a
439 * on 32 byte boundary. So clear LSB 5 bits
440 */
441 regw(((params->win.width * 2 + 31) & ~0x1f), CCDC_HSIZE_OFF);
442
443 /* configure the memory line offset */
444 if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
445 /* two fields are interleaved in memory */
446 regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST);
447
448 ccdc_sbl_reset();
449 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n");
450}
451
452static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp)
453{
454 u32 val;
455
456 if (!bclamp->enable) {
457 /* configure DCSub */
458 val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK;
459 regw(val, CCDC_DCSUB);
460 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to DCSUB...\n", val);
461 regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP);
462 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to CLAMP...\n");
463 return;
464 }
465 /*
466 * Configure gain, Start pixel, No of line to be avg,
467 * No of pixel/line to be avg, & Enable the Black clamping
468 */
469 val = ((bclamp->sgain & CCDC_BLK_SGAIN_MASK) |
470 ((bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) <<
471 CCDC_BLK_ST_PXL_SHIFT) |
472 ((bclamp->sample_ln & CCDC_BLK_SAMPLE_LINE_MASK) <<
473 CCDC_BLK_SAMPLE_LINE_SHIFT) |
474 ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) <<
475 CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE);
476 regw(val, CCDC_CLAMP);
477 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to CLAMP...\n", val);
478 /* If Black clamping is enable then make dcsub 0 */
479 regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB);
480 dev_dbg(ccdc_cfg.dev, "\nWriting 0x00000000 to DCSUB...\n");
481}
482
483static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp)
484{
485 u32 val;
486
487 val = ((bcomp->b & CCDC_BLK_COMP_MASK) |
488 ((bcomp->gb & CCDC_BLK_COMP_MASK) <<
489 CCDC_BLK_COMP_GB_COMP_SHIFT) |
490 ((bcomp->gr & CCDC_BLK_COMP_MASK) <<
491 CCDC_BLK_COMP_GR_COMP_SHIFT) |
492 ((bcomp->r & CCDC_BLK_COMP_MASK) <<
493 CCDC_BLK_COMP_R_COMP_SHIFT));
494 regw(val, CCDC_BLKCMP);
495}
496
497static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc)
498{
499 u32 val;
500
501 /* Initially disable FPC */
502 val = CCDC_FPC_DISABLE;
503 regw(val, CCDC_FPC);
504
505 if (!fpc->enable)
506 return;
507
508 /* Configure Fault pixel if needed */
509 regw(fpc->fpc_table_addr, CCDC_FPC_ADDR);
510 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC_ADDR...\n",
511 (fpc->fpc_table_addr));
512 /* Write the FPC params with FPC disable */
513 val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK;
514 regw(val, CCDC_FPC);
515
516 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val);
517 /* read the FPC register */
518 val = regr(CCDC_FPC) | CCDC_FPC_ENABLE;
519 regw(val, CCDC_FPC);
520 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val);
521}
522
523/*
524 * ccdc_config_raw()
525 * This function will configure CCDC for Raw capture mode
526 */
527void ccdc_config_raw(void)
528{
529 struct ccdc_params_raw *params = &ccdc_cfg.bayer;
530 struct ccdc_config_params_raw *config_params =
531 &ccdc_cfg.bayer.config_params;
532 unsigned int syn_mode = 0;
533 unsigned int val;
534
535 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw...");
536
537 /* Reset CCDC */
538 ccdc_restore_defaults();
539
540 /* Disable latching function registers on VSYNC */
541 regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
542
543 /*
544 * Configure the vertical sync polarity(SYN_MODE.VDPOL),
545 * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity
546 * (SYN_MODE.FLDPOL), frame format(progressive or interlace),
547 * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output
548 * SDRAM, enable internal timing generator
549 */
550 syn_mode =
551 (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
552 ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
553 ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
554 ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
555 ((config_params->data_sz & CCDC_DATA_SZ_MASK) <<
556 CCDC_DATA_SZ_SHIFT) |
557 ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT) |
558 CCDC_WEN_ENABLE | CCDC_VDHDEN_ENABLE);
559
560 /* Enable and configure aLaw register if needed */
561 if (config_params->alaw.enable) {
562 val = ((config_params->alaw.gama_wd &
563 CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE);
564 regw(val, CCDC_ALAW);
565 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val);
566 }
567
568 /* Configure video window */
569 ccdc_setwin(&params->win, params->frm_fmt, CCDC_PPC_RAW);
570
571 /* Configure Black Clamp */
572 ccdc_config_black_clamp(&config_params->blk_clamp);
573
574 /* Configure Black level compensation */
575 ccdc_config_black_compense(&config_params->blk_comp);
576
577 /* Configure Fault Pixel Correction */
578 ccdc_config_fpc(&config_params->fault_pxl);
579
580 /* If data size is 8 bit then pack the data */
581 if ((config_params->data_sz == CCDC_DATA_8BITS) ||
582 config_params->alaw.enable)
583 syn_mode |= CCDC_DATA_PACK_ENABLE;
584
585#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE
586 /* enable video port */
587 val = CCDC_ENABLE_VIDEO_PORT;
588#else
589 /* disable video port */
590 val = CCDC_DISABLE_VIDEO_PORT;
591#endif
592
593 if (config_params->data_sz == CCDC_DATA_8BITS)
594 val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
595 << CCDC_FMTCFG_VPIN_SHIFT;
596 else
597 val |= (config_params->data_sz & CCDC_FMTCFG_VPIN_MASK)
598 << CCDC_FMTCFG_VPIN_SHIFT;
599 /* Write value in FMTCFG */
600 regw(val, CCDC_FMTCFG);
601
602 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMTCFG...\n", val);
603 /* Configure the color pattern according to mt9t001 sensor */
604 regw(CCDC_COLPTN_VAL, CCDC_COLPTN);
605
606 dev_dbg(ccdc_cfg.dev, "\nWriting 0xBB11BB11 to COLPTN...\n");
607 /*
608 * Configure Data formatter(Video port) pixel selection
609 * (FMT_HORZ, FMT_VERT)
610 */
611 val = ((params->win.left & CCDC_FMT_HORZ_FMTSPH_MASK) <<
612 CCDC_FMT_HORZ_FMTSPH_SHIFT) |
613 (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK);
614 regw(val, CCDC_FMT_HORZ);
615
616 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_HORZ...\n", val);
617 val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK)
618 << CCDC_FMT_VERT_FMTSLV_SHIFT;
619 if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
620 val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK;
621 else
622 val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK;
623
624 dev_dbg(ccdc_cfg.dev, "\nparams->win.height 0x%x ...\n",
625 params->win.height);
626 regw(val, CCDC_FMT_VERT);
627
628 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_VERT...\n", val);
629
630 dev_dbg(ccdc_cfg.dev, "\nbelow regw(val, FMT_VERT)...");
631
632 /*
633 * Configure Horizontal offset register. If pack 8 is enabled then
634 * 1 pixel will take 1 byte
635 */
636 if ((config_params->data_sz == CCDC_DATA_8BITS) ||
637 config_params->alaw.enable)
638 regw((params->win.width + CCDC_32BYTE_ALIGN_VAL) &
639 CCDC_HSIZE_OFF_MASK, CCDC_HSIZE_OFF);
640 else
641 /* else one pixel will take 2 byte */
642 regw(((params->win.width * CCDC_TWO_BYTES_PER_PIXEL) +
643 CCDC_32BYTE_ALIGN_VAL) & CCDC_HSIZE_OFF_MASK,
644 CCDC_HSIZE_OFF);
645
646 /* Set value for SDOFST */
647 if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
648 if (params->image_invert_enable) {
649 /* For intelace inverse mode */
650 regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST);
651 dev_dbg(ccdc_cfg.dev, "\nWriting 0x4B6D to SDOFST..\n");
652 }
653
654 else {
655 /* For intelace non inverse mode */
656 regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST);
657 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0249 to SDOFST..\n");
658 }
659 } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
660 regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST);
661 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to SDOFST...\n");
662 }
663
664 /*
665 * Configure video port pixel selection (VPOUT)
666 * Here -1 is to make the height value less than FMT_VERT.FMTLNV
667 */
668 if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
669 val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK))
670 << CCDC_VP_OUT_VERT_NUM_SHIFT;
671 else
672 val =
673 ((((params->win.height >> CCDC_INTERLACED_HEIGHT_SHIFT) -
674 1) & CCDC_VP_OUT_VERT_NUM_MASK)) <<
675 CCDC_VP_OUT_VERT_NUM_SHIFT;
676
677 val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK)
678 << CCDC_VP_OUT_HORZ_NUM_SHIFT;
679 val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK;
680 regw(val, CCDC_VP_OUT);
681
682 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to VP_OUT...\n", val);
683 regw(syn_mode, CCDC_SYN_MODE);
684 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode);
685
686 ccdc_sbl_reset();
687 dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw...");
688 ccdc_readregs();
689}
690
691static int ccdc_configure(void)
692{
693 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
694 ccdc_config_raw();
695 else
696 ccdc_config_ycbcr();
697 return 0;
698}
699
700static int ccdc_set_buftype(enum ccdc_buftype buf_type)
701{
702 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
703 ccdc_cfg.bayer.buf_type = buf_type;
704 else
705 ccdc_cfg.ycbcr.buf_type = buf_type;
706 return 0;
707}
708
709static enum ccdc_buftype ccdc_get_buftype(void)
710{
711 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
712 return ccdc_cfg.bayer.buf_type;
713 return ccdc_cfg.ycbcr.buf_type;
714}
715
716static int ccdc_enum_pix(u32 *pix, int i)
717{
718 int ret = -EINVAL;
719 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
720 if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
721 *pix = ccdc_raw_bayer_pix_formats[i];
722 ret = 0;
723 }
724 } else {
725 if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
726 *pix = ccdc_raw_yuv_pix_formats[i];
727 ret = 0;
728 }
729 }
730 return ret;
731}
732
733static int ccdc_set_pixel_format(u32 pixfmt)
734{
735 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
736 ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
737 if (pixfmt == V4L2_PIX_FMT_SBGGR8)
738 ccdc_cfg.bayer.config_params.alaw.enable = 1;
739 else if (pixfmt != V4L2_PIX_FMT_SBGGR16)
740 return -EINVAL;
741 } else {
742 if (pixfmt == V4L2_PIX_FMT_YUYV)
743 ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
744 else if (pixfmt == V4L2_PIX_FMT_UYVY)
745 ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
746 else
747 return -EINVAL;
748 }
749 return 0;
750}
751
752static u32 ccdc_get_pixel_format(void)
753{
754 struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw;
755 u32 pixfmt;
756
757 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
758 if (alaw->enable)
759 pixfmt = V4L2_PIX_FMT_SBGGR8;
760 else
761 pixfmt = V4L2_PIX_FMT_SBGGR16;
762 else {
763 if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
764 pixfmt = V4L2_PIX_FMT_YUYV;
765 else
766 pixfmt = V4L2_PIX_FMT_UYVY;
767 }
768 return pixfmt;
769}
770
771static int ccdc_set_image_window(struct v4l2_rect *win)
772{
773 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
774 ccdc_cfg.bayer.win = *win;
775 else
776 ccdc_cfg.ycbcr.win = *win;
777 return 0;
778}
779
780static void ccdc_get_image_window(struct v4l2_rect *win)
781{
782 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
783 *win = ccdc_cfg.bayer.win;
784 else
785 *win = ccdc_cfg.ycbcr.win;
786}
787
788static unsigned int ccdc_get_line_length(void)
789{
790 struct ccdc_config_params_raw *config_params =
791 &ccdc_cfg.bayer.config_params;
792 unsigned int len;
793
794 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
795 if ((config_params->alaw.enable) ||
796 (config_params->data_sz == CCDC_DATA_8BITS))
797 len = ccdc_cfg.bayer.win.width;
798 else
799 len = ccdc_cfg.bayer.win.width * 2;
800 } else
801 len = ccdc_cfg.ycbcr.win.width * 2;
802 return ALIGN(len, 32);
803}
804
805static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
806{
807 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
808 ccdc_cfg.bayer.frm_fmt = frm_fmt;
809 else
810 ccdc_cfg.ycbcr.frm_fmt = frm_fmt;
811 return 0;
812}
813
814static enum ccdc_frmfmt ccdc_get_frame_format(void)
815{
816 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
817 return ccdc_cfg.bayer.frm_fmt;
818 else
819 return ccdc_cfg.ycbcr.frm_fmt;
820}
821
822static int ccdc_getfid(void)
823{
824 return (regr(CCDC_SYN_MODE) >> 15) & 1;
825}
826
827/* misc operations */
828static inline void ccdc_setfbaddr(unsigned long addr)
829{
830 regw(addr & 0xffffffe0, CCDC_SDR_ADDR);
831}
832
833static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
834{
835 ccdc_cfg.if_type = params->if_type;
836
837 switch (params->if_type) {
838 case VPFE_BT656:
839 case VPFE_YCBCR_SYNC_16:
840 case VPFE_YCBCR_SYNC_8:
841 case VPFE_BT656_10BIT:
842 ccdc_cfg.ycbcr.vd_pol = params->vdpol;
843 ccdc_cfg.ycbcr.hd_pol = params->hdpol;
844 break;
845 default:
846 /* TODO add support for raw bayer here */
847 return -EINVAL;
848 }
849 return 0;
850}
851
852static void ccdc_save_context(void)
853{
854 ccdc_ctx[CCDC_PCR >> 2] = regr(CCDC_PCR);
855 ccdc_ctx[CCDC_SYN_MODE >> 2] = regr(CCDC_SYN_MODE);
856 ccdc_ctx[CCDC_HD_VD_WID >> 2] = regr(CCDC_HD_VD_WID);
857 ccdc_ctx[CCDC_PIX_LINES >> 2] = regr(CCDC_PIX_LINES);
858 ccdc_ctx[CCDC_HORZ_INFO >> 2] = regr(CCDC_HORZ_INFO);
859 ccdc_ctx[CCDC_VERT_START >> 2] = regr(CCDC_VERT_START);
860 ccdc_ctx[CCDC_VERT_LINES >> 2] = regr(CCDC_VERT_LINES);
861 ccdc_ctx[CCDC_CULLING >> 2] = regr(CCDC_CULLING);
862 ccdc_ctx[CCDC_HSIZE_OFF >> 2] = regr(CCDC_HSIZE_OFF);
863 ccdc_ctx[CCDC_SDOFST >> 2] = regr(CCDC_SDOFST);
864 ccdc_ctx[CCDC_SDR_ADDR >> 2] = regr(CCDC_SDR_ADDR);
865 ccdc_ctx[CCDC_CLAMP >> 2] = regr(CCDC_CLAMP);
866 ccdc_ctx[CCDC_DCSUB >> 2] = regr(CCDC_DCSUB);
867 ccdc_ctx[CCDC_COLPTN >> 2] = regr(CCDC_COLPTN);
868 ccdc_ctx[CCDC_BLKCMP >> 2] = regr(CCDC_BLKCMP);
869 ccdc_ctx[CCDC_FPC >> 2] = regr(CCDC_FPC);
870 ccdc_ctx[CCDC_FPC_ADDR >> 2] = regr(CCDC_FPC_ADDR);
871 ccdc_ctx[CCDC_VDINT >> 2] = regr(CCDC_VDINT);
872 ccdc_ctx[CCDC_ALAW >> 2] = regr(CCDC_ALAW);
873 ccdc_ctx[CCDC_REC656IF >> 2] = regr(CCDC_REC656IF);
874 ccdc_ctx[CCDC_CCDCFG >> 2] = regr(CCDC_CCDCFG);
875 ccdc_ctx[CCDC_FMTCFG >> 2] = regr(CCDC_FMTCFG);
876 ccdc_ctx[CCDC_FMT_HORZ >> 2] = regr(CCDC_FMT_HORZ);
877 ccdc_ctx[CCDC_FMT_VERT >> 2] = regr(CCDC_FMT_VERT);
878 ccdc_ctx[CCDC_FMT_ADDR0 >> 2] = regr(CCDC_FMT_ADDR0);
879 ccdc_ctx[CCDC_FMT_ADDR1 >> 2] = regr(CCDC_FMT_ADDR1);
880 ccdc_ctx[CCDC_FMT_ADDR2 >> 2] = regr(CCDC_FMT_ADDR2);
881 ccdc_ctx[CCDC_FMT_ADDR3 >> 2] = regr(CCDC_FMT_ADDR3);
882 ccdc_ctx[CCDC_FMT_ADDR4 >> 2] = regr(CCDC_FMT_ADDR4);
883 ccdc_ctx[CCDC_FMT_ADDR5 >> 2] = regr(CCDC_FMT_ADDR5);
884 ccdc_ctx[CCDC_FMT_ADDR6 >> 2] = regr(CCDC_FMT_ADDR6);
885 ccdc_ctx[CCDC_FMT_ADDR7 >> 2] = regr(CCDC_FMT_ADDR7);
886 ccdc_ctx[CCDC_PRGEVEN_0 >> 2] = regr(CCDC_PRGEVEN_0);
887 ccdc_ctx[CCDC_PRGEVEN_1 >> 2] = regr(CCDC_PRGEVEN_1);
888 ccdc_ctx[CCDC_PRGODD_0 >> 2] = regr(CCDC_PRGODD_0);
889 ccdc_ctx[CCDC_PRGODD_1 >> 2] = regr(CCDC_PRGODD_1);
890 ccdc_ctx[CCDC_VP_OUT >> 2] = regr(CCDC_VP_OUT);
891}
892
893static void ccdc_restore_context(void)
894{
895 regw(ccdc_ctx[CCDC_SYN_MODE >> 2], CCDC_SYN_MODE);
896 regw(ccdc_ctx[CCDC_HD_VD_WID >> 2], CCDC_HD_VD_WID);
897 regw(ccdc_ctx[CCDC_PIX_LINES >> 2], CCDC_PIX_LINES);
898 regw(ccdc_ctx[CCDC_HORZ_INFO >> 2], CCDC_HORZ_INFO);
899 regw(ccdc_ctx[CCDC_VERT_START >> 2], CCDC_VERT_START);
900 regw(ccdc_ctx[CCDC_VERT_LINES >> 2], CCDC_VERT_LINES);
901 regw(ccdc_ctx[CCDC_CULLING >> 2], CCDC_CULLING);
902 regw(ccdc_ctx[CCDC_HSIZE_OFF >> 2], CCDC_HSIZE_OFF);
903 regw(ccdc_ctx[CCDC_SDOFST >> 2], CCDC_SDOFST);
904 regw(ccdc_ctx[CCDC_SDR_ADDR >> 2], CCDC_SDR_ADDR);
905 regw(ccdc_ctx[CCDC_CLAMP >> 2], CCDC_CLAMP);
906 regw(ccdc_ctx[CCDC_DCSUB >> 2], CCDC_DCSUB);
907 regw(ccdc_ctx[CCDC_COLPTN >> 2], CCDC_COLPTN);
908 regw(ccdc_ctx[CCDC_BLKCMP >> 2], CCDC_BLKCMP);
909 regw(ccdc_ctx[CCDC_FPC >> 2], CCDC_FPC);
910 regw(ccdc_ctx[CCDC_FPC_ADDR >> 2], CCDC_FPC_ADDR);
911 regw(ccdc_ctx[CCDC_VDINT >> 2], CCDC_VDINT);
912 regw(ccdc_ctx[CCDC_ALAW >> 2], CCDC_ALAW);
913 regw(ccdc_ctx[CCDC_REC656IF >> 2], CCDC_REC656IF);
914 regw(ccdc_ctx[CCDC_CCDCFG >> 2], CCDC_CCDCFG);
915 regw(ccdc_ctx[CCDC_FMTCFG >> 2], CCDC_FMTCFG);
916 regw(ccdc_ctx[CCDC_FMT_HORZ >> 2], CCDC_FMT_HORZ);
917 regw(ccdc_ctx[CCDC_FMT_VERT >> 2], CCDC_FMT_VERT);
918 regw(ccdc_ctx[CCDC_FMT_ADDR0 >> 2], CCDC_FMT_ADDR0);
919 regw(ccdc_ctx[CCDC_FMT_ADDR1 >> 2], CCDC_FMT_ADDR1);
920 regw(ccdc_ctx[CCDC_FMT_ADDR2 >> 2], CCDC_FMT_ADDR2);
921 regw(ccdc_ctx[CCDC_FMT_ADDR3 >> 2], CCDC_FMT_ADDR3);
922 regw(ccdc_ctx[CCDC_FMT_ADDR4 >> 2], CCDC_FMT_ADDR4);
923 regw(ccdc_ctx[CCDC_FMT_ADDR5 >> 2], CCDC_FMT_ADDR5);
924 regw(ccdc_ctx[CCDC_FMT_ADDR6 >> 2], CCDC_FMT_ADDR6);
925 regw(ccdc_ctx[CCDC_FMT_ADDR7 >> 2], CCDC_FMT_ADDR7);
926 regw(ccdc_ctx[CCDC_PRGEVEN_0 >> 2], CCDC_PRGEVEN_0);
927 regw(ccdc_ctx[CCDC_PRGEVEN_1 >> 2], CCDC_PRGEVEN_1);
928 regw(ccdc_ctx[CCDC_PRGODD_0 >> 2], CCDC_PRGODD_0);
929 regw(ccdc_ctx[CCDC_PRGODD_1 >> 2], CCDC_PRGODD_1);
930 regw(ccdc_ctx[CCDC_VP_OUT >> 2], CCDC_VP_OUT);
931 regw(ccdc_ctx[CCDC_PCR >> 2], CCDC_PCR);
932}
933static struct ccdc_hw_device ccdc_hw_dev = {
934 .name = "DM6446 CCDC",
935 .owner = THIS_MODULE,
936 .hw_ops = {
937 .open = ccdc_open,
938 .close = ccdc_close,
939 .reset = ccdc_sbl_reset,
940 .enable = ccdc_enable,
941 .set_hw_if_params = ccdc_set_hw_if_params,
942 .set_params = ccdc_set_params,
943 .configure = ccdc_configure,
944 .set_buftype = ccdc_set_buftype,
945 .get_buftype = ccdc_get_buftype,
946 .enum_pix = ccdc_enum_pix,
947 .set_pixel_format = ccdc_set_pixel_format,
948 .get_pixel_format = ccdc_get_pixel_format,
949 .set_frame_format = ccdc_set_frame_format,
950 .get_frame_format = ccdc_get_frame_format,
951 .set_image_window = ccdc_set_image_window,
952 .get_image_window = ccdc_get_image_window,
953 .get_line_length = ccdc_get_line_length,
954 .setfbaddr = ccdc_setfbaddr,
955 .getfid = ccdc_getfid,
956 },
957};
958
959static int __init dm644x_ccdc_probe(struct platform_device *pdev)
960{
961 struct resource *res;
962 int status = 0;
963
964 /*
965 * first try to register with vpfe. If not correct platform, then we
966 * don't have to iomap
967 */
968 status = vpfe_register_ccdc_device(&ccdc_hw_dev);
969 if (status < 0)
970 return status;
971
972 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
973 if (!res) {
974 status = -ENODEV;
975 goto fail_nores;
976 }
977
978 res = request_mem_region(res->start, resource_size(res), res->name);
979 if (!res) {
980 status = -EBUSY;
981 goto fail_nores;
982 }
983
984 ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res));
985 if (!ccdc_cfg.base_addr) {
986 status = -ENOMEM;
987 goto fail_nomem;
988 }
989
990 /* Get and enable Master clock */
991 ccdc_cfg.mclk = clk_get(&pdev->dev, "master");
992 if (IS_ERR(ccdc_cfg.mclk)) {
993 status = PTR_ERR(ccdc_cfg.mclk);
994 goto fail_nomap;
995 }
996 if (clk_enable(ccdc_cfg.mclk)) {
997 status = -ENODEV;
998 goto fail_mclk;
999 }
1000
1001 /* Get and enable Slave clock */
1002 ccdc_cfg.sclk = clk_get(&pdev->dev, "slave");
1003 if (IS_ERR(ccdc_cfg.sclk)) {
1004 status = PTR_ERR(ccdc_cfg.sclk);
1005 goto fail_mclk;
1006 }
1007 if (clk_enable(ccdc_cfg.sclk)) {
1008 status = -ENODEV;
1009 goto fail_sclk;
1010 }
1011 ccdc_cfg.dev = &pdev->dev;
1012 printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
1013 return 0;
1014fail_sclk:
1015 clk_put(ccdc_cfg.sclk);
1016fail_mclk:
1017 clk_put(ccdc_cfg.mclk);
1018fail_nomap:
1019 iounmap(ccdc_cfg.base_addr);
1020fail_nomem:
1021 release_mem_region(res->start, resource_size(res));
1022fail_nores:
1023 vpfe_unregister_ccdc_device(&ccdc_hw_dev);
1024 return status;
1025}
1026
1027static int dm644x_ccdc_remove(struct platform_device *pdev)
1028{
1029 struct resource *res;
1030
1031 clk_put(ccdc_cfg.mclk);
1032 clk_put(ccdc_cfg.sclk);
1033 iounmap(ccdc_cfg.base_addr);
1034 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1035 if (res)
1036 release_mem_region(res->start, resource_size(res));
1037 vpfe_unregister_ccdc_device(&ccdc_hw_dev);
1038 return 0;
1039}
1040
1041static int dm644x_ccdc_suspend(struct device *dev)
1042{
1043 /* Save CCDC context */
1044 ccdc_save_context();
1045 /* Disable CCDC */
1046 ccdc_enable(0);
1047 /* Disable both master and slave clock */
1048 clk_disable(ccdc_cfg.mclk);
1049 clk_disable(ccdc_cfg.sclk);
1050
1051 return 0;
1052}
1053
1054static int dm644x_ccdc_resume(struct device *dev)
1055{
1056 /* Enable both master and slave clock */
1057 clk_enable(ccdc_cfg.mclk);
1058 clk_enable(ccdc_cfg.sclk);
1059 /* Restore CCDC context */
1060 ccdc_restore_context();
1061
1062 return 0;
1063}
1064
1065static const struct dev_pm_ops dm644x_ccdc_pm_ops = {
1066 .suspend = dm644x_ccdc_suspend,
1067 .resume = dm644x_ccdc_resume,
1068};
1069
1070static struct platform_driver dm644x_ccdc_driver = {
1071 .driver = {
1072 .name = "dm644x_ccdc",
1073 .owner = THIS_MODULE,
1074 .pm = &dm644x_ccdc_pm_ops,
1075 },
1076 .remove = __devexit_p(dm644x_ccdc_remove),
1077 .probe = dm644x_ccdc_probe,
1078};
1079
1080static int __init dm644x_ccdc_init(void)
1081{
1082 return platform_driver_register(&dm644x_ccdc_driver);
1083}
1084
1085static void __exit dm644x_ccdc_exit(void)
1086{
1087 platform_driver_unregister(&dm644x_ccdc_driver);
1088}
1089
1090module_init(dm644x_ccdc_init);
1091module_exit(dm644x_ccdc_exit);
diff --git a/drivers/media/video/davinci/dm644x_ccdc_regs.h b/drivers/media/video/davinci/dm644x_ccdc_regs.h
new file mode 100644
index 00000000000..90370e414e2
--- /dev/null
+++ b/drivers/media/video/davinci/dm644x_ccdc_regs.h
@@ -0,0 +1,153 @@
1/*
2 * Copyright (C) 2006-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _DM644X_CCDC_REGS_H
19#define _DM644X_CCDC_REGS_H
20
21/**************************************************************************\
22* Register OFFSET Definitions
23\**************************************************************************/
24#define CCDC_PID 0x0
25#define CCDC_PCR 0x4
26#define CCDC_SYN_MODE 0x8
27#define CCDC_HD_VD_WID 0xc
28#define CCDC_PIX_LINES 0x10
29#define CCDC_HORZ_INFO 0x14
30#define CCDC_VERT_START 0x18
31#define CCDC_VERT_LINES 0x1c
32#define CCDC_CULLING 0x20
33#define CCDC_HSIZE_OFF 0x24
34#define CCDC_SDOFST 0x28
35#define CCDC_SDR_ADDR 0x2c
36#define CCDC_CLAMP 0x30
37#define CCDC_DCSUB 0x34
38#define CCDC_COLPTN 0x38
39#define CCDC_BLKCMP 0x3c
40#define CCDC_FPC 0x40
41#define CCDC_FPC_ADDR 0x44
42#define CCDC_VDINT 0x48
43#define CCDC_ALAW 0x4c
44#define CCDC_REC656IF 0x50
45#define CCDC_CCDCFG 0x54
46#define CCDC_FMTCFG 0x58
47#define CCDC_FMT_HORZ 0x5c
48#define CCDC_FMT_VERT 0x60
49#define CCDC_FMT_ADDR0 0x64
50#define CCDC_FMT_ADDR1 0x68
51#define CCDC_FMT_ADDR2 0x6c
52#define CCDC_FMT_ADDR3 0x70
53#define CCDC_FMT_ADDR4 0x74
54#define CCDC_FMT_ADDR5 0x78
55#define CCDC_FMT_ADDR6 0x7c
56#define CCDC_FMT_ADDR7 0x80
57#define CCDC_PRGEVEN_0 0x84
58#define CCDC_PRGEVEN_1 0x88
59#define CCDC_PRGODD_0 0x8c
60#define CCDC_PRGODD_1 0x90
61#define CCDC_VP_OUT 0x94
62#define CCDC_REG_END 0x98
63
64/***************************************************************
65* Define for various register bit mask and shifts for CCDC
66****************************************************************/
67#define CCDC_FID_POL_MASK 1
68#define CCDC_FID_POL_SHIFT 4
69#define CCDC_HD_POL_MASK 1
70#define CCDC_HD_POL_SHIFT 3
71#define CCDC_VD_POL_MASK 1
72#define CCDC_VD_POL_SHIFT 2
73#define CCDC_HSIZE_OFF_MASK 0xffffffe0
74#define CCDC_32BYTE_ALIGN_VAL 31
75#define CCDC_FRM_FMT_MASK 0x1
76#define CCDC_FRM_FMT_SHIFT 7
77#define CCDC_DATA_SZ_MASK 7
78#define CCDC_DATA_SZ_SHIFT 8
79#define CCDC_PIX_FMT_MASK 3
80#define CCDC_PIX_FMT_SHIFT 12
81#define CCDC_VP2SDR_DISABLE 0xFFFBFFFF
82#define CCDC_WEN_ENABLE (1 << 17)
83#define CCDC_SDR2RSZ_DISABLE 0xFFF7FFFF
84#define CCDC_VDHDEN_ENABLE (1 << 16)
85#define CCDC_LPF_ENABLE (1 << 14)
86#define CCDC_ALAW_ENABLE (1 << 3)
87#define CCDC_ALAW_GAMA_WD_MASK 7
88#define CCDC_BLK_CLAMP_ENABLE (1 << 31)
89#define CCDC_BLK_SGAIN_MASK 0x1F
90#define CCDC_BLK_ST_PXL_MASK 0x7FFF
91#define CCDC_BLK_ST_PXL_SHIFT 10
92#define CCDC_BLK_SAMPLE_LN_MASK 7
93#define CCDC_BLK_SAMPLE_LN_SHIFT 28
94#define CCDC_BLK_SAMPLE_LINE_MASK 7
95#define CCDC_BLK_SAMPLE_LINE_SHIFT 25
96#define CCDC_BLK_DC_SUB_MASK 0x03FFF
97#define CCDC_BLK_COMP_MASK 0xFF
98#define CCDC_BLK_COMP_GB_COMP_SHIFT 8
99#define CCDC_BLK_COMP_GR_COMP_SHIFT 16
100#define CCDC_BLK_COMP_R_COMP_SHIFT 24
101#define CCDC_LATCH_ON_VSYNC_DISABLE (1 << 15)
102#define CCDC_FPC_ENABLE (1 << 15)
103#define CCDC_FPC_DISABLE 0
104#define CCDC_FPC_FPC_NUM_MASK 0x7FFF
105#define CCDC_DATA_PACK_ENABLE (1 << 11)
106#define CCDC_FMTCFG_VPIN_MASK 7
107#define CCDC_FMTCFG_VPIN_SHIFT 12
108#define CCDC_FMT_HORZ_FMTLNH_MASK 0x1FFF
109#define CCDC_FMT_HORZ_FMTSPH_MASK 0x1FFF
110#define CCDC_FMT_HORZ_FMTSPH_SHIFT 16
111#define CCDC_FMT_VERT_FMTLNV_MASK 0x1FFF
112#define CCDC_FMT_VERT_FMTSLV_MASK 0x1FFF
113#define CCDC_FMT_VERT_FMTSLV_SHIFT 16
114#define CCDC_VP_OUT_VERT_NUM_MASK 0x3FFF
115#define CCDC_VP_OUT_VERT_NUM_SHIFT 17
116#define CCDC_VP_OUT_HORZ_NUM_MASK 0x1FFF
117#define CCDC_VP_OUT_HORZ_NUM_SHIFT 4
118#define CCDC_VP_OUT_HORZ_ST_MASK 0xF
119#define CCDC_HORZ_INFO_SPH_SHIFT 16
120#define CCDC_VERT_START_SLV0_SHIFT 16
121#define CCDC_VDINT_VDINT0_SHIFT 16
122#define CCDC_VDINT_VDINT1_MASK 0xFFFF
123#define CCDC_PPC_RAW 1
124#define CCDC_DCSUB_DEFAULT_VAL 0
125#define CCDC_CLAMP_DEFAULT_VAL 0
126#define CCDC_ENABLE_VIDEO_PORT 0x8000
127#define CCDC_DISABLE_VIDEO_PORT 0
128#define CCDC_COLPTN_VAL 0xBB11BB11
129#define CCDC_TWO_BYTES_PER_PIXEL 2
130#define CCDC_INTERLACED_IMAGE_INVERT 0x4B6D
131#define CCDC_INTERLACED_NO_IMAGE_INVERT 0x0249
132#define CCDC_PROGRESSIVE_IMAGE_INVERT 0x4000
133#define CCDC_PROGRESSIVE_NO_IMAGE_INVERT 0
134#define CCDC_INTERLACED_HEIGHT_SHIFT 1
135#define CCDC_SYN_MODE_INPMOD_SHIFT 12
136#define CCDC_SYN_MODE_INPMOD_MASK 3
137#define CCDC_SYN_MODE_8BITS (7 << 8)
138#define CCDC_SYN_MODE_10BITS (6 << 8)
139#define CCDC_SYN_MODE_11BITS (5 << 8)
140#define CCDC_SYN_MODE_12BITS (4 << 8)
141#define CCDC_SYN_MODE_13BITS (3 << 8)
142#define CCDC_SYN_MODE_14BITS (2 << 8)
143#define CCDC_SYN_MODE_15BITS (1 << 8)
144#define CCDC_SYN_MODE_16BITS (0 << 8)
145#define CCDC_SYN_FLDMODE_MASK 1
146#define CCDC_SYN_FLDMODE_SHIFT 7
147#define CCDC_REC656IF_BT656_EN 3
148#define CCDC_SYN_MODE_VD_POL_NEGATIVE (1 << 2)
149#define CCDC_CCDCFG_Y8POS_SHIFT 11
150#define CCDC_CCDCFG_BW656_10BIT (1 << 5)
151#define CCDC_SDOFST_FIELD_INTERLEAVED 0x249
152#define CCDC_NO_CULLING 0xffff00ff
153#endif
diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c
new file mode 100644
index 00000000000..29c29c66859
--- /dev/null
+++ b/drivers/media/video/davinci/isif.c
@@ -0,0 +1,1172 @@
1/*
2 * Copyright (C) 2008-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Image Sensor Interface (ISIF) driver
19 *
20 * This driver is for configuring the ISIF IP available on DM365 or any other
21 * TI SoCs. This is used for capturing yuv or bayer video or image data
22 * from a decoder or sensor. This IP is similar to the CCDC IP on DM355
23 * and DM6446, but with enhanced or additional ip blocks. The driver
24 * configures the ISIF upon commands from the vpfe bridge driver through
25 * ccdc_hw_device interface.
26 *
27 * TODO: 1) Raw bayer parameter settings and bayer capture
28 * 2) Add support for control ioctl
29 */
30#include <linux/delay.h>
31#include <linux/platform_device.h>
32#include <linux/uaccess.h>
33#include <linux/io.h>
34#include <linux/videodev2.h>
35#include <linux/clk.h>
36#include <linux/err.h>
37
38#include <mach/mux.h>
39
40#include <media/davinci/isif.h>
41#include <media/davinci/vpss.h>
42
43#include "isif_regs.h"
44#include "ccdc_hw_device.h"
45
46/* Defaults for module configuration parameters */
47static struct isif_config_params_raw isif_config_defaults = {
48 .linearize = {
49 .en = 0,
50 .corr_shft = ISIF_NO_SHIFT,
51 .scale_fact = {1, 0},
52 },
53 .df_csc = {
54 .df_or_csc = 0,
55 .csc = {
56 .en = 0,
57 },
58 },
59 .dfc = {
60 .en = 0,
61 },
62 .bclamp = {
63 .en = 0,
64 },
65 .gain_offset = {
66 .gain = {
67 .r_ye = {1, 0},
68 .gr_cy = {1, 0},
69 .gb_g = {1, 0},
70 .b_mg = {1, 0},
71 },
72 },
73 .culling = {
74 .hcpat_odd = 0xff,
75 .hcpat_even = 0xff,
76 .vcpat = 0xff,
77 },
78 .compress = {
79 .alg = ISIF_ALAW,
80 },
81};
82
83/* ISIF operation configuration */
84static struct isif_oper_config {
85 struct device *dev;
86 enum vpfe_hw_if_type if_type;
87 struct isif_ycbcr_config ycbcr;
88 struct isif_params_raw bayer;
89 enum isif_data_pack data_pack;
90 /* Master clock */
91 struct clk *mclk;
92 /* ISIF base address */
93 void __iomem *base_addr;
94 /* ISIF Linear Table 0 */
95 void __iomem *linear_tbl0_addr;
96 /* ISIF Linear Table 1 */
97 void __iomem *linear_tbl1_addr;
98} isif_cfg = {
99 .ycbcr = {
100 .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
101 .frm_fmt = CCDC_FRMFMT_INTERLACED,
102 .win = ISIF_WIN_NTSC,
103 .fid_pol = VPFE_PINPOL_POSITIVE,
104 .vd_pol = VPFE_PINPOL_POSITIVE,
105 .hd_pol = VPFE_PINPOL_POSITIVE,
106 .pix_order = CCDC_PIXORDER_CBYCRY,
107 .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED,
108 },
109 .bayer = {
110 .pix_fmt = CCDC_PIXFMT_RAW,
111 .frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
112 .win = ISIF_WIN_VGA,
113 .fid_pol = VPFE_PINPOL_POSITIVE,
114 .vd_pol = VPFE_PINPOL_POSITIVE,
115 .hd_pol = VPFE_PINPOL_POSITIVE,
116 .gain = {
117 .r_ye = {1, 0},
118 .gr_cy = {1, 0},
119 .gb_g = {1, 0},
120 .b_mg = {1, 0},
121 },
122 .cfa_pat = ISIF_CFA_PAT_MOSAIC,
123 .data_msb = ISIF_BIT_MSB_11,
124 .config_params = {
125 .data_shift = ISIF_NO_SHIFT,
126 .col_pat_field0 = {
127 .olop = ISIF_GREEN_BLUE,
128 .olep = ISIF_BLUE,
129 .elop = ISIF_RED,
130 .elep = ISIF_GREEN_RED,
131 },
132 .col_pat_field1 = {
133 .olop = ISIF_GREEN_BLUE,
134 .olep = ISIF_BLUE,
135 .elop = ISIF_RED,
136 .elep = ISIF_GREEN_RED,
137 },
138 .test_pat_gen = 0,
139 },
140 },
141 .data_pack = ISIF_DATA_PACK8,
142};
143
144/* Raw Bayer formats */
145static const u32 isif_raw_bayer_pix_formats[] = {
146 V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
147
148/* Raw YUV formats */
149static const u32 isif_raw_yuv_pix_formats[] = {
150 V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
151
152/* register access routines */
153static inline u32 regr(u32 offset)
154{
155 return __raw_readl(isif_cfg.base_addr + offset);
156}
157
158static inline void regw(u32 val, u32 offset)
159{
160 __raw_writel(val, isif_cfg.base_addr + offset);
161}
162
163/* reg_modify() - read, modify and write register */
164static inline u32 reg_modify(u32 mask, u32 val, u32 offset)
165{
166 u32 new_val = (regr(offset) & ~mask) | (val & mask);
167
168 regw(new_val, offset);
169 return new_val;
170}
171
172static inline void regw_lin_tbl(u32 val, u32 offset, int i)
173{
174 if (!i)
175 __raw_writel(val, isif_cfg.linear_tbl0_addr + offset);
176 else
177 __raw_writel(val, isif_cfg.linear_tbl1_addr + offset);
178}
179
180static void isif_disable_all_modules(void)
181{
182 /* disable BC */
183 regw(0, CLAMPCFG);
184 /* disable vdfc */
185 regw(0, DFCCTL);
186 /* disable CSC */
187 regw(0, CSCCTL);
188 /* disable linearization */
189 regw(0, LINCFG0);
190 /* disable other modules here as they are supported */
191}
192
193static void isif_enable(int en)
194{
195 if (!en) {
196 /* Before disable isif, disable all ISIF modules */
197 isif_disable_all_modules();
198 /*
199 * wait for next VD. Assume lowest scan rate is 12 Hz. So
200 * 100 msec delay is good enough
201 */
202 msleep(100);
203 }
204 reg_modify(ISIF_SYNCEN_VDHDEN_MASK, en, SYNCEN);
205}
206
207static void isif_enable_output_to_sdram(int en)
208{
209 reg_modify(ISIF_SYNCEN_WEN_MASK, en << ISIF_SYNCEN_WEN_SHIFT, SYNCEN);
210}
211
212static void isif_config_culling(struct isif_cul *cul)
213{
214 u32 val;
215
216 /* Horizontal pattern */
217 val = (cul->hcpat_even << CULL_PAT_EVEN_LINE_SHIFT) | cul->hcpat_odd;
218 regw(val, CULH);
219
220 /* vertical pattern */
221 regw(cul->vcpat, CULV);
222
223 /* LPF */
224 reg_modify(ISIF_LPF_MASK << ISIF_LPF_SHIFT,
225 cul->en_lpf << ISIF_LPF_SHIFT, MODESET);
226}
227
228static void isif_config_gain_offset(void)
229{
230 struct isif_gain_offsets_adj *gain_off_p =
231 &isif_cfg.bayer.config_params.gain_offset;
232 u32 val;
233
234 val = (!!gain_off_p->gain_sdram_en << GAIN_SDRAM_EN_SHIFT) |
235 (!!gain_off_p->gain_ipipe_en << GAIN_IPIPE_EN_SHIFT) |
236 (!!gain_off_p->gain_h3a_en << GAIN_H3A_EN_SHIFT) |
237 (!!gain_off_p->offset_sdram_en << OFST_SDRAM_EN_SHIFT) |
238 (!!gain_off_p->offset_ipipe_en << OFST_IPIPE_EN_SHIFT) |
239 (!!gain_off_p->offset_h3a_en << OFST_H3A_EN_SHIFT);
240
241 reg_modify(GAIN_OFFSET_EN_MASK, val, CGAMMAWD);
242
243 val = (gain_off_p->gain.r_ye.integer << GAIN_INTEGER_SHIFT) |
244 gain_off_p->gain.r_ye.decimal;
245 regw(val, CRGAIN);
246
247 val = (gain_off_p->gain.gr_cy.integer << GAIN_INTEGER_SHIFT) |
248 gain_off_p->gain.gr_cy.decimal;
249 regw(val, CGRGAIN);
250
251 val = (gain_off_p->gain.gb_g.integer << GAIN_INTEGER_SHIFT) |
252 gain_off_p->gain.gb_g.decimal;
253 regw(val, CGBGAIN);
254
255 val = (gain_off_p->gain.b_mg.integer << GAIN_INTEGER_SHIFT) |
256 gain_off_p->gain.b_mg.decimal;
257 regw(val, CBGAIN);
258
259 regw(gain_off_p->offset, COFSTA);
260}
261
262static void isif_restore_defaults(void)
263{
264 enum vpss_ccdc_source_sel source = VPSS_CCDCIN;
265
266 dev_dbg(isif_cfg.dev, "\nstarting isif_restore_defaults...");
267 isif_cfg.bayer.config_params = isif_config_defaults;
268 /* Enable clock to ISIF, IPIPEIF and BL */
269 vpss_enable_clock(VPSS_CCDC_CLOCK, 1);
270 vpss_enable_clock(VPSS_IPIPEIF_CLOCK, 1);
271 vpss_enable_clock(VPSS_BL_CLOCK, 1);
272 /* Set default offset and gain */
273 isif_config_gain_offset();
274 vpss_select_ccdc_source(source);
275 dev_dbg(isif_cfg.dev, "\nEnd of isif_restore_defaults...");
276}
277
278static int isif_open(struct device *device)
279{
280 isif_restore_defaults();
281 return 0;
282}
283
284/* This function will configure the window size to be capture in ISIF reg */
285static void isif_setwin(struct v4l2_rect *image_win,
286 enum ccdc_frmfmt frm_fmt, int ppc)
287{
288 int horz_start, horz_nr_pixels;
289 int vert_start, vert_nr_lines;
290 int mid_img = 0;
291
292 dev_dbg(isif_cfg.dev, "\nStarting isif_setwin...");
293 /*
294 * ppc - per pixel count. indicates how many pixels per cell
295 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
296 * raw capture this is 1
297 */
298 horz_start = image_win->left << (ppc - 1);
299 horz_nr_pixels = ((image_win->width) << (ppc - 1)) - 1;
300
301 /* Writing the horizontal info into the registers */
302 regw(horz_start & START_PX_HOR_MASK, SPH);
303 regw(horz_nr_pixels & NUM_PX_HOR_MASK, LNH);
304 vert_start = image_win->top;
305
306 if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
307 vert_nr_lines = (image_win->height >> 1) - 1;
308 vert_start >>= 1;
309 /* To account for VD since line 0 doesn't have any data */
310 vert_start += 1;
311 } else {
312 /* To account for VD since line 0 doesn't have any data */
313 vert_start += 1;
314 vert_nr_lines = image_win->height - 1;
315 /* configure VDINT0 and VDINT1 */
316 mid_img = vert_start + (image_win->height / 2);
317 regw(mid_img, VDINT1);
318 }
319
320 regw(0, VDINT0);
321 regw(vert_start & START_VER_ONE_MASK, SLV0);
322 regw(vert_start & START_VER_TWO_MASK, SLV1);
323 regw(vert_nr_lines & NUM_LINES_VER, LNV);
324}
325
326static void isif_config_bclamp(struct isif_black_clamp *bc)
327{
328 u32 val;
329
330 /*
331 * DC Offset is always added to image data irrespective of bc enable
332 * status
333 */
334 regw(bc->dc_offset, CLDCOFST);
335
336 if (bc->en) {
337 val = bc->bc_mode_color << ISIF_BC_MODE_COLOR_SHIFT;
338
339 /* Enable BC and horizontal clamp caculation paramaters */
340 val = val | 1 | (bc->horz.mode << ISIF_HORZ_BC_MODE_SHIFT);
341
342 regw(val, CLAMPCFG);
343
344 if (bc->horz.mode != ISIF_HORZ_BC_DISABLE) {
345 /*
346 * Window count for calculation
347 * Base window selection
348 * pixel limit
349 * Horizontal size of window
350 * vertical size of the window
351 * Horizontal start position of the window
352 * Vertical start position of the window
353 */
354 val = bc->horz.win_count_calc |
355 ((!!bc->horz.base_win_sel_calc) <<
356 ISIF_HORZ_BC_WIN_SEL_SHIFT) |
357 ((!!bc->horz.clamp_pix_limit) <<
358 ISIF_HORZ_BC_PIX_LIMIT_SHIFT) |
359 (bc->horz.win_h_sz_calc <<
360 ISIF_HORZ_BC_WIN_H_SIZE_SHIFT) |
361 (bc->horz.win_v_sz_calc <<
362 ISIF_HORZ_BC_WIN_V_SIZE_SHIFT);
363 regw(val, CLHWIN0);
364
365 regw(bc->horz.win_start_h_calc, CLHWIN1);
366 regw(bc->horz.win_start_v_calc, CLHWIN2);
367 }
368
369 /* vertical clamp caculation paramaters */
370
371 /* Reset clamp value sel for previous line */
372 val |=
373 (bc->vert.reset_val_sel << ISIF_VERT_BC_RST_VAL_SEL_SHIFT) |
374 (bc->vert.line_ave_coef << ISIF_VERT_BC_LINE_AVE_COEF_SHIFT);
375 regw(val, CLVWIN0);
376
377 /* Optical Black horizontal start position */
378 regw(bc->vert.ob_start_h, CLVWIN1);
379 /* Optical Black vertical start position */
380 regw(bc->vert.ob_start_v, CLVWIN2);
381 /* Optical Black vertical size for calculation */
382 regw(bc->vert.ob_v_sz_calc, CLVWIN3);
383 /* Vertical start position for BC subtraction */
384 regw(bc->vert_start_sub, CLSV);
385 }
386}
387
388static void isif_config_linearization(struct isif_linearize *linearize)
389{
390 u32 val, i;
391
392 if (!linearize->en) {
393 regw(0, LINCFG0);
394 return;
395 }
396
397 /* shift value for correction & enable linearization (set lsb) */
398 val = (linearize->corr_shft << ISIF_LIN_CORRSFT_SHIFT) | 1;
399 regw(val, LINCFG0);
400
401 /* Scale factor */
402 val = ((!!linearize->scale_fact.integer) <<
403 ISIF_LIN_SCALE_FACT_INTEG_SHIFT) |
404 linearize->scale_fact.decimal;
405 regw(val, LINCFG1);
406
407 for (i = 0; i < ISIF_LINEAR_TAB_SIZE; i++) {
408 if (i % 2)
409 regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 1);
410 else
411 regw_lin_tbl(linearize->table[i], ((i >> 1) << 2), 0);
412 }
413}
414
415static int isif_config_dfc(struct isif_dfc *vdfc)
416{
417 /* initialize retries to loop for max ~ 250 usec */
418 u32 val, count, retries = loops_per_jiffy / (4000/HZ);
419 int i;
420
421 if (!vdfc->en)
422 return 0;
423
424 /* Correction mode */
425 val = (vdfc->corr_mode << ISIF_VDFC_CORR_MOD_SHIFT);
426
427 /* Correct whole line or partial */
428 if (vdfc->corr_whole_line)
429 val |= 1 << ISIF_VDFC_CORR_WHOLE_LN_SHIFT;
430
431 /* level shift value */
432 val |= vdfc->def_level_shift << ISIF_VDFC_LEVEL_SHFT_SHIFT;
433
434 regw(val, DFCCTL);
435
436 /* Defect saturation level */
437 regw(vdfc->def_sat_level, VDFSATLV);
438
439 regw(vdfc->table[0].pos_vert, DFCMEM0);
440 regw(vdfc->table[0].pos_horz, DFCMEM1);
441 if (vdfc->corr_mode == ISIF_VDFC_NORMAL ||
442 vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
443 regw(vdfc->table[0].level_at_pos, DFCMEM2);
444 regw(vdfc->table[0].level_up_pixels, DFCMEM3);
445 regw(vdfc->table[0].level_low_pixels, DFCMEM4);
446 }
447
448 /* set DFCMARST and set DFCMWR */
449 val = regr(DFCMEMCTL) | (1 << ISIF_DFCMEMCTL_DFCMARST_SHIFT) | 1;
450 regw(val, DFCMEMCTL);
451
452 count = retries;
453 while (count && (regr(DFCMEMCTL) & 0x1))
454 count--;
455
456 if (!count) {
457 dev_dbg(isif_cfg.dev, "defect table write timeout !!!\n");
458 return -1;
459 }
460
461 for (i = 1; i < vdfc->num_vdefects; i++) {
462 regw(vdfc->table[i].pos_vert, DFCMEM0);
463 regw(vdfc->table[i].pos_horz, DFCMEM1);
464 if (vdfc->corr_mode == ISIF_VDFC_NORMAL ||
465 vdfc->corr_mode == ISIF_VDFC_HORZ_INTERPOL_IF_SAT) {
466 regw(vdfc->table[i].level_at_pos, DFCMEM2);
467 regw(vdfc->table[i].level_up_pixels, DFCMEM3);
468 regw(vdfc->table[i].level_low_pixels, DFCMEM4);
469 }
470 val = regr(DFCMEMCTL);
471 /* clear DFCMARST and set DFCMWR */
472 val &= ~BIT(ISIF_DFCMEMCTL_DFCMARST_SHIFT);
473 val |= 1;
474 regw(val, DFCMEMCTL);
475
476 count = retries;
477 while (count && (regr(DFCMEMCTL) & 0x1))
478 count--;
479
480 if (!count) {
481 dev_err(isif_cfg.dev,
482 "defect table write timeout !!!\n");
483 return -1;
484 }
485 }
486 if (vdfc->num_vdefects < ISIF_VDFC_TABLE_SIZE) {
487 /* Extra cycle needed */
488 regw(0, DFCMEM0);
489 regw(0x1FFF, DFCMEM1);
490 regw(1, DFCMEMCTL);
491 }
492
493 /* enable VDFC */
494 reg_modify((1 << ISIF_VDFC_EN_SHIFT), (1 << ISIF_VDFC_EN_SHIFT),
495 DFCCTL);
496 return 0;
497}
498
499static void isif_config_csc(struct isif_df_csc *df_csc)
500{
501 u32 val1 = 0, val2 = 0, i;
502
503 if (!df_csc->csc.en) {
504 regw(0, CSCCTL);
505 return;
506 }
507 for (i = 0; i < ISIF_CSC_NUM_COEFF; i++) {
508 if ((i % 2) == 0) {
509 /* CSCM - LSB */
510 val1 = (df_csc->csc.coeff[i].integer <<
511 ISIF_CSC_COEF_INTEG_SHIFT) |
512 df_csc->csc.coeff[i].decimal;
513 } else {
514
515 /* CSCM - MSB */
516 val2 = (df_csc->csc.coeff[i].integer <<
517 ISIF_CSC_COEF_INTEG_SHIFT) |
518 df_csc->csc.coeff[i].decimal;
519 val2 <<= ISIF_CSCM_MSB_SHIFT;
520 val2 |= val1;
521 regw(val2, (CSCM0 + ((i - 1) << 1)));
522 }
523 }
524
525 /* program the active area */
526 regw(df_csc->start_pix, FMTSPH);
527 /*
528 * one extra pixel as required for CSC. Actually number of
529 * pixel - 1 should be configured in this register. So we
530 * need to subtract 1 before writing to FMTSPH, but we will
531 * not do this since csc requires one extra pixel
532 */
533 regw(df_csc->num_pixels, FMTLNH);
534 regw(df_csc->start_line, FMTSLV);
535 /*
536 * one extra line as required for CSC. See reason documented for
537 * num_pixels
538 */
539 regw(df_csc->num_lines, FMTLNV);
540
541 /* Enable CSC */
542 regw(1, CSCCTL);
543}
544
545static int isif_config_raw(void)
546{
547 struct isif_params_raw *params = &isif_cfg.bayer;
548 struct isif_config_params_raw *module_params =
549 &isif_cfg.bayer.config_params;
550 struct vpss_pg_frame_size frame_size;
551 struct vpss_sync_pol sync;
552 u32 val;
553
554 dev_dbg(isif_cfg.dev, "\nStarting isif_config_raw..\n");
555
556 /*
557 * Configure CCDCFG register:-
558 * Set CCD Not to swap input since input is RAW data
559 * Set FID detection function to Latch at V-Sync
560 * Set WENLOG - isif valid area
561 * Set TRGSEL
562 * Set EXTRG
563 * Packed to 8 or 16 bits
564 */
565
566 val = ISIF_YCINSWP_RAW | ISIF_CCDCFG_FIDMD_LATCH_VSYNC |
567 ISIF_CCDCFG_WENLOG_AND | ISIF_CCDCFG_TRGSEL_WEN |
568 ISIF_CCDCFG_EXTRG_DISABLE | isif_cfg.data_pack;
569
570 dev_dbg(isif_cfg.dev, "Writing 0x%x to ...CCDCFG \n", val);
571 regw(val, CCDCFG);
572
573 /*
574 * Configure the vertical sync polarity(MODESET.VDPOL)
575 * Configure the horizontal sync polarity (MODESET.HDPOL)
576 * Configure frame id polarity (MODESET.FLDPOL)
577 * Configure data polarity
578 * Configure External WEN Selection
579 * Configure frame format(progressive or interlace)
580 * Configure pixel format (Input mode)
581 * Configure the data shift
582 */
583
584 val = ISIF_VDHDOUT_INPUT | (params->vd_pol << ISIF_VD_POL_SHIFT) |
585 (params->hd_pol << ISIF_HD_POL_SHIFT) |
586 (params->fid_pol << ISIF_FID_POL_SHIFT) |
587 (ISIF_DATAPOL_NORMAL << ISIF_DATAPOL_SHIFT) |
588 (ISIF_EXWEN_DISABLE << ISIF_EXWEN_SHIFT) |
589 (params->frm_fmt << ISIF_FRM_FMT_SHIFT) |
590 (params->pix_fmt << ISIF_INPUT_SHIFT) |
591 (params->config_params.data_shift << ISIF_DATASFT_SHIFT);
592
593 regw(val, MODESET);
594 dev_dbg(isif_cfg.dev, "Writing 0x%x to MODESET...\n", val);
595
596 /*
597 * Configure GAMMAWD register
598 * CFA pattern setting
599 */
600 val = params->cfa_pat << ISIF_GAMMAWD_CFA_SHIFT;
601
602 /* Gamma msb */
603 if (module_params->compress.alg == ISIF_ALAW)
604 val |= ISIF_ALAW_ENABLE;
605
606 val |= (params->data_msb << ISIF_ALAW_GAMA_WD_SHIFT);
607 regw(val, CGAMMAWD);
608
609 /* Configure DPCM compression settings */
610 if (module_params->compress.alg == ISIF_DPCM) {
611 val = BIT(ISIF_DPCM_EN_SHIFT) |
612 (module_params->compress.pred <<
613 ISIF_DPCM_PREDICTOR_SHIFT);
614 }
615
616 regw(val, MISC);
617
618 /* Configure Gain & Offset */
619 isif_config_gain_offset();
620
621 /* Configure Color pattern */
622 val = (params->config_params.col_pat_field0.olop) |
623 (params->config_params.col_pat_field0.olep << 2) |
624 (params->config_params.col_pat_field0.elop << 4) |
625 (params->config_params.col_pat_field0.elep << 6) |
626 (params->config_params.col_pat_field1.olop << 8) |
627 (params->config_params.col_pat_field1.olep << 10) |
628 (params->config_params.col_pat_field1.elop << 12) |
629 (params->config_params.col_pat_field1.elep << 14);
630 regw(val, CCOLP);
631 dev_dbg(isif_cfg.dev, "Writing %x to CCOLP ...\n", val);
632
633 /* Configure HSIZE register */
634 val = (!!params->horz_flip_en) << ISIF_HSIZE_FLIP_SHIFT;
635
636 /* calculate line offset in 32 bytes based on pack value */
637 if (isif_cfg.data_pack == ISIF_PACK_8BIT)
638 val |= ((params->win.width + 31) >> 5);
639 else if (isif_cfg.data_pack == ISIF_PACK_12BIT)
640 val |= (((params->win.width +
641 (params->win.width >> 2)) + 31) >> 5);
642 else
643 val |= (((params->win.width * 2) + 31) >> 5);
644 regw(val, HSIZE);
645
646 /* Configure SDOFST register */
647 if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
648 if (params->image_invert_en) {
649 /* For interlace inverse mode */
650 regw(0x4B6D, SDOFST);
651 dev_dbg(isif_cfg.dev, "Writing 0x4B6D to SDOFST...\n");
652 } else {
653 /* For interlace non inverse mode */
654 regw(0x0B6D, SDOFST);
655 dev_dbg(isif_cfg.dev, "Writing 0x0B6D to SDOFST...\n");
656 }
657 } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
658 if (params->image_invert_en) {
659 /* For progressive inverse mode */
660 regw(0x4000, SDOFST);
661 dev_dbg(isif_cfg.dev, "Writing 0x4000 to SDOFST...\n");
662 } else {
663 /* For progressive non inverse mode */
664 regw(0x0000, SDOFST);
665 dev_dbg(isif_cfg.dev, "Writing 0x0000 to SDOFST...\n");
666 }
667 }
668
669 /* Configure video window */
670 isif_setwin(&params->win, params->frm_fmt, 1);
671
672 /* Configure Black Clamp */
673 isif_config_bclamp(&module_params->bclamp);
674
675 /* Configure Vertical Defection Pixel Correction */
676 if (isif_config_dfc(&module_params->dfc) < 0)
677 return -EFAULT;
678
679 if (!module_params->df_csc.df_or_csc)
680 /* Configure Color Space Conversion */
681 isif_config_csc(&module_params->df_csc);
682
683 isif_config_linearization(&module_params->linearize);
684
685 /* Configure Culling */
686 isif_config_culling(&module_params->culling);
687
688 /* Configure horizontal and vertical offsets(DFC,LSC,Gain) */
689 regw(module_params->horz_offset, DATAHOFST);
690 regw(module_params->vert_offset, DATAVOFST);
691
692 /* Setup test pattern if enabled */
693 if (params->config_params.test_pat_gen) {
694 /* Use the HD/VD pol settings from user */
695 sync.ccdpg_hdpol = params->hd_pol;
696 sync.ccdpg_vdpol = params->vd_pol;
697 dm365_vpss_set_sync_pol(sync);
698 frame_size.hlpfr = isif_cfg.bayer.win.width;
699 frame_size.pplen = isif_cfg.bayer.win.height;
700 dm365_vpss_set_pg_frame_size(frame_size);
701 vpss_select_ccdc_source(VPSS_PGLPBK);
702 }
703
704 dev_dbg(isif_cfg.dev, "\nEnd of isif_config_ycbcr...\n");
705 return 0;
706}
707
708static int isif_set_buftype(enum ccdc_buftype buf_type)
709{
710 if (isif_cfg.if_type == VPFE_RAW_BAYER)
711 isif_cfg.bayer.buf_type = buf_type;
712 else
713 isif_cfg.ycbcr.buf_type = buf_type;
714
715 return 0;
716
717}
718static enum ccdc_buftype isif_get_buftype(void)
719{
720 if (isif_cfg.if_type == VPFE_RAW_BAYER)
721 return isif_cfg.bayer.buf_type;
722
723 return isif_cfg.ycbcr.buf_type;
724}
725
726static int isif_enum_pix(u32 *pix, int i)
727{
728 int ret = -EINVAL;
729
730 if (isif_cfg.if_type == VPFE_RAW_BAYER) {
731 if (i < ARRAY_SIZE(isif_raw_bayer_pix_formats)) {
732 *pix = isif_raw_bayer_pix_formats[i];
733 ret = 0;
734 }
735 } else {
736 if (i < ARRAY_SIZE(isif_raw_yuv_pix_formats)) {
737 *pix = isif_raw_yuv_pix_formats[i];
738 ret = 0;
739 }
740 }
741
742 return ret;
743}
744
745static int isif_set_pixel_format(unsigned int pixfmt)
746{
747 if (isif_cfg.if_type == VPFE_RAW_BAYER) {
748 if (pixfmt == V4L2_PIX_FMT_SBGGR8) {
749 if ((isif_cfg.bayer.config_params.compress.alg !=
750 ISIF_ALAW) &&
751 (isif_cfg.bayer.config_params.compress.alg !=
752 ISIF_DPCM)) {
753 dev_dbg(isif_cfg.dev,
754 "Either configure A-Law or DPCM\n");
755 return -EINVAL;
756 }
757 isif_cfg.data_pack = ISIF_PACK_8BIT;
758 } else if (pixfmt == V4L2_PIX_FMT_SBGGR16) {
759 isif_cfg.bayer.config_params.compress.alg =
760 ISIF_NO_COMPRESSION;
761 isif_cfg.data_pack = ISIF_PACK_16BIT;
762 } else
763 return -EINVAL;
764 isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
765 } else {
766 if (pixfmt == V4L2_PIX_FMT_YUYV)
767 isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
768 else if (pixfmt == V4L2_PIX_FMT_UYVY)
769 isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
770 else
771 return -EINVAL;
772 isif_cfg.data_pack = ISIF_PACK_8BIT;
773 }
774 return 0;
775}
776
777static u32 isif_get_pixel_format(void)
778{
779 u32 pixfmt;
780
781 if (isif_cfg.if_type == VPFE_RAW_BAYER)
782 if (isif_cfg.bayer.config_params.compress.alg == ISIF_ALAW ||
783 isif_cfg.bayer.config_params.compress.alg == ISIF_DPCM)
784 pixfmt = V4L2_PIX_FMT_SBGGR8;
785 else
786 pixfmt = V4L2_PIX_FMT_SBGGR16;
787 else {
788 if (isif_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
789 pixfmt = V4L2_PIX_FMT_YUYV;
790 else
791 pixfmt = V4L2_PIX_FMT_UYVY;
792 }
793 return pixfmt;
794}
795
796static int isif_set_image_window(struct v4l2_rect *win)
797{
798 if (isif_cfg.if_type == VPFE_RAW_BAYER) {
799 isif_cfg.bayer.win.top = win->top;
800 isif_cfg.bayer.win.left = win->left;
801 isif_cfg.bayer.win.width = win->width;
802 isif_cfg.bayer.win.height = win->height;
803 } else {
804 isif_cfg.ycbcr.win.top = win->top;
805 isif_cfg.ycbcr.win.left = win->left;
806 isif_cfg.ycbcr.win.width = win->width;
807 isif_cfg.ycbcr.win.height = win->height;
808 }
809 return 0;
810}
811
812static void isif_get_image_window(struct v4l2_rect *win)
813{
814 if (isif_cfg.if_type == VPFE_RAW_BAYER)
815 *win = isif_cfg.bayer.win;
816 else
817 *win = isif_cfg.ycbcr.win;
818}
819
820static unsigned int isif_get_line_length(void)
821{
822 unsigned int len;
823
824 if (isif_cfg.if_type == VPFE_RAW_BAYER) {
825 if (isif_cfg.data_pack == ISIF_PACK_8BIT)
826 len = ((isif_cfg.bayer.win.width));
827 else if (isif_cfg.data_pack == ISIF_PACK_12BIT)
828 len = (((isif_cfg.bayer.win.width * 2) +
829 (isif_cfg.bayer.win.width >> 2)));
830 else
831 len = (((isif_cfg.bayer.win.width * 2)));
832 } else
833 len = (((isif_cfg.ycbcr.win.width * 2)));
834 return ALIGN(len, 32);
835}
836
837static int isif_set_frame_format(enum ccdc_frmfmt frm_fmt)
838{
839 if (isif_cfg.if_type == VPFE_RAW_BAYER)
840 isif_cfg.bayer.frm_fmt = frm_fmt;
841 else
842 isif_cfg.ycbcr.frm_fmt = frm_fmt;
843 return 0;
844}
845static enum ccdc_frmfmt isif_get_frame_format(void)
846{
847 if (isif_cfg.if_type == VPFE_RAW_BAYER)
848 return isif_cfg.bayer.frm_fmt;
849 return isif_cfg.ycbcr.frm_fmt;
850}
851
852static int isif_getfid(void)
853{
854 return (regr(MODESET) >> 15) & 0x1;
855}
856
857/* misc operations */
858static void isif_setfbaddr(unsigned long addr)
859{
860 regw((addr >> 21) & 0x07ff, CADU);
861 regw((addr >> 5) & 0x0ffff, CADL);
862}
863
864static int isif_set_hw_if_params(struct vpfe_hw_if_param *params)
865{
866 isif_cfg.if_type = params->if_type;
867
868 switch (params->if_type) {
869 case VPFE_BT656:
870 case VPFE_BT656_10BIT:
871 case VPFE_YCBCR_SYNC_8:
872 isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT;
873 isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
874 break;
875 case VPFE_BT1120:
876 case VPFE_YCBCR_SYNC_16:
877 isif_cfg.ycbcr.pix_fmt = CCDC_PIXFMT_YCBCR_16BIT;
878 isif_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
879 break;
880 case VPFE_RAW_BAYER:
881 isif_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
882 break;
883 default:
884 dev_dbg(isif_cfg.dev, "Invalid interface type\n");
885 return -EINVAL;
886 }
887
888 return 0;
889}
890
891/* This function will configure ISIF for YCbCr parameters. */
892static int isif_config_ycbcr(void)
893{
894 struct isif_ycbcr_config *params = &isif_cfg.ycbcr;
895 struct vpss_pg_frame_size frame_size;
896 u32 modeset = 0, ccdcfg = 0;
897 struct vpss_sync_pol sync;
898
899 dev_dbg(isif_cfg.dev, "\nStarting isif_config_ycbcr...");
900
901 /* configure pixel format or input mode */
902 modeset = modeset | (params->pix_fmt << ISIF_INPUT_SHIFT) |
903 (params->frm_fmt << ISIF_FRM_FMT_SHIFT) |
904 (params->fid_pol << ISIF_FID_POL_SHIFT) |
905 (params->hd_pol << ISIF_HD_POL_SHIFT) |
906 (params->vd_pol << ISIF_VD_POL_SHIFT);
907
908 /* pack the data to 8-bit ISIFCFG */
909 switch (isif_cfg.if_type) {
910 case VPFE_BT656:
911 if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
912 dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n");
913 return -EINVAL;
914 }
915 modeset |= (VPFE_PINPOL_NEGATIVE << ISIF_VD_POL_SHIFT);
916 regw(3, REC656IF);
917 ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR;
918 break;
919 case VPFE_BT656_10BIT:
920 if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
921 dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n");
922 return -EINVAL;
923 }
924 /* setup BT.656, embedded sync */
925 regw(3, REC656IF);
926 /* enable 10 bit mode in ccdcfg */
927 ccdcfg = ccdcfg | ISIF_DATA_PACK8 | ISIF_YCINSWP_YCBCR |
928 ISIF_BW656_ENABLE;
929 break;
930 case VPFE_BT1120:
931 if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) {
932 dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n");
933 return -EINVAL;
934 }
935 regw(3, REC656IF);
936 break;
937
938 case VPFE_YCBCR_SYNC_8:
939 ccdcfg |= ISIF_DATA_PACK8;
940 ccdcfg |= ISIF_YCINSWP_YCBCR;
941 if (params->pix_fmt != CCDC_PIXFMT_YCBCR_8BIT) {
942 dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n");
943 return -EINVAL;
944 }
945 break;
946 case VPFE_YCBCR_SYNC_16:
947 if (params->pix_fmt != CCDC_PIXFMT_YCBCR_16BIT) {
948 dev_dbg(isif_cfg.dev, "Invalid pix_fmt(input mode)\n");
949 return -EINVAL;
950 }
951 break;
952 default:
953 /* should never come here */
954 dev_dbg(isif_cfg.dev, "Invalid interface type\n");
955 return -EINVAL;
956 }
957
958 regw(modeset, MODESET);
959
960 /* Set up pix order */
961 ccdcfg |= params->pix_order << ISIF_PIX_ORDER_SHIFT;
962
963 regw(ccdcfg, CCDCFG);
964
965 /* configure video window */
966 if ((isif_cfg.if_type == VPFE_BT1120) ||
967 (isif_cfg.if_type == VPFE_YCBCR_SYNC_16))
968 isif_setwin(&params->win, params->frm_fmt, 1);
969 else
970 isif_setwin(&params->win, params->frm_fmt, 2);
971
972 /*
973 * configure the horizontal line offset
974 * this is done by rounding up width to a multiple of 16 pixels
975 * and multiply by two to account for y:cb:cr 4:2:2 data
976 */
977 regw(((((params->win.width * 2) + 31) & 0xffffffe0) >> 5), HSIZE);
978
979 /* configure the memory line offset */
980 if ((params->frm_fmt == CCDC_FRMFMT_INTERLACED) &&
981 (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED))
982 /* two fields are interleaved in memory */
983 regw(0x00000249, SDOFST);
984
985 /* Setup test pattern if enabled */
986 if (isif_cfg.bayer.config_params.test_pat_gen) {
987 sync.ccdpg_hdpol = params->hd_pol;
988 sync.ccdpg_vdpol = params->vd_pol;
989 dm365_vpss_set_sync_pol(sync);
990 dm365_vpss_set_pg_frame_size(frame_size);
991 }
992 return 0;
993}
994
995static int isif_configure(void)
996{
997 if (isif_cfg.if_type == VPFE_RAW_BAYER)
998 return isif_config_raw();
999 return isif_config_ycbcr();
1000}
1001
1002static int isif_close(struct device *device)
1003{
1004 /* copy defaults to module params */
1005 isif_cfg.bayer.config_params = isif_config_defaults;
1006 return 0;
1007}
1008
1009static struct ccdc_hw_device isif_hw_dev = {
1010 .name = "ISIF",
1011 .owner = THIS_MODULE,
1012 .hw_ops = {
1013 .open = isif_open,
1014 .close = isif_close,
1015 .enable = isif_enable,
1016 .enable_out_to_sdram = isif_enable_output_to_sdram,
1017 .set_hw_if_params = isif_set_hw_if_params,
1018 .configure = isif_configure,
1019 .set_buftype = isif_set_buftype,
1020 .get_buftype = isif_get_buftype,
1021 .enum_pix = isif_enum_pix,
1022 .set_pixel_format = isif_set_pixel_format,
1023 .get_pixel_format = isif_get_pixel_format,
1024 .set_frame_format = isif_set_frame_format,
1025 .get_frame_format = isif_get_frame_format,
1026 .set_image_window = isif_set_image_window,
1027 .get_image_window = isif_get_image_window,
1028 .get_line_length = isif_get_line_length,
1029 .setfbaddr = isif_setfbaddr,
1030 .getfid = isif_getfid,
1031 },
1032};
1033
1034static int __init isif_probe(struct platform_device *pdev)
1035{
1036 void (*setup_pinmux)(void);
1037 struct resource *res;
1038 void *__iomem addr;
1039 int status = 0, i;
1040
1041 /*
1042 * first try to register with vpfe. If not correct platform, then we
1043 * don't have to iomap
1044 */
1045 status = vpfe_register_ccdc_device(&isif_hw_dev);
1046 if (status < 0)
1047 return status;
1048
1049 /* Get and enable Master clock */
1050 isif_cfg.mclk = clk_get(&pdev->dev, "master");
1051 if (IS_ERR(isif_cfg.mclk)) {
1052 status = PTR_ERR(isif_cfg.mclk);
1053 goto fail_mclk;
1054 }
1055 if (clk_enable(isif_cfg.mclk)) {
1056 status = -ENODEV;
1057 goto fail_mclk;
1058 }
1059
1060 /* Platform data holds setup_pinmux function ptr */
1061 if (NULL == pdev->dev.platform_data) {
1062 status = -ENODEV;
1063 goto fail_mclk;
1064 }
1065 setup_pinmux = pdev->dev.platform_data;
1066 /*
1067 * setup Mux configuration for ccdc which may be different for
1068 * different SoCs using this CCDC
1069 */
1070 setup_pinmux();
1071
1072 i = 0;
1073 /* Get the ISIF base address, linearization table0 and table1 addr. */
1074 while (i < 3) {
1075 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1076 if (!res) {
1077 status = -ENODEV;
1078 goto fail_nobase_res;
1079 }
1080 res = request_mem_region(res->start, resource_size(res),
1081 res->name);
1082 if (!res) {
1083 status = -EBUSY;
1084 goto fail_nobase_res;
1085 }
1086 addr = ioremap_nocache(res->start, resource_size(res));
1087 if (!addr) {
1088 status = -ENOMEM;
1089 goto fail_base_iomap;
1090 }
1091 switch (i) {
1092 case 0:
1093 /* ISIF base address */
1094 isif_cfg.base_addr = addr;
1095 break;
1096 case 1:
1097 /* ISIF linear tbl0 address */
1098 isif_cfg.linear_tbl0_addr = addr;
1099 break;
1100 default:
1101 /* ISIF linear tbl0 address */
1102 isif_cfg.linear_tbl1_addr = addr;
1103 break;
1104 }
1105 i++;
1106 }
1107 isif_cfg.dev = &pdev->dev;
1108
1109 printk(KERN_NOTICE "%s is registered with vpfe.\n",
1110 isif_hw_dev.name);
1111 return 0;
1112fail_base_iomap:
1113 release_mem_region(res->start, resource_size(res));
1114 i--;
1115fail_nobase_res:
1116 if (isif_cfg.base_addr)
1117 iounmap(isif_cfg.base_addr);
1118 if (isif_cfg.linear_tbl0_addr)
1119 iounmap(isif_cfg.linear_tbl0_addr);
1120
1121 while (i >= 0) {
1122 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1123 release_mem_region(res->start, resource_size(res));
1124 i--;
1125 }
1126fail_mclk:
1127 clk_put(isif_cfg.mclk);
1128 vpfe_unregister_ccdc_device(&isif_hw_dev);
1129 return status;
1130}
1131
1132static int isif_remove(struct platform_device *pdev)
1133{
1134 struct resource *res;
1135 int i = 0;
1136
1137 iounmap(isif_cfg.base_addr);
1138 iounmap(isif_cfg.linear_tbl0_addr);
1139 iounmap(isif_cfg.linear_tbl1_addr);
1140 while (i < 3) {
1141 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
1142 if (res)
1143 release_mem_region(res->start, resource_size(res));
1144 i++;
1145 }
1146 vpfe_unregister_ccdc_device(&isif_hw_dev);
1147 return 0;
1148}
1149
1150static struct platform_driver isif_driver = {
1151 .driver = {
1152 .name = "isif",
1153 .owner = THIS_MODULE,
1154 },
1155 .remove = __devexit_p(isif_remove),
1156 .probe = isif_probe,
1157};
1158
1159static int __init isif_init(void)
1160{
1161 return platform_driver_register(&isif_driver);
1162}
1163
1164static void isif_exit(void)
1165{
1166 platform_driver_unregister(&isif_driver);
1167}
1168
1169module_init(isif_init);
1170module_exit(isif_exit);
1171
1172MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/davinci/isif_regs.h b/drivers/media/video/davinci/isif_regs.h
new file mode 100644
index 00000000000..aa69a463c12
--- /dev/null
+++ b/drivers/media/video/davinci/isif_regs.h
@@ -0,0 +1,269 @@
1/*
2 * Copyright (C) 2008-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18#ifndef _ISIF_REGS_H
19#define _ISIF_REGS_H
20
21/* ISIF registers relative offsets */
22#define SYNCEN 0x00
23#define MODESET 0x04
24#define HDW 0x08
25#define VDW 0x0c
26#define PPLN 0x10
27#define LPFR 0x14
28#define SPH 0x18
29#define LNH 0x1c
30#define SLV0 0x20
31#define SLV1 0x24
32#define LNV 0x28
33#define CULH 0x2c
34#define CULV 0x30
35#define HSIZE 0x34
36#define SDOFST 0x38
37#define CADU 0x3c
38#define CADL 0x40
39#define LINCFG0 0x44
40#define LINCFG1 0x48
41#define CCOLP 0x4c
42#define CRGAIN 0x50
43#define CGRGAIN 0x54
44#define CGBGAIN 0x58
45#define CBGAIN 0x5c
46#define COFSTA 0x60
47#define FLSHCFG0 0x64
48#define FLSHCFG1 0x68
49#define FLSHCFG2 0x6c
50#define VDINT0 0x70
51#define VDINT1 0x74
52#define VDINT2 0x78
53#define MISC 0x7c
54#define CGAMMAWD 0x80
55#define REC656IF 0x84
56#define CCDCFG 0x88
57/*****************************************************
58* Defect Correction registers
59*****************************************************/
60#define DFCCTL 0x8c
61#define VDFSATLV 0x90
62#define DFCMEMCTL 0x94
63#define DFCMEM0 0x98
64#define DFCMEM1 0x9c
65#define DFCMEM2 0xa0
66#define DFCMEM3 0xa4
67#define DFCMEM4 0xa8
68/****************************************************
69* Black Clamp registers
70****************************************************/
71#define CLAMPCFG 0xac
72#define CLDCOFST 0xb0
73#define CLSV 0xb4
74#define CLHWIN0 0xb8
75#define CLHWIN1 0xbc
76#define CLHWIN2 0xc0
77#define CLVRV 0xc4
78#define CLVWIN0 0xc8
79#define CLVWIN1 0xcc
80#define CLVWIN2 0xd0
81#define CLVWIN3 0xd4
82/****************************************************
83* Lense Shading Correction
84****************************************************/
85#define DATAHOFST 0xd8
86#define DATAVOFST 0xdc
87#define LSCHVAL 0xe0
88#define LSCVVAL 0xe4
89#define TWODLSCCFG 0xe8
90#define TWODLSCOFST 0xec
91#define TWODLSCINI 0xf0
92#define TWODLSCGRBU 0xf4
93#define TWODLSCGRBL 0xf8
94#define TWODLSCGROF 0xfc
95#define TWODLSCORBU 0x100
96#define TWODLSCORBL 0x104
97#define TWODLSCOROF 0x108
98#define TWODLSCIRQEN 0x10c
99#define TWODLSCIRQST 0x110
100/****************************************************
101* Data formatter
102****************************************************/
103#define FMTCFG 0x114
104#define FMTPLEN 0x118
105#define FMTSPH 0x11c
106#define FMTLNH 0x120
107#define FMTSLV 0x124
108#define FMTLNV 0x128
109#define FMTRLEN 0x12c
110#define FMTHCNT 0x130
111#define FMTAPTR_BASE 0x134
112/* Below macro for addresses FMTAPTR0 - FMTAPTR15 */
113#define FMTAPTR(i) (FMTAPTR_BASE + (i * 4))
114#define FMTPGMVF0 0x174
115#define FMTPGMVF1 0x178
116#define FMTPGMAPU0 0x17c
117#define FMTPGMAPU1 0x180
118#define FMTPGMAPS0 0x184
119#define FMTPGMAPS1 0x188
120#define FMTPGMAPS2 0x18c
121#define FMTPGMAPS3 0x190
122#define FMTPGMAPS4 0x194
123#define FMTPGMAPS5 0x198
124#define FMTPGMAPS6 0x19c
125#define FMTPGMAPS7 0x1a0
126/************************************************
127* Color Space Converter
128************************************************/
129#define CSCCTL 0x1a4
130#define CSCM0 0x1a8
131#define CSCM1 0x1ac
132#define CSCM2 0x1b0
133#define CSCM3 0x1b4
134#define CSCM4 0x1b8
135#define CSCM5 0x1bc
136#define CSCM6 0x1c0
137#define CSCM7 0x1c4
138#define OBWIN0 0x1c8
139#define OBWIN1 0x1cc
140#define OBWIN2 0x1d0
141#define OBWIN3 0x1d4
142#define OBVAL0 0x1d8
143#define OBVAL1 0x1dc
144#define OBVAL2 0x1e0
145#define OBVAL3 0x1e4
146#define OBVAL4 0x1e8
147#define OBVAL5 0x1ec
148#define OBVAL6 0x1f0
149#define OBVAL7 0x1f4
150#define CLKCTL 0x1f8
151
152/* Masks & Shifts below */
153#define START_PX_HOR_MASK 0x7FFF
154#define NUM_PX_HOR_MASK 0x7FFF
155#define START_VER_ONE_MASK 0x7FFF
156#define START_VER_TWO_MASK 0x7FFF
157#define NUM_LINES_VER 0x7FFF
158
159/* gain - offset masks */
160#define GAIN_INTEGER_SHIFT 9
161#define OFFSET_MASK 0xFFF
162#define GAIN_SDRAM_EN_SHIFT 12
163#define GAIN_IPIPE_EN_SHIFT 13
164#define GAIN_H3A_EN_SHIFT 14
165#define OFST_SDRAM_EN_SHIFT 8
166#define OFST_IPIPE_EN_SHIFT 9
167#define OFST_H3A_EN_SHIFT 10
168#define GAIN_OFFSET_EN_MASK 0x7700
169
170/* Culling */
171#define CULL_PAT_EVEN_LINE_SHIFT 8
172
173/* CCDCFG register */
174#define ISIF_YCINSWP_RAW (0x00 << 4)
175#define ISIF_YCINSWP_YCBCR (0x01 << 4)
176#define ISIF_CCDCFG_FIDMD_LATCH_VSYNC (0x00 << 6)
177#define ISIF_CCDCFG_WENLOG_AND (0x00 << 8)
178#define ISIF_CCDCFG_TRGSEL_WEN (0x00 << 9)
179#define ISIF_CCDCFG_EXTRG_DISABLE (0x00 << 10)
180#define ISIF_LATCH_ON_VSYNC_DISABLE (0x01 << 15)
181#define ISIF_LATCH_ON_VSYNC_ENABLE (0x00 << 15)
182#define ISIF_DATA_PACK_MASK 3
183#define ISIF_DATA_PACK16 0
184#define ISIF_DATA_PACK12 1
185#define ISIF_DATA_PACK8 2
186#define ISIF_PIX_ORDER_SHIFT 11
187#define ISIF_BW656_ENABLE (0x01 << 5)
188
189/* MODESET registers */
190#define ISIF_VDHDOUT_INPUT (0x00 << 0)
191#define ISIF_INPUT_SHIFT 12
192#define ISIF_RAW_INPUT_MODE 0
193#define ISIF_FID_POL_SHIFT 4
194#define ISIF_HD_POL_SHIFT 3
195#define ISIF_VD_POL_SHIFT 2
196#define ISIF_DATAPOL_NORMAL 0
197#define ISIF_DATAPOL_SHIFT 6
198#define ISIF_EXWEN_DISABLE 0
199#define ISIF_EXWEN_SHIFT 5
200#define ISIF_FRM_FMT_SHIFT 7
201#define ISIF_DATASFT_SHIFT 8
202#define ISIF_LPF_SHIFT 14
203#define ISIF_LPF_MASK 1
204
205/* GAMMAWD registers */
206#define ISIF_ALAW_GAMA_WD_MASK 0xF
207#define ISIF_ALAW_GAMA_WD_SHIFT 1
208#define ISIF_ALAW_ENABLE 1
209#define ISIF_GAMMAWD_CFA_SHIFT 5
210
211/* HSIZE registers */
212#define ISIF_HSIZE_FLIP_MASK 1
213#define ISIF_HSIZE_FLIP_SHIFT 12
214
215/* MISC registers */
216#define ISIF_DPCM_EN_SHIFT 12
217#define ISIF_DPCM_PREDICTOR_SHIFT 13
218
219/* Black clamp related */
220#define ISIF_BC_MODE_COLOR_SHIFT 4
221#define ISIF_HORZ_BC_MODE_SHIFT 1
222#define ISIF_HORZ_BC_WIN_SEL_SHIFT 5
223#define ISIF_HORZ_BC_PIX_LIMIT_SHIFT 6
224#define ISIF_HORZ_BC_WIN_H_SIZE_SHIFT 8
225#define ISIF_HORZ_BC_WIN_V_SIZE_SHIFT 12
226#define ISIF_VERT_BC_RST_VAL_SEL_SHIFT 4
227#define ISIF_VERT_BC_LINE_AVE_COEF_SHIFT 8
228
229/* VDFC registers */
230#define ISIF_VDFC_EN_SHIFT 4
231#define ISIF_VDFC_CORR_MOD_SHIFT 5
232#define ISIF_VDFC_CORR_WHOLE_LN_SHIFT 7
233#define ISIF_VDFC_LEVEL_SHFT_SHIFT 8
234#define ISIF_VDFC_POS_MASK 0x1FFF
235#define ISIF_DFCMEMCTL_DFCMARST_SHIFT 2
236
237/* CSC registers */
238#define ISIF_CSC_COEF_INTEG_MASK 7
239#define ISIF_CSC_COEF_DECIMAL_MASK 0x1f
240#define ISIF_CSC_COEF_INTEG_SHIFT 5
241#define ISIF_CSCM_MSB_SHIFT 8
242#define ISIF_DF_CSC_SPH_MASK 0x1FFF
243#define ISIF_DF_CSC_LNH_MASK 0x1FFF
244#define ISIF_DF_CSC_SLV_MASK 0x1FFF
245#define ISIF_DF_CSC_LNV_MASK 0x1FFF
246#define ISIF_DF_NUMLINES 0x7FFF
247#define ISIF_DF_NUMPIX 0x1FFF
248
249/* Offsets for LSC/DFC/Gain */
250#define ISIF_DATA_H_OFFSET_MASK 0x1FFF
251#define ISIF_DATA_V_OFFSET_MASK 0x1FFF
252
253/* Linearization */
254#define ISIF_LIN_CORRSFT_SHIFT 4
255#define ISIF_LIN_SCALE_FACT_INTEG_SHIFT 10
256
257
258/* Pattern registers */
259#define ISIF_PG_EN (1 << 3)
260#define ISIF_SEL_PG_SRC (3 << 4)
261#define ISIF_PG_VD_POL_SHIFT 0
262#define ISIF_PG_HD_POL_SHIFT 1
263
264/*random other junk*/
265#define ISIF_SYNCEN_VDHDEN_MASK (1 << 0)
266#define ISIF_SYNCEN_WEN_MASK (1 << 1)
267#define ISIF_SYNCEN_WEN_SHIFT 1
268
269#endif
diff --git a/drivers/media/video/davinci/vpbe.c b/drivers/media/video/davinci/vpbe.c
new file mode 100644
index 00000000000..d773d30de22
--- /dev/null
+++ b/drivers/media/video/davinci/vpbe.c
@@ -0,0 +1,864 @@
1/*
2 * Copyright (C) 2010 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/errno.h>
21#include <linux/fs.h>
22#include <linux/string.h>
23#include <linux/wait.h>
24#include <linux/time.h>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/slab.h>
28#include <linux/clk.h>
29#include <linux/err.h>
30
31#include <media/v4l2-device.h>
32#include <media/davinci/vpbe_types.h>
33#include <media/davinci/vpbe.h>
34#include <media/davinci/vpss.h>
35#include <media/davinci/vpbe_venc.h>
36
37#define VPBE_DEFAULT_OUTPUT "Composite"
38#define VPBE_DEFAULT_MODE "ntsc"
39
40static char *def_output = VPBE_DEFAULT_OUTPUT;
41static char *def_mode = VPBE_DEFAULT_MODE;
42static int debug;
43
44module_param(def_output, charp, S_IRUGO);
45module_param(def_mode, charp, S_IRUGO);
46module_param(debug, int, 0644);
47
48MODULE_PARM_DESC(def_output, "vpbe output name (default:Composite)");
49MODULE_PARM_DESC(def_mode, "vpbe output mode name (default:ntsc");
50MODULE_PARM_DESC(debug, "Debug level 0-1");
51
52MODULE_DESCRIPTION("TI DMXXX VPBE Display controller");
53MODULE_LICENSE("GPL");
54MODULE_AUTHOR("Texas Instruments");
55
56/**
57 * vpbe_current_encoder_info - Get config info for current encoder
58 * @vpbe_dev - vpbe device ptr
59 *
60 * Return ptr to current encoder config info
61 */
62static struct encoder_config_info*
63vpbe_current_encoder_info(struct vpbe_device *vpbe_dev)
64{
65 struct vpbe_config *cfg = vpbe_dev->cfg;
66 int index = vpbe_dev->current_sd_index;
67
68 return ((index == 0) ? &cfg->venc :
69 &cfg->ext_encoders[index-1]);
70}
71
72/**
73 * vpbe_find_encoder_sd_index - Given a name find encoder sd index
74 *
75 * @vpbe_config - ptr to vpbe cfg
76 * @output_index - index used by application
77 *
78 * Return sd index of the encoder
79 */
80static int vpbe_find_encoder_sd_index(struct vpbe_config *cfg,
81 int index)
82{
83 char *encoder_name = cfg->outputs[index].subdev_name;
84 int i;
85
86 /* Venc is always first */
87 if (!strcmp(encoder_name, cfg->venc.module_name))
88 return 0;
89
90 for (i = 0; i < cfg->num_ext_encoders; i++) {
91 if (!strcmp(encoder_name,
92 cfg->ext_encoders[i].module_name))
93 return i+1;
94 }
95
96 return -EINVAL;
97}
98
99/**
100 * vpbe_g_cropcap - Get crop capabilities of the display
101 * @vpbe_dev - vpbe device ptr
102 * @cropcap - cropcap is a ptr to struct v4l2_cropcap
103 *
104 * Update the crop capabilities in crop cap for current
105 * mode
106 */
107static int vpbe_g_cropcap(struct vpbe_device *vpbe_dev,
108 struct v4l2_cropcap *cropcap)
109{
110 if (NULL == cropcap)
111 return -EINVAL;
112 cropcap->bounds.left = 0;
113 cropcap->bounds.top = 0;
114 cropcap->bounds.width = vpbe_dev->current_timings.xres;
115 cropcap->bounds.height = vpbe_dev->current_timings.yres;
116 cropcap->defrect = cropcap->bounds;
117
118 return 0;
119}
120
121/**
122 * vpbe_enum_outputs - enumerate outputs
123 * @vpbe_dev - vpbe device ptr
124 * @output - ptr to v4l2_output structure
125 *
126 * Enumerates the outputs available at the vpbe display
127 * returns the status, -EINVAL if end of output list
128 */
129static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev,
130 struct v4l2_output *output)
131{
132 struct vpbe_config *cfg = vpbe_dev->cfg;
133 int temp_index = output->index;
134
135 if (temp_index >= cfg->num_outputs)
136 return -EINVAL;
137
138 *output = cfg->outputs[temp_index].output;
139 output->index = temp_index;
140
141 return 0;
142}
143
144static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode)
145{
146 struct vpbe_config *cfg = vpbe_dev->cfg;
147 struct vpbe_enc_mode_info var;
148 int curr_output = vpbe_dev->current_out_index;
149 int i;
150
151 if (NULL == mode)
152 return -EINVAL;
153
154 for (i = 0; i < cfg->outputs[curr_output].num_modes; i++) {
155 var = cfg->outputs[curr_output].modes[i];
156 if (!strcmp(mode, var.name)) {
157 vpbe_dev->current_timings = var;
158 return 0;
159 }
160 }
161
162 return -EINVAL;
163}
164
165static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
166 struct vpbe_enc_mode_info *mode_info)
167{
168 if (NULL == mode_info)
169 return -EINVAL;
170
171 *mode_info = vpbe_dev->current_timings;
172
173 return 0;
174}
175
176static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev,
177 unsigned int dv_preset)
178{
179 struct vpbe_config *cfg = vpbe_dev->cfg;
180 struct vpbe_enc_mode_info var;
181 int curr_output = vpbe_dev->current_out_index;
182 int i;
183
184 for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
185 var = cfg->outputs[curr_output].modes[i];
186 if ((var.timings_type & VPBE_ENC_DV_PRESET) &&
187 (var.timings.dv_preset == dv_preset)) {
188 vpbe_dev->current_timings = var;
189 return 0;
190 }
191 }
192
193 return -EINVAL;
194}
195
196/* Get std by std id */
197static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
198 v4l2_std_id std_id)
199{
200 struct vpbe_config *cfg = vpbe_dev->cfg;
201 struct vpbe_enc_mode_info var;
202 int curr_output = vpbe_dev->current_out_index;
203 int i;
204
205 for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
206 var = cfg->outputs[curr_output].modes[i];
207 if ((var.timings_type & VPBE_ENC_STD) &&
208 (var.timings.std_id & std_id)) {
209 vpbe_dev->current_timings = var;
210 return 0;
211 }
212 }
213
214 return -EINVAL;
215}
216
217static int vpbe_get_std_info_by_name(struct vpbe_device *vpbe_dev,
218 char *std_name)
219{
220 struct vpbe_config *cfg = vpbe_dev->cfg;
221 struct vpbe_enc_mode_info var;
222 int curr_output = vpbe_dev->current_out_index;
223 int i;
224
225 for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
226 var = cfg->outputs[curr_output].modes[i];
227 if (!strcmp(var.name, std_name)) {
228 vpbe_dev->current_timings = var;
229 return 0;
230 }
231 }
232
233 return -EINVAL;
234}
235
236/**
237 * vpbe_set_output - Set output
238 * @vpbe_dev - vpbe device ptr
239 * @index - index of output
240 *
241 * Set vpbe output to the output specified by the index
242 */
243static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index)
244{
245 struct encoder_config_info *curr_enc_info =
246 vpbe_current_encoder_info(vpbe_dev);
247 struct vpbe_config *cfg = vpbe_dev->cfg;
248 int enc_out_index;
249 int sd_index;
250 int ret = 0;
251
252 if (index >= cfg->num_outputs)
253 return -EINVAL;
254
255 mutex_lock(&vpbe_dev->lock);
256
257 sd_index = vpbe_dev->current_sd_index;
258 enc_out_index = cfg->outputs[index].output.index;
259 /*
260 * Currently we switch the encoder based on output selected
261 * by the application. If media controller is implemented later
262 * there is will be an API added to setup_link between venc
263 * and external encoder. So in that case below comparison always
264 * match and encoder will not be switched. But if application
265 * chose not to use media controller, then this provides current
266 * way of switching encoder at the venc output.
267 */
268 if (strcmp(curr_enc_info->module_name,
269 cfg->outputs[index].subdev_name)) {
270 /* Need to switch the encoder at the output */
271 sd_index = vpbe_find_encoder_sd_index(cfg, index);
272 if (sd_index < 0) {
273 ret = -EINVAL;
274 goto out;
275 }
276
277 if (ret)
278 goto out;
279 }
280
281 /* Set output at the encoder */
282 ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
283 s_routing, 0, enc_out_index, 0);
284 if (ret)
285 goto out;
286
287 /*
288 * It is assumed that venc or extenal encoder will set a default
289 * mode in the sub device. For external encoder or LCD pannel output,
290 * we also need to set up the lcd port for the required mode. So setup
291 * the lcd port for the default mode that is configured in the board
292 * arch/arm/mach-davinci/board-dm355-evm.setup file for the external
293 * encoder.
294 */
295 ret = vpbe_get_mode_info(vpbe_dev,
296 cfg->outputs[index].default_mode);
297 if (!ret) {
298 struct osd_state *osd_device = vpbe_dev->osd_device;
299
300 osd_device->ops.set_left_margin(osd_device,
301 vpbe_dev->current_timings.left_margin);
302 osd_device->ops.set_top_margin(osd_device,
303 vpbe_dev->current_timings.upper_margin);
304 vpbe_dev->current_sd_index = sd_index;
305 vpbe_dev->current_out_index = index;
306 }
307out:
308 mutex_unlock(&vpbe_dev->lock);
309 return ret;
310}
311
312static int vpbe_set_default_output(struct vpbe_device *vpbe_dev)
313{
314 struct vpbe_config *cfg = vpbe_dev->cfg;
315 int ret = 0;
316 int i;
317
318 for (i = 0; i < cfg->num_outputs; i++) {
319 if (!strcmp(def_output,
320 cfg->outputs[i].output.name)) {
321 ret = vpbe_set_output(vpbe_dev, i);
322 if (!ret)
323 vpbe_dev->current_out_index = i;
324 return ret;
325 }
326 }
327 return ret;
328}
329
330/**
331 * vpbe_get_output - Get output
332 * @vpbe_dev - vpbe device ptr
333 *
334 * return current vpbe output to the the index
335 */
336static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
337{
338 return vpbe_dev->current_out_index;
339}
340
341/**
342 * vpbe_s_dv_preset - Set the given preset timings in the encoder
343 *
344 * Sets the preset if supported by the current encoder. Return the status.
345 * 0 - success & -EINVAL on error
346 */
347static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
348 struct v4l2_dv_preset *dv_preset)
349{
350 struct vpbe_config *cfg = vpbe_dev->cfg;
351 int out_index = vpbe_dev->current_out_index;
352 int sd_index = vpbe_dev->current_sd_index;
353 int ret;
354
355
356 if (!(cfg->outputs[out_index].output.capabilities &
357 V4L2_OUT_CAP_PRESETS))
358 return -EINVAL;
359
360 ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset);
361
362 if (ret)
363 return ret;
364
365 mutex_lock(&vpbe_dev->lock);
366
367
368 ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
369 s_dv_preset, dv_preset);
370 /* set the lcd controller output for the given mode */
371 if (!ret) {
372 struct osd_state *osd_device = vpbe_dev->osd_device;
373
374 osd_device->ops.set_left_margin(osd_device,
375 vpbe_dev->current_timings.left_margin);
376 osd_device->ops.set_top_margin(osd_device,
377 vpbe_dev->current_timings.upper_margin);
378 }
379 mutex_unlock(&vpbe_dev->lock);
380
381 return ret;
382}
383
384/**
385 * vpbe_g_dv_preset - Get the preset in the current encoder
386 *
387 * Get the preset in the current encoder. Return the status. 0 - success
388 * -EINVAL on error
389 */
390static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
391 struct v4l2_dv_preset *dv_preset)
392{
393 if (vpbe_dev->current_timings.timings_type &
394 VPBE_ENC_DV_PRESET) {
395 dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset;
396 return 0;
397 }
398
399 return -EINVAL;
400}
401
402/**
403 * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder
404 *
405 * Get the preset in the current encoder. Return the status. 0 - success
406 * -EINVAL on error
407 */
408static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
409 struct v4l2_dv_enum_preset *preset_info)
410{
411 struct vpbe_config *cfg = vpbe_dev->cfg;
412 int out_index = vpbe_dev->current_out_index;
413 struct vpbe_output *output = &cfg->outputs[out_index];
414 int j = 0;
415 int i;
416
417 if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS))
418 return -EINVAL;
419
420 for (i = 0; i < output->num_modes; i++) {
421 if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) {
422 if (j == preset_info->index)
423 break;
424 j++;
425 }
426 }
427
428 if (i == output->num_modes)
429 return -EINVAL;
430
431 return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset,
432 preset_info);
433}
434
435/**
436 * vpbe_s_std - Set the given standard in the encoder
437 *
438 * Sets the standard if supported by the current encoder. Return the status.
439 * 0 - success & -EINVAL on error
440 */
441static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
442{
443 struct vpbe_config *cfg = vpbe_dev->cfg;
444 int out_index = vpbe_dev->current_out_index;
445 int sd_index = vpbe_dev->current_sd_index;
446 int ret;
447
448 if (!(cfg->outputs[out_index].output.capabilities &
449 V4L2_OUT_CAP_STD))
450 return -EINVAL;
451
452 ret = vpbe_get_std_info(vpbe_dev, *std_id);
453 if (ret)
454 return ret;
455
456 mutex_lock(&vpbe_dev->lock);
457
458 ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
459 s_std_output, *std_id);
460 /* set the lcd controller output for the given mode */
461 if (!ret) {
462 struct osd_state *osd_device = vpbe_dev->osd_device;
463
464 osd_device->ops.set_left_margin(osd_device,
465 vpbe_dev->current_timings.left_margin);
466 osd_device->ops.set_top_margin(osd_device,
467 vpbe_dev->current_timings.upper_margin);
468 }
469 mutex_unlock(&vpbe_dev->lock);
470
471 return ret;
472}
473
474/**
475 * vpbe_g_std - Get the standard in the current encoder
476 *
477 * Get the standard in the current encoder. Return the status. 0 - success
478 * -EINVAL on error
479 */
480static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
481{
482 struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings;
483
484 if (cur_timings.timings_type & VPBE_ENC_STD) {
485 *std_id = cur_timings.timings.std_id;
486 return 0;
487 }
488
489 return -EINVAL;
490}
491
492/**
493 * vpbe_set_mode - Set mode in the current encoder using mode info
494 *
495 * Use the mode string to decide what timings to set in the encoder
496 * This is typically useful when fbset command is used to change the current
497 * timings by specifying a string to indicate the timings.
498 */
499static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
500 struct vpbe_enc_mode_info *mode_info)
501{
502 struct vpbe_enc_mode_info *preset_mode = NULL;
503 struct vpbe_config *cfg = vpbe_dev->cfg;
504 struct v4l2_dv_preset dv_preset;
505 struct osd_state *osd_device;
506 int out_index = vpbe_dev->current_out_index;
507 int ret = 0;
508 int i;
509
510 if ((NULL == mode_info) || (NULL == mode_info->name))
511 return -EINVAL;
512
513 for (i = 0; i < cfg->outputs[out_index].num_modes; i++) {
514 if (!strcmp(mode_info->name,
515 cfg->outputs[out_index].modes[i].name)) {
516 preset_mode = &cfg->outputs[out_index].modes[i];
517 /*
518 * it may be one of the 3 timings type. Check and
519 * invoke right API
520 */
521 if (preset_mode->timings_type & VPBE_ENC_STD)
522 return vpbe_s_std(vpbe_dev,
523 &preset_mode->timings.std_id);
524 if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) {
525 dv_preset.preset =
526 preset_mode->timings.dv_preset;
527 return vpbe_s_dv_preset(vpbe_dev, &dv_preset);
528 }
529 }
530 }
531
532 /* Only custom timing should reach here */
533 if (preset_mode == NULL)
534 return -EINVAL;
535
536 mutex_lock(&vpbe_dev->lock);
537
538 osd_device = vpbe_dev->osd_device;
539 vpbe_dev->current_timings = *preset_mode;
540 osd_device->ops.set_left_margin(osd_device,
541 vpbe_dev->current_timings.left_margin);
542 osd_device->ops.set_top_margin(osd_device,
543 vpbe_dev->current_timings.upper_margin);
544
545 mutex_unlock(&vpbe_dev->lock);
546
547 return ret;
548}
549
550static int vpbe_set_default_mode(struct vpbe_device *vpbe_dev)
551{
552 int ret;
553
554 ret = vpbe_get_std_info_by_name(vpbe_dev, def_mode);
555 if (ret)
556 return ret;
557
558 /* set the default mode in the encoder */
559 return vpbe_set_mode(vpbe_dev, &vpbe_dev->current_timings);
560}
561
562static int platform_device_get(struct device *dev, void *data)
563{
564 struct platform_device *pdev = to_platform_device(dev);
565 struct vpbe_device *vpbe_dev = data;
566
567 if (strcmp("vpbe-osd", pdev->name) == 0)
568 vpbe_dev->osd_device = platform_get_drvdata(pdev);
569
570 return 0;
571}
572
573/**
574 * vpbe_initialize() - Initialize the vpbe display controller
575 * @vpbe_dev - vpbe device ptr
576 *
577 * Master frame buffer device drivers calls this to initialize vpbe
578 * display controller. This will then registers v4l2 device and the sub
579 * devices and sets a current encoder sub device for display. v4l2 display
580 * device driver is the master and frame buffer display device driver is
581 * the slave. Frame buffer display driver checks the initialized during
582 * probe and exit if not initialized. Returns status.
583 */
584static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev)
585{
586 struct encoder_config_info *enc_info;
587 struct v4l2_subdev **enc_subdev;
588 struct osd_state *osd_device;
589 struct i2c_adapter *i2c_adap;
590 int output_index;
591 int num_encoders;
592 int ret = 0;
593 int err;
594 int i;
595
596 /*
597 * v4l2 abd FBDev frame buffer devices will get the vpbe_dev pointer
598 * from the platform device by iteration of platform drivers and
599 * matching with device name
600 */
601 if (NULL == vpbe_dev || NULL == dev) {
602 printk(KERN_ERR "Null device pointers.\n");
603 return -ENODEV;
604 }
605
606 if (vpbe_dev->initialized)
607 return 0;
608
609 mutex_lock(&vpbe_dev->lock);
610
611 if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) {
612 /* We have dac clock available for platform */
613 vpbe_dev->dac_clk = clk_get(vpbe_dev->pdev, "vpss_dac");
614 if (IS_ERR(vpbe_dev->dac_clk)) {
615 ret = PTR_ERR(vpbe_dev->dac_clk);
616 goto vpbe_unlock;
617 }
618 if (clk_enable(vpbe_dev->dac_clk)) {
619 ret = -ENODEV;
620 goto vpbe_unlock;
621 }
622 }
623
624 /* first enable vpss clocks */
625 vpss_enable_clock(VPSS_VPBE_CLOCK, 1);
626
627 /* First register a v4l2 device */
628 ret = v4l2_device_register(dev, &vpbe_dev->v4l2_dev);
629 if (ret) {
630 v4l2_err(dev->driver,
631 "Unable to register v4l2 device.\n");
632 goto vpbe_fail_clock;
633 }
634 v4l2_info(&vpbe_dev->v4l2_dev, "vpbe v4l2 device registered\n");
635
636 err = bus_for_each_dev(&platform_bus_type, NULL, vpbe_dev,
637 platform_device_get);
638 if (err < 0)
639 return err;
640
641 vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev,
642 vpbe_dev->cfg->venc.module_name);
643 /* register venc sub device */
644 if (vpbe_dev->venc == NULL) {
645 v4l2_err(&vpbe_dev->v4l2_dev,
646 "vpbe unable to init venc sub device\n");
647 ret = -ENODEV;
648 goto vpbe_fail_v4l2_device;
649 }
650 /* initialize osd device */
651 osd_device = vpbe_dev->osd_device;
652
653 if (NULL != osd_device->ops.initialize) {
654 err = osd_device->ops.initialize(osd_device);
655 if (err) {
656 v4l2_err(&vpbe_dev->v4l2_dev,
657 "unable to initialize the OSD device");
658 err = -ENOMEM;
659 goto vpbe_fail_v4l2_device;
660 }
661 }
662
663 /*
664 * Register any external encoders that are configured. At index 0 we
665 * store venc sd index.
666 */
667 num_encoders = vpbe_dev->cfg->num_ext_encoders + 1;
668 vpbe_dev->encoders = kmalloc(
669 sizeof(struct v4l2_subdev *)*num_encoders,
670 GFP_KERNEL);
671 if (NULL == vpbe_dev->encoders) {
672 v4l2_err(&vpbe_dev->v4l2_dev,
673 "unable to allocate memory for encoders sub devices");
674 ret = -ENOMEM;
675 goto vpbe_fail_v4l2_device;
676 }
677
678 i2c_adap = i2c_get_adapter(vpbe_dev->cfg->i2c_adapter_id);
679 for (i = 0; i < (vpbe_dev->cfg->num_ext_encoders + 1); i++) {
680 if (i == 0) {
681 /* venc is at index 0 */
682 enc_subdev = &vpbe_dev->encoders[i];
683 *enc_subdev = vpbe_dev->venc;
684 continue;
685 }
686 enc_info = &vpbe_dev->cfg->ext_encoders[i];
687 if (enc_info->is_i2c) {
688 enc_subdev = &vpbe_dev->encoders[i];
689 *enc_subdev = v4l2_i2c_new_subdev_board(
690 &vpbe_dev->v4l2_dev, i2c_adap,
691 &enc_info->board_info, NULL);
692 if (*enc_subdev)
693 v4l2_info(&vpbe_dev->v4l2_dev,
694 "v4l2 sub device %s registered\n",
695 enc_info->module_name);
696 else {
697 v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s"
698 " failed to register",
699 enc_info->module_name);
700 ret = -ENODEV;
701 goto vpbe_fail_sd_register;
702 }
703 } else
704 v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
705 " currently not supported");
706 }
707
708 /* set the current encoder and output to that of venc by default */
709 vpbe_dev->current_sd_index = 0;
710 vpbe_dev->current_out_index = 0;
711 output_index = 0;
712
713 mutex_unlock(&vpbe_dev->lock);
714
715 printk(KERN_NOTICE "Setting default output to %s\n", def_output);
716 ret = vpbe_set_default_output(vpbe_dev);
717 if (ret) {
718 v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default output %s",
719 def_output);
720 return ret;
721 }
722
723 printk(KERN_NOTICE "Setting default mode to %s\n", def_mode);
724 ret = vpbe_set_default_mode(vpbe_dev);
725 if (ret) {
726 v4l2_err(&vpbe_dev->v4l2_dev, "Failed to set default mode %s",
727 def_mode);
728 return ret;
729 }
730 vpbe_dev->initialized = 1;
731 /* TBD handling of bootargs for default output and mode */
732 return 0;
733
734vpbe_fail_sd_register:
735 kfree(vpbe_dev->encoders);
736vpbe_fail_v4l2_device:
737 v4l2_device_unregister(&vpbe_dev->v4l2_dev);
738vpbe_fail_clock:
739 if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
740 clk_put(vpbe_dev->dac_clk);
741vpbe_unlock:
742 mutex_unlock(&vpbe_dev->lock);
743 return ret;
744}
745
746/**
747 * vpbe_deinitialize() - de-initialize the vpbe display controller
748 * @dev - Master and slave device ptr
749 *
750 * vpbe_master and slave frame buffer devices calls this to de-initialize
751 * the display controller. It is called when master and slave device
752 * driver modules are removed and no longer requires the display controller.
753 */
754static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev)
755{
756 v4l2_device_unregister(&vpbe_dev->v4l2_dev);
757 if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0)
758 clk_put(vpbe_dev->dac_clk);
759
760 kfree(vpbe_dev->encoders);
761 vpbe_dev->initialized = 0;
762 /* disable vpss clocks */
763 vpss_enable_clock(VPSS_VPBE_CLOCK, 0);
764}
765
766static struct vpbe_device_ops vpbe_dev_ops = {
767 .g_cropcap = vpbe_g_cropcap,
768 .enum_outputs = vpbe_enum_outputs,
769 .set_output = vpbe_set_output,
770 .get_output = vpbe_get_output,
771 .s_dv_preset = vpbe_s_dv_preset,
772 .g_dv_preset = vpbe_g_dv_preset,
773 .enum_dv_presets = vpbe_enum_dv_presets,
774 .s_std = vpbe_s_std,
775 .g_std = vpbe_g_std,
776 .initialize = vpbe_initialize,
777 .deinitialize = vpbe_deinitialize,
778 .get_mode_info = vpbe_get_current_mode_info,
779 .set_mode = vpbe_set_mode,
780};
781
782static __devinit int vpbe_probe(struct platform_device *pdev)
783{
784 struct vpbe_device *vpbe_dev;
785 struct vpbe_config *cfg;
786 int ret = -EINVAL;
787
788 if (pdev->dev.platform_data == NULL) {
789 v4l2_err(pdev->dev.driver, "No platform data\n");
790 return -ENODEV;
791 }
792 cfg = pdev->dev.platform_data;
793
794 if (!cfg->module_name[0] ||
795 !cfg->osd.module_name[0] ||
796 !cfg->venc.module_name[0]) {
797 v4l2_err(pdev->dev.driver, "vpbe display module names not"
798 " defined\n");
799 return ret;
800 }
801
802 vpbe_dev = kzalloc(sizeof(*vpbe_dev), GFP_KERNEL);
803 if (vpbe_dev == NULL) {
804 v4l2_err(pdev->dev.driver, "Unable to allocate memory"
805 " for vpbe_device\n");
806 return -ENOMEM;
807 }
808 vpbe_dev->cfg = cfg;
809 vpbe_dev->ops = vpbe_dev_ops;
810 vpbe_dev->pdev = &pdev->dev;
811
812 if (cfg->outputs->num_modes > 0)
813 vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0];
814 else
815 return -ENODEV;
816
817 /* set the driver data in platform device */
818 platform_set_drvdata(pdev, vpbe_dev);
819 mutex_init(&vpbe_dev->lock);
820
821 return 0;
822}
823
824static int vpbe_remove(struct platform_device *device)
825{
826 struct vpbe_device *vpbe_dev = platform_get_drvdata(device);
827
828 kfree(vpbe_dev);
829
830 return 0;
831}
832
833static struct platform_driver vpbe_driver = {
834 .driver = {
835 .name = "vpbe_controller",
836 .owner = THIS_MODULE,
837 },
838 .probe = vpbe_probe,
839 .remove = vpbe_remove,
840};
841
842/**
843 * vpbe_init: initialize the vpbe driver
844 *
845 * This function registers device and driver to the kernel
846 */
847static __init int vpbe_init(void)
848{
849 return platform_driver_register(&vpbe_driver);
850}
851
852/**
853 * vpbe_cleanup : cleanup function for vpbe driver
854 *
855 * This will un-registers the device and driver to the kernel
856 */
857static void vpbe_cleanup(void)
858{
859 platform_driver_unregister(&vpbe_driver);
860}
861
862/* Function for module initialization and cleanup */
863module_init(vpbe_init);
864module_exit(vpbe_cleanup);
diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c
new file mode 100644
index 00000000000..7f1d83a6d57
--- /dev/null
+++ b/drivers/media/video/davinci/vpbe_display.c
@@ -0,0 +1,1860 @@
1/*
2 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/errno.h>
17#include <linux/interrupt.h>
18#include <linux/string.h>
19#include <linux/wait.h>
20#include <linux/time.h>
21#include <linux/platform_device.h>
22#include <linux/irq.h>
23#include <linux/mm.h>
24#include <linux/mutex.h>
25#include <linux/videodev2.h>
26#include <linux/slab.h>
27
28#include <asm/pgtable.h>
29#include <mach/cputype.h>
30
31#include <media/v4l2-dev.h>
32#include <media/v4l2-common.h>
33#include <media/v4l2-ioctl.h>
34#include <media/v4l2-device.h>
35#include <media/davinci/vpbe_display.h>
36#include <media/davinci/vpbe_types.h>
37#include <media/davinci/vpbe.h>
38#include <media/davinci/vpbe_venc.h>
39#include <media/davinci/vpbe_osd.h>
40#include "vpbe_venc_regs.h"
41
42#define VPBE_DISPLAY_DRIVER "vpbe-v4l2"
43
44static int debug;
45
46#define VPBE_DISPLAY_SD_BUF_SIZE (720*576*2)
47#define VPBE_DEFAULT_NUM_BUFS 3
48
49module_param(debug, int, 0644);
50
51static int venc_is_second_field(struct vpbe_display *disp_dev)
52{
53 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
54 int ret;
55 int val;
56
57 ret = v4l2_subdev_call(vpbe_dev->venc,
58 core,
59 ioctl,
60 VENC_GET_FLD,
61 &val);
62 if (ret < 0) {
63 v4l2_err(&vpbe_dev->v4l2_dev,
64 "Error in getting Field ID 0\n");
65 }
66 return val;
67}
68
69static void vpbe_isr_even_field(struct vpbe_display *disp_obj,
70 struct vpbe_layer *layer)
71{
72 struct timespec timevalue;
73
74 if (layer->cur_frm == layer->next_frm)
75 return;
76 ktime_get_ts(&timevalue);
77 layer->cur_frm->ts.tv_sec = timevalue.tv_sec;
78 layer->cur_frm->ts.tv_usec = timevalue.tv_nsec / NSEC_PER_USEC;
79 layer->cur_frm->state = VIDEOBUF_DONE;
80 wake_up_interruptible(&layer->cur_frm->done);
81 /* Make cur_frm pointing to next_frm */
82 layer->cur_frm = layer->next_frm;
83}
84
85static void vpbe_isr_odd_field(struct vpbe_display *disp_obj,
86 struct vpbe_layer *layer)
87{
88 struct osd_state *osd_device = disp_obj->osd_device;
89 unsigned long addr;
90
91 spin_lock(&disp_obj->dma_queue_lock);
92 if (list_empty(&layer->dma_queue) ||
93 (layer->cur_frm != layer->next_frm)) {
94 spin_unlock(&disp_obj->dma_queue_lock);
95 return;
96 }
97 /*
98 * one field is displayed configure
99 * the next frame if it is available
100 * otherwise hold on current frame
101 * Get next from the buffer queue
102 */
103 layer->next_frm = list_entry(
104 layer->dma_queue.next,
105 struct videobuf_buffer,
106 queue);
107 /* Remove that from the buffer queue */
108 list_del(&layer->next_frm->queue);
109 spin_unlock(&disp_obj->dma_queue_lock);
110 /* Mark state of the frame to active */
111 layer->next_frm->state = VIDEOBUF_ACTIVE;
112 addr = videobuf_to_dma_contig(layer->next_frm);
113 osd_device->ops.start_layer(osd_device,
114 layer->layer_info.id,
115 addr,
116 disp_obj->cbcr_ofst);
117}
118
119/* interrupt service routine */
120static irqreturn_t venc_isr(int irq, void *arg)
121{
122 struct vpbe_display *disp_dev = (struct vpbe_display *)arg;
123 struct vpbe_layer *layer;
124 static unsigned last_event;
125 unsigned event = 0;
126 int fid;
127 int i;
128
129 if ((NULL == arg) || (NULL == disp_dev->dev[0]))
130 return IRQ_HANDLED;
131
132 if (venc_is_second_field(disp_dev))
133 event |= VENC_SECOND_FIELD;
134 else
135 event |= VENC_FIRST_FIELD;
136
137 if (event == (last_event & ~VENC_END_OF_FRAME)) {
138 /*
139 * If the display is non-interlaced, then we need to flag the
140 * end-of-frame event at every interrupt regardless of the
141 * value of the FIDST bit. We can conclude that the display is
142 * non-interlaced if the value of the FIDST bit is unchanged
143 * from the previous interrupt.
144 */
145 event |= VENC_END_OF_FRAME;
146 } else if (event == VENC_SECOND_FIELD) {
147 /* end-of-frame for interlaced display */
148 event |= VENC_END_OF_FRAME;
149 }
150 last_event = event;
151
152 for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
153 layer = disp_dev->dev[i];
154 /* If streaming is started in this layer */
155 if (!layer->started)
156 continue;
157
158 if (layer->layer_first_int) {
159 layer->layer_first_int = 0;
160 continue;
161 }
162 /* Check the field format */
163 if ((V4L2_FIELD_NONE == layer->pix_fmt.field) &&
164 (event & VENC_END_OF_FRAME)) {
165 /* Progressive mode */
166
167 vpbe_isr_even_field(disp_dev, layer);
168 vpbe_isr_odd_field(disp_dev, layer);
169 } else {
170 /* Interlaced mode */
171
172 layer->field_id ^= 1;
173 if (event & VENC_FIRST_FIELD)
174 fid = 0;
175 else
176 fid = 1;
177
178 /*
179 * If field id does not match with store
180 * field id
181 */
182 if (fid != layer->field_id) {
183 /* Make them in sync */
184 layer->field_id = fid;
185 continue;
186 }
187 /*
188 * device field id and local field id are
189 * in sync. If this is even field
190 */
191 if (0 == fid)
192 vpbe_isr_even_field(disp_dev, layer);
193 else /* odd field */
194 vpbe_isr_odd_field(disp_dev, layer);
195 }
196 }
197
198 return IRQ_HANDLED;
199}
200
201/*
202 * vpbe_buffer_prepare()
203 * This is the callback function called from videobuf_qbuf() function
204 * the buffer is prepared and user space virtual address is converted into
205 * physical address
206 */
207static int vpbe_buffer_prepare(struct videobuf_queue *q,
208 struct videobuf_buffer *vb,
209 enum v4l2_field field)
210{
211 struct vpbe_fh *fh = q->priv_data;
212 struct vpbe_layer *layer = fh->layer;
213 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
214 unsigned long addr;
215 int ret;
216
217 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
218 "vpbe_buffer_prepare\n");
219
220 /* If buffer is not initialized, initialize it */
221 if (VIDEOBUF_NEEDS_INIT == vb->state) {
222 vb->width = layer->pix_fmt.width;
223 vb->height = layer->pix_fmt.height;
224 vb->size = layer->pix_fmt.sizeimage;
225 vb->field = field;
226
227 ret = videobuf_iolock(q, vb, NULL);
228 if (ret < 0) {
229 v4l2_err(&vpbe_dev->v4l2_dev, "Failed to map \
230 user address\n");
231 return -EINVAL;
232 }
233
234 addr = videobuf_to_dma_contig(vb);
235
236 if (q->streaming) {
237 if (!IS_ALIGNED(addr, 8)) {
238 v4l2_err(&vpbe_dev->v4l2_dev,
239 "buffer_prepare:offset is \
240 not aligned to 32 bytes\n");
241 return -EINVAL;
242 }
243 }
244 vb->state = VIDEOBUF_PREPARED;
245 }
246 return 0;
247}
248
249/*
250 * vpbe_buffer_setup()
251 * This function allocates memory for the buffers
252 */
253static int vpbe_buffer_setup(struct videobuf_queue *q,
254 unsigned int *count,
255 unsigned int *size)
256{
257 /* Get the file handle object and layer object */
258 struct vpbe_fh *fh = q->priv_data;
259 struct vpbe_layer *layer = fh->layer;
260 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
261
262 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n");
263
264 *size = layer->pix_fmt.sizeimage;
265
266 /* Store number of buffers allocated in numbuffer member */
267 if (*count < VPBE_DEFAULT_NUM_BUFS)
268 *count = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
269
270 return 0;
271}
272
273/*
274 * vpbe_buffer_queue()
275 * This function adds the buffer to DMA queue
276 */
277static void vpbe_buffer_queue(struct videobuf_queue *q,
278 struct videobuf_buffer *vb)
279{
280 /* Get the file handle object and layer object */
281 struct vpbe_fh *fh = q->priv_data;
282 struct vpbe_layer *layer = fh->layer;
283 struct vpbe_display *disp = fh->disp_dev;
284 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
285 unsigned long flags;
286
287 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
288 "vpbe_buffer_queue\n");
289
290 /* add the buffer to the DMA queue */
291 spin_lock_irqsave(&disp->dma_queue_lock, flags);
292 list_add_tail(&vb->queue, &layer->dma_queue);
293 spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
294 /* Change state of the buffer */
295 vb->state = VIDEOBUF_QUEUED;
296}
297
298/*
299 * vpbe_buffer_release()
300 * This function is called from the videobuf layer to free memory allocated to
301 * the buffers
302 */
303static void vpbe_buffer_release(struct videobuf_queue *q,
304 struct videobuf_buffer *vb)
305{
306 /* Get the file handle object and layer object */
307 struct vpbe_fh *fh = q->priv_data;
308 struct vpbe_layer *layer = fh->layer;
309 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
310
311 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
312 "vpbe_buffer_release\n");
313
314 if (V4L2_MEMORY_USERPTR != layer->memory)
315 videobuf_dma_contig_free(q, vb);
316
317 vb->state = VIDEOBUF_NEEDS_INIT;
318}
319
320static struct videobuf_queue_ops video_qops = {
321 .buf_setup = vpbe_buffer_setup,
322 .buf_prepare = vpbe_buffer_prepare,
323 .buf_queue = vpbe_buffer_queue,
324 .buf_release = vpbe_buffer_release,
325};
326
327static
328struct vpbe_layer*
329_vpbe_display_get_other_win_layer(struct vpbe_display *disp_dev,
330 struct vpbe_layer *layer)
331{
332 enum vpbe_display_device_id thiswin, otherwin;
333 thiswin = layer->device_id;
334
335 otherwin = (thiswin == VPBE_DISPLAY_DEVICE_0) ?
336 VPBE_DISPLAY_DEVICE_1 : VPBE_DISPLAY_DEVICE_0;
337 return disp_dev->dev[otherwin];
338}
339
340static int vpbe_set_osd_display_params(struct vpbe_display *disp_dev,
341 struct vpbe_layer *layer)
342{
343 struct osd_layer_config *cfg = &layer->layer_info.config;
344 struct osd_state *osd_device = disp_dev->osd_device;
345 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
346 unsigned long addr;
347 int ret;
348
349 addr = videobuf_to_dma_contig(layer->cur_frm);
350 /* Set address in the display registers */
351 osd_device->ops.start_layer(osd_device,
352 layer->layer_info.id,
353 addr,
354 disp_dev->cbcr_ofst);
355
356 ret = osd_device->ops.enable_layer(osd_device,
357 layer->layer_info.id, 0);
358 if (ret < 0) {
359 v4l2_err(&vpbe_dev->v4l2_dev,
360 "Error in enabling osd window layer 0\n");
361 return -1;
362 }
363
364 /* Enable the window */
365 layer->layer_info.enable = 1;
366 if (cfg->pixfmt == PIXFMT_NV12) {
367 struct vpbe_layer *otherlayer =
368 _vpbe_display_get_other_win_layer(disp_dev, layer);
369
370 ret = osd_device->ops.enable_layer(osd_device,
371 otherlayer->layer_info.id, 1);
372 if (ret < 0) {
373 v4l2_err(&vpbe_dev->v4l2_dev,
374 "Error in enabling osd window layer 1\n");
375 return -1;
376 }
377 otherlayer->layer_info.enable = 1;
378 }
379 return 0;
380}
381
382static void
383vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
384 struct vpbe_layer *layer,
385 int expected_xsize, int expected_ysize)
386{
387 struct display_layer_info *layer_info = &layer->layer_info;
388 struct v4l2_pix_format *pixfmt = &layer->pix_fmt;
389 struct osd_layer_config *cfg = &layer->layer_info.config;
390 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
391 int calculated_xsize;
392 int h_exp = 0;
393 int v_exp = 0;
394 int h_scale;
395 int v_scale;
396
397 v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id;
398
399 /*
400 * Application initially set the image format. Current display
401 * size is obtained from the vpbe display controller. expected_xsize
402 * and expected_ysize are set through S_CROP ioctl. Based on this,
403 * driver will calculate the scale factors for vertical and
404 * horizontal direction so that the image is displayed scaled
405 * and expanded. Application uses expansion to display the image
406 * in a square pixel. Otherwise it is displayed using displays
407 * pixel aspect ratio.It is expected that application chooses
408 * the crop coordinates for cropped or scaled display. if crop
409 * size is less than the image size, it is displayed cropped or
410 * it is displayed scaled and/or expanded.
411 *
412 * to begin with, set the crop window same as expected. Later we
413 * will override with scaled window size
414 */
415
416 cfg->xsize = pixfmt->width;
417 cfg->ysize = pixfmt->height;
418 layer_info->h_zoom = ZOOM_X1; /* no horizontal zoom */
419 layer_info->v_zoom = ZOOM_X1; /* no horizontal zoom */
420 layer_info->h_exp = H_EXP_OFF; /* no horizontal zoom */
421 layer_info->v_exp = V_EXP_OFF; /* no horizontal zoom */
422
423 if (pixfmt->width < expected_xsize) {
424 h_scale = vpbe_dev->current_timings.xres / pixfmt->width;
425 if (h_scale < 2)
426 h_scale = 1;
427 else if (h_scale >= 4)
428 h_scale = 4;
429 else
430 h_scale = 2;
431 cfg->xsize *= h_scale;
432 if (cfg->xsize < expected_xsize) {
433 if ((standard_id & V4L2_STD_525_60) ||
434 (standard_id & V4L2_STD_625_50)) {
435 calculated_xsize = (cfg->xsize *
436 VPBE_DISPLAY_H_EXP_RATIO_N) /
437 VPBE_DISPLAY_H_EXP_RATIO_D;
438 if (calculated_xsize <= expected_xsize) {
439 h_exp = 1;
440 cfg->xsize = calculated_xsize;
441 }
442 }
443 }
444 if (h_scale == 2)
445 layer_info->h_zoom = ZOOM_X2;
446 else if (h_scale == 4)
447 layer_info->h_zoom = ZOOM_X4;
448 if (h_exp)
449 layer_info->h_exp = H_EXP_9_OVER_8;
450 } else {
451 /* no scaling, only cropping. Set display area to crop area */
452 cfg->xsize = expected_xsize;
453 }
454
455 if (pixfmt->height < expected_ysize) {
456 v_scale = expected_ysize / pixfmt->height;
457 if (v_scale < 2)
458 v_scale = 1;
459 else if (v_scale >= 4)
460 v_scale = 4;
461 else
462 v_scale = 2;
463 cfg->ysize *= v_scale;
464 if (cfg->ysize < expected_ysize) {
465 if ((standard_id & V4L2_STD_625_50)) {
466 calculated_xsize = (cfg->ysize *
467 VPBE_DISPLAY_V_EXP_RATIO_N) /
468 VPBE_DISPLAY_V_EXP_RATIO_D;
469 if (calculated_xsize <= expected_ysize) {
470 v_exp = 1;
471 cfg->ysize = calculated_xsize;
472 }
473 }
474 }
475 if (v_scale == 2)
476 layer_info->v_zoom = ZOOM_X2;
477 else if (v_scale == 4)
478 layer_info->v_zoom = ZOOM_X4;
479 if (v_exp)
480 layer_info->h_exp = V_EXP_6_OVER_5;
481 } else {
482 /* no scaling, only cropping. Set display area to crop area */
483 cfg->ysize = expected_ysize;
484 }
485 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
486 "crop display xsize = %d, ysize = %d\n",
487 cfg->xsize, cfg->ysize);
488}
489
490static void vpbe_disp_adj_position(struct vpbe_display *disp_dev,
491 struct vpbe_layer *layer,
492 int top, int left)
493{
494 struct osd_layer_config *cfg = &layer->layer_info.config;
495 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
496
497 cfg->xpos = min((unsigned int)left,
498 vpbe_dev->current_timings.xres - cfg->xsize);
499 cfg->ypos = min((unsigned int)top,
500 vpbe_dev->current_timings.yres - cfg->ysize);
501
502 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
503 "new xpos = %d, ypos = %d\n",
504 cfg->xpos, cfg->ypos);
505}
506
507static void vpbe_disp_check_window_params(struct vpbe_display *disp_dev,
508 struct v4l2_rect *c)
509{
510 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
511
512 if ((c->width == 0) ||
513 ((c->width + c->left) > vpbe_dev->current_timings.xres))
514 c->width = vpbe_dev->current_timings.xres - c->left;
515
516 if ((c->height == 0) || ((c->height + c->top) >
517 vpbe_dev->current_timings.yres))
518 c->height = vpbe_dev->current_timings.yres - c->top;
519
520 /* window height must be even for interlaced display */
521 if (vpbe_dev->current_timings.interlaced)
522 c->height &= (~0x01);
523
524}
525
526/**
527 * vpbe_try_format()
528 * If user application provides width and height, and have bytesperline set
529 * to zero, driver calculates bytesperline and sizeimage based on hardware
530 * limits.
531 */
532static int vpbe_try_format(struct vpbe_display *disp_dev,
533 struct v4l2_pix_format *pixfmt, int check)
534{
535 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
536 int min_height = 1;
537 int min_width = 32;
538 int max_height;
539 int max_width;
540 int bpp;
541
542 if ((pixfmt->pixelformat != V4L2_PIX_FMT_UYVY) &&
543 (pixfmt->pixelformat != V4L2_PIX_FMT_NV12))
544 /* choose default as V4L2_PIX_FMT_UYVY */
545 pixfmt->pixelformat = V4L2_PIX_FMT_UYVY;
546
547 /* Check the field format */
548 if ((pixfmt->field != V4L2_FIELD_INTERLACED) &&
549 (pixfmt->field != V4L2_FIELD_NONE)) {
550 if (vpbe_dev->current_timings.interlaced)
551 pixfmt->field = V4L2_FIELD_INTERLACED;
552 else
553 pixfmt->field = V4L2_FIELD_NONE;
554 }
555
556 if (pixfmt->field == V4L2_FIELD_INTERLACED)
557 min_height = 2;
558
559 if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
560 bpp = 1;
561 else
562 bpp = 2;
563
564 max_width = vpbe_dev->current_timings.xres;
565 max_height = vpbe_dev->current_timings.yres;
566
567 min_width /= bpp;
568
569 if (!pixfmt->width || (pixfmt->width < min_width) ||
570 (pixfmt->width > max_width)) {
571 pixfmt->width = vpbe_dev->current_timings.xres;
572 }
573
574 if (!pixfmt->height || (pixfmt->height < min_height) ||
575 (pixfmt->height > max_height)) {
576 pixfmt->height = vpbe_dev->current_timings.yres;
577 }
578
579 if (pixfmt->bytesperline < (pixfmt->width * bpp))
580 pixfmt->bytesperline = pixfmt->width * bpp;
581
582 /* Make the bytesperline 32 byte aligned */
583 pixfmt->bytesperline = ((pixfmt->width * bpp + 31) & ~31);
584
585 if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
586 pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height +
587 (pixfmt->bytesperline * pixfmt->height >> 1);
588 else
589 pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
590
591 return 0;
592}
593
594static int vpbe_display_g_priority(struct file *file, void *priv,
595 enum v4l2_priority *p)
596{
597 struct vpbe_fh *fh = file->private_data;
598 struct vpbe_layer *layer = fh->layer;
599
600 *p = v4l2_prio_max(&layer->prio);
601
602 return 0;
603}
604
605static int vpbe_display_s_priority(struct file *file, void *priv,
606 enum v4l2_priority p)
607{
608 struct vpbe_fh *fh = file->private_data;
609 struct vpbe_layer *layer = fh->layer;
610 int ret;
611
612 ret = v4l2_prio_change(&layer->prio, &fh->prio, p);
613
614 return ret;
615}
616
617static int vpbe_display_querycap(struct file *file, void *priv,
618 struct v4l2_capability *cap)
619{
620 struct vpbe_fh *fh = file->private_data;
621 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
622
623 cap->version = VPBE_DISPLAY_VERSION_CODE;
624 cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
625 strlcpy(cap->driver, VPBE_DISPLAY_DRIVER, sizeof(cap->driver));
626 strlcpy(cap->bus_info, "platform", sizeof(cap->bus_info));
627 strlcpy(cap->card, vpbe_dev->cfg->module_name, sizeof(cap->card));
628
629 return 0;
630}
631
632static int vpbe_display_s_crop(struct file *file, void *priv,
633 struct v4l2_crop *crop)
634{
635 struct vpbe_fh *fh = file->private_data;
636 struct vpbe_layer *layer = fh->layer;
637 struct vpbe_display *disp_dev = fh->disp_dev;
638 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
639 struct osd_layer_config *cfg = &layer->layer_info.config;
640 struct osd_state *osd_device = disp_dev->osd_device;
641 struct v4l2_rect *rect = &crop->c;
642 int ret;
643
644 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
645 "VIDIOC_S_CROP, layer id = %d\n", layer->device_id);
646
647 if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
648 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n");
649 return -EINVAL;
650 }
651
652 if (rect->top < 0)
653 rect->top = 0;
654 if (rect->left < 0)
655 rect->left = 0;
656
657 vpbe_disp_check_window_params(disp_dev, rect);
658
659 osd_device->ops.get_layer_config(osd_device,
660 layer->layer_info.id, cfg);
661
662 vpbe_disp_calculate_scale_factor(disp_dev, layer,
663 rect->width,
664 rect->height);
665 vpbe_disp_adj_position(disp_dev, layer, rect->top,
666 rect->left);
667 ret = osd_device->ops.set_layer_config(osd_device,
668 layer->layer_info.id, cfg);
669 if (ret < 0) {
670 v4l2_err(&vpbe_dev->v4l2_dev,
671 "Error in set layer config:\n");
672 return -EINVAL;
673 }
674
675 /* apply zooming and h or v expansion */
676 osd_device->ops.set_zoom(osd_device,
677 layer->layer_info.id,
678 layer->layer_info.h_zoom,
679 layer->layer_info.v_zoom);
680 ret = osd_device->ops.set_vid_expansion(osd_device,
681 layer->layer_info.h_exp,
682 layer->layer_info.v_exp);
683 if (ret < 0) {
684 v4l2_err(&vpbe_dev->v4l2_dev,
685 "Error in set vid expansion:\n");
686 return -EINVAL;
687 }
688
689 if ((layer->layer_info.h_zoom != ZOOM_X1) ||
690 (layer->layer_info.v_zoom != ZOOM_X1) ||
691 (layer->layer_info.h_exp != H_EXP_OFF) ||
692 (layer->layer_info.v_exp != V_EXP_OFF))
693 /* Enable expansion filter */
694 osd_device->ops.set_interpolation_filter(osd_device, 1);
695 else
696 osd_device->ops.set_interpolation_filter(osd_device, 0);
697
698 return 0;
699}
700
701static int vpbe_display_g_crop(struct file *file, void *priv,
702 struct v4l2_crop *crop)
703{
704 struct vpbe_fh *fh = file->private_data;
705 struct vpbe_layer *layer = fh->layer;
706 struct osd_layer_config *cfg = &layer->layer_info.config;
707 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
708 struct osd_state *osd_device = fh->disp_dev->osd_device;
709 struct v4l2_rect *rect = &crop->c;
710 int ret;
711
712 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
713 "VIDIOC_G_CROP, layer id = %d\n",
714 layer->device_id);
715
716 if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
717 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buf type\n");
718 ret = -EINVAL;
719 }
720 osd_device->ops.get_layer_config(osd_device,
721 layer->layer_info.id, cfg);
722 rect->top = cfg->ypos;
723 rect->left = cfg->xpos;
724 rect->width = cfg->xsize;
725 rect->height = cfg->ysize;
726
727 return 0;
728}
729
730static int vpbe_display_cropcap(struct file *file, void *priv,
731 struct v4l2_cropcap *cropcap)
732{
733 struct vpbe_fh *fh = file->private_data;
734 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
735
736 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_CROPCAP ioctl\n");
737
738 cropcap->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
739 cropcap->bounds.left = 0;
740 cropcap->bounds.top = 0;
741 cropcap->bounds.width = vpbe_dev->current_timings.xres;
742 cropcap->bounds.height = vpbe_dev->current_timings.yres;
743 cropcap->pixelaspect = vpbe_dev->current_timings.aspect;
744 cropcap->defrect = cropcap->bounds;
745 return 0;
746}
747
748static int vpbe_display_g_fmt(struct file *file, void *priv,
749 struct v4l2_format *fmt)
750{
751 struct vpbe_fh *fh = file->private_data;
752 struct vpbe_layer *layer = fh->layer;
753 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
754
755 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
756 "VIDIOC_G_FMT, layer id = %d\n",
757 layer->device_id);
758
759 /* If buffer type is video output */
760 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
761 v4l2_err(&vpbe_dev->v4l2_dev, "invalid type\n");
762 return -EINVAL;
763 }
764 /* Fill in the information about format */
765 fmt->fmt.pix = layer->pix_fmt;
766
767 return 0;
768}
769
770static int vpbe_display_enum_fmt(struct file *file, void *priv,
771 struct v4l2_fmtdesc *fmt)
772{
773 struct vpbe_fh *fh = file->private_data;
774 struct vpbe_layer *layer = fh->layer;
775 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
776 unsigned int index = 0;
777
778 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
779 "VIDIOC_ENUM_FMT, layer id = %d\n",
780 layer->device_id);
781 if (fmt->index > 1) {
782 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid format index\n");
783 return -EINVAL;
784 }
785
786 /* Fill in the information about format */
787 index = fmt->index;
788 memset(fmt, 0, sizeof(*fmt));
789 fmt->index = index;
790 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
791 if (index == 0) {
792 strcpy(fmt->description, "YUV 4:2:2 - UYVY");
793 fmt->pixelformat = V4L2_PIX_FMT_UYVY;
794 } else {
795 strcpy(fmt->description, "Y/CbCr 4:2:0");
796 fmt->pixelformat = V4L2_PIX_FMT_NV12;
797 }
798
799 return 0;
800}
801
802static int vpbe_display_s_fmt(struct file *file, void *priv,
803 struct v4l2_format *fmt)
804{
805 struct vpbe_fh *fh = file->private_data;
806 struct vpbe_layer *layer = fh->layer;
807 struct vpbe_display *disp_dev = fh->disp_dev;
808 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
809 struct osd_layer_config *cfg = &layer->layer_info.config;
810 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
811 struct osd_state *osd_device = disp_dev->osd_device;
812 int ret;
813
814 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
815 "VIDIOC_S_FMT, layer id = %d\n",
816 layer->device_id);
817
818 /* If streaming is started, return error */
819 if (layer->started) {
820 v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
821 return -EBUSY;
822 }
823 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
824 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "invalid type\n");
825 return -EINVAL;
826 }
827 /* Check for valid pixel format */
828 ret = vpbe_try_format(disp_dev, pixfmt, 1);
829 if (ret)
830 return ret;
831
832 /* YUV420 is requested, check availability of the
833 other video window */
834
835 layer->pix_fmt = *pixfmt;
836
837 /* Get osd layer config */
838 osd_device->ops.get_layer_config(osd_device,
839 layer->layer_info.id, cfg);
840 /* Store the pixel format in the layer object */
841 cfg->xsize = pixfmt->width;
842 cfg->ysize = pixfmt->height;
843 cfg->line_length = pixfmt->bytesperline;
844 cfg->ypos = 0;
845 cfg->xpos = 0;
846 cfg->interlaced = vpbe_dev->current_timings.interlaced;
847
848 if (V4L2_PIX_FMT_UYVY == pixfmt->pixelformat)
849 cfg->pixfmt = PIXFMT_YCbCrI;
850
851 /* Change of the default pixel format for both video windows */
852 if (V4L2_PIX_FMT_NV12 == pixfmt->pixelformat) {
853 struct vpbe_layer *otherlayer;
854 cfg->pixfmt = PIXFMT_NV12;
855 otherlayer = _vpbe_display_get_other_win_layer(disp_dev,
856 layer);
857 otherlayer->layer_info.config.pixfmt = PIXFMT_NV12;
858 }
859
860 /* Set the layer config in the osd window */
861 ret = osd_device->ops.set_layer_config(osd_device,
862 layer->layer_info.id, cfg);
863 if (ret < 0) {
864 v4l2_err(&vpbe_dev->v4l2_dev,
865 "Error in S_FMT params:\n");
866 return -EINVAL;
867 }
868
869 /* Readback and fill the local copy of current pix format */
870 osd_device->ops.get_layer_config(osd_device,
871 layer->layer_info.id, cfg);
872
873 return 0;
874}
875
876static int vpbe_display_try_fmt(struct file *file, void *priv,
877 struct v4l2_format *fmt)
878{
879 struct vpbe_fh *fh = file->private_data;
880 struct vpbe_display *disp_dev = fh->disp_dev;
881 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
882 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
883
884 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_TRY_FMT\n");
885
886 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
887 v4l2_err(&vpbe_dev->v4l2_dev, "invalid type\n");
888 return -EINVAL;
889 }
890
891 /* Check for valid field format */
892 return vpbe_try_format(disp_dev, pixfmt, 0);
893
894}
895
896/**
897 * vpbe_display_s_std - Set the given standard in the encoder
898 *
899 * Sets the standard if supported by the current encoder. Return the status.
900 * 0 - success & -EINVAL on error
901 */
902static int vpbe_display_s_std(struct file *file, void *priv,
903 v4l2_std_id *std_id)
904{
905 struct vpbe_fh *fh = priv;
906 struct vpbe_layer *layer = fh->layer;
907 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
908 int ret;
909
910 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_STD\n");
911
912 /* If streaming is started, return error */
913 if (layer->started) {
914 v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
915 return -EBUSY;
916 }
917 if (NULL != vpbe_dev->ops.s_std) {
918 ret = vpbe_dev->ops.s_std(vpbe_dev, std_id);
919 if (ret) {
920 v4l2_err(&vpbe_dev->v4l2_dev,
921 "Failed to set standard for sub devices\n");
922 return -EINVAL;
923 }
924 } else {
925 return -EINVAL;
926 }
927
928 return 0;
929}
930
931/**
932 * vpbe_display_g_std - Get the standard in the current encoder
933 *
934 * Get the standard in the current encoder. Return the status. 0 - success
935 * -EINVAL on error
936 */
937static int vpbe_display_g_std(struct file *file, void *priv,
938 v4l2_std_id *std_id)
939{
940 struct vpbe_fh *fh = priv;
941 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
942
943 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_STD\n");
944
945 /* Get the standard from the current encoder */
946 if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) {
947 *std_id = vpbe_dev->current_timings.timings.std_id;
948 return 0;
949 }
950
951 return -EINVAL;
952}
953
954/**
955 * vpbe_display_enum_output - enumerate outputs
956 *
957 * Enumerates the outputs available at the vpbe display
958 * returns the status, -EINVAL if end of output list
959 */
960static int vpbe_display_enum_output(struct file *file, void *priv,
961 struct v4l2_output *output)
962{
963 struct vpbe_fh *fh = priv;
964 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
965 int ret;
966
967 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_OUTPUT\n");
968
969 /* Enumerate outputs */
970
971 if (NULL == vpbe_dev->ops.enum_outputs)
972 return -EINVAL;
973
974 ret = vpbe_dev->ops.enum_outputs(vpbe_dev, output);
975 if (ret) {
976 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
977 "Failed to enumerate outputs\n");
978 return -EINVAL;
979 }
980
981 return 0;
982}
983
984/**
985 * vpbe_display_s_output - Set output to
986 * the output specified by the index
987 */
988static int vpbe_display_s_output(struct file *file, void *priv,
989 unsigned int i)
990{
991 struct vpbe_fh *fh = priv;
992 struct vpbe_layer *layer = fh->layer;
993 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
994 int ret;
995
996 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_OUTPUT\n");
997 /* If streaming is started, return error */
998 if (layer->started) {
999 v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
1000 return -EBUSY;
1001 }
1002 if (NULL == vpbe_dev->ops.set_output)
1003 return -EINVAL;
1004
1005 ret = vpbe_dev->ops.set_output(vpbe_dev, i);
1006 if (ret) {
1007 v4l2_err(&vpbe_dev->v4l2_dev,
1008 "Failed to set output for sub devices\n");
1009 return -EINVAL;
1010 }
1011
1012 return 0;
1013}
1014
1015/**
1016 * vpbe_display_g_output - Get output from subdevice
1017 * for a given by the index
1018 */
1019static int vpbe_display_g_output(struct file *file, void *priv,
1020 unsigned int *i)
1021{
1022 struct vpbe_fh *fh = priv;
1023 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1024
1025 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_OUTPUT\n");
1026 /* Get the standard from the current encoder */
1027 *i = vpbe_dev->current_out_index;
1028
1029 return 0;
1030}
1031
1032/**
1033 * vpbe_display_enum_dv_presets - Enumerate the dv presets
1034 *
1035 * enum the preset in the current encoder. Return the status. 0 - success
1036 * -EINVAL on error
1037 */
1038static int
1039vpbe_display_enum_dv_presets(struct file *file, void *priv,
1040 struct v4l2_dv_enum_preset *preset)
1041{
1042 struct vpbe_fh *fh = priv;
1043 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1044 int ret;
1045
1046 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n");
1047
1048 /* Enumerate outputs */
1049 if (NULL == vpbe_dev->ops.enum_dv_presets)
1050 return -EINVAL;
1051
1052 ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset);
1053 if (ret) {
1054 v4l2_err(&vpbe_dev->v4l2_dev,
1055 "Failed to enumerate dv presets info\n");
1056 return -EINVAL;
1057 }
1058
1059 return 0;
1060}
1061
1062/**
1063 * vpbe_display_s_dv_preset - Set the dv presets
1064 *
1065 * Set the preset in the current encoder. Return the status. 0 - success
1066 * -EINVAL on error
1067 */
1068static int
1069vpbe_display_s_dv_preset(struct file *file, void *priv,
1070 struct v4l2_dv_preset *preset)
1071{
1072 struct vpbe_fh *fh = priv;
1073 struct vpbe_layer *layer = fh->layer;
1074 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1075 int ret;
1076
1077 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n");
1078
1079
1080 /* If streaming is started, return error */
1081 if (layer->started) {
1082 v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
1083 return -EBUSY;
1084 }
1085
1086 /* Set the given standard in the encoder */
1087 if (NULL != vpbe_dev->ops.s_dv_preset)
1088 return -EINVAL;
1089
1090 ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset);
1091 if (ret) {
1092 v4l2_err(&vpbe_dev->v4l2_dev,
1093 "Failed to set the dv presets info\n");
1094 return -EINVAL;
1095 }
1096 /* set the current norm to zero to be consistent. If STD is used
1097 * v4l2 layer will set the norm properly on successful s_std call
1098 */
1099 layer->video_dev.current_norm = 0;
1100
1101 return 0;
1102}
1103
1104/**
1105 * vpbe_display_g_dv_preset - Set the dv presets
1106 *
1107 * Get the preset in the current encoder. Return the status. 0 - success
1108 * -EINVAL on error
1109 */
1110static int
1111vpbe_display_g_dv_preset(struct file *file, void *priv,
1112 struct v4l2_dv_preset *dv_preset)
1113{
1114 struct vpbe_fh *fh = priv;
1115 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1116
1117 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n");
1118
1119 /* Get the given standard in the encoder */
1120
1121 if (vpbe_dev->current_timings.timings_type &
1122 VPBE_ENC_DV_PRESET) {
1123 dv_preset->preset =
1124 vpbe_dev->current_timings.timings.dv_preset;
1125 } else {
1126 return -EINVAL;
1127 }
1128
1129 return 0;
1130}
1131
1132static int vpbe_display_streamoff(struct file *file, void *priv,
1133 enum v4l2_buf_type buf_type)
1134{
1135 struct vpbe_fh *fh = file->private_data;
1136 struct vpbe_layer *layer = fh->layer;
1137 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1138 struct osd_state *osd_device = fh->disp_dev->osd_device;
1139 int ret;
1140
1141 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
1142 "VIDIOC_STREAMOFF,layer id = %d\n",
1143 layer->device_id);
1144
1145 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
1146 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
1147 return -EINVAL;
1148 }
1149
1150 /* If io is allowed for this file handle, return error */
1151 if (!fh->io_allowed) {
1152 v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
1153 return -EACCES;
1154 }
1155
1156 /* If streaming is not started, return error */
1157 if (!layer->started) {
1158 v4l2_err(&vpbe_dev->v4l2_dev, "streaming not started in layer"
1159 " id = %d\n", layer->device_id);
1160 return -EINVAL;
1161 }
1162
1163 osd_device->ops.disable_layer(osd_device,
1164 layer->layer_info.id);
1165 layer->started = 0;
1166 ret = videobuf_streamoff(&layer->buffer_queue);
1167
1168 return ret;
1169}
1170
1171static int vpbe_display_streamon(struct file *file, void *priv,
1172 enum v4l2_buf_type buf_type)
1173{
1174 struct vpbe_fh *fh = file->private_data;
1175 struct vpbe_layer *layer = fh->layer;
1176 struct vpbe_display *disp_dev = fh->disp_dev;
1177 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1178 struct osd_state *osd_device = disp_dev->osd_device;
1179 int ret;
1180
1181 osd_device->ops.disable_layer(osd_device,
1182 layer->layer_info.id);
1183
1184 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_STREAMON, layerid=%d\n",
1185 layer->device_id);
1186
1187 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
1188 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
1189 return -EINVAL;
1190 }
1191
1192 /* If file handle is not allowed IO, return error */
1193 if (!fh->io_allowed) {
1194 v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
1195 return -EACCES;
1196 }
1197 /* If Streaming is already started, return error */
1198 if (layer->started) {
1199 v4l2_err(&vpbe_dev->v4l2_dev, "layer is already streaming\n");
1200 return -EBUSY;
1201 }
1202
1203 /*
1204 * Call videobuf_streamon to start streaming
1205 * in videobuf
1206 */
1207 ret = videobuf_streamon(&layer->buffer_queue);
1208 if (ret) {
1209 v4l2_err(&vpbe_dev->v4l2_dev,
1210 "error in videobuf_streamon\n");
1211 return ret;
1212 }
1213 /* If buffer queue is empty, return error */
1214 if (list_empty(&layer->dma_queue)) {
1215 v4l2_err(&vpbe_dev->v4l2_dev, "buffer queue is empty\n");
1216 goto streamoff;
1217 }
1218 /* Get the next frame from the buffer queue */
1219 layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
1220 struct videobuf_buffer, queue);
1221 /* Remove buffer from the buffer queue */
1222 list_del(&layer->cur_frm->queue);
1223 /* Mark state of the current frame to active */
1224 layer->cur_frm->state = VIDEOBUF_ACTIVE;
1225 /* Initialize field_id and started member */
1226 layer->field_id = 0;
1227
1228 /* Set parameters in OSD and VENC */
1229 ret = vpbe_set_osd_display_params(disp_dev, layer);
1230 if (ret < 0)
1231 goto streamoff;
1232
1233 /*
1234 * if request format is yuv420 semiplanar, need to
1235 * enable both video windows
1236 */
1237 layer->started = 1;
1238
1239 layer->layer_first_int = 1;
1240
1241 return ret;
1242streamoff:
1243 ret = videobuf_streamoff(&layer->buffer_queue);
1244 return ret;
1245}
1246
1247static int vpbe_display_dqbuf(struct file *file, void *priv,
1248 struct v4l2_buffer *buf)
1249{
1250 struct vpbe_fh *fh = file->private_data;
1251 struct vpbe_layer *layer = fh->layer;
1252 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1253 int ret;
1254
1255 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
1256 "VIDIOC_DQBUF, layer id = %d\n",
1257 layer->device_id);
1258
1259 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
1260 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
1261 return -EINVAL;
1262 }
1263 /* If this file handle is not allowed to do IO, return error */
1264 if (!fh->io_allowed) {
1265 v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
1266 return -EACCES;
1267 }
1268 if (file->f_flags & O_NONBLOCK)
1269 /* Call videobuf_dqbuf for non blocking mode */
1270 ret = videobuf_dqbuf(&layer->buffer_queue, buf, 1);
1271 else
1272 /* Call videobuf_dqbuf for blocking mode */
1273 ret = videobuf_dqbuf(&layer->buffer_queue, buf, 0);
1274
1275 return ret;
1276}
1277
1278static int vpbe_display_qbuf(struct file *file, void *priv,
1279 struct v4l2_buffer *p)
1280{
1281 struct vpbe_fh *fh = file->private_data;
1282 struct vpbe_layer *layer = fh->layer;
1283 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1284
1285 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
1286 "VIDIOC_QBUF, layer id = %d\n",
1287 layer->device_id);
1288
1289 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != p->type) {
1290 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
1291 return -EINVAL;
1292 }
1293
1294 /* If this file handle is not allowed to do IO, return error */
1295 if (!fh->io_allowed) {
1296 v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
1297 return -EACCES;
1298 }
1299
1300 return videobuf_qbuf(&layer->buffer_queue, p);
1301}
1302
1303static int vpbe_display_querybuf(struct file *file, void *priv,
1304 struct v4l2_buffer *buf)
1305{
1306 struct vpbe_fh *fh = file->private_data;
1307 struct vpbe_layer *layer = fh->layer;
1308 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1309 int ret;
1310
1311 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
1312 "VIDIOC_QUERYBUF, layer id = %d\n",
1313 layer->device_id);
1314
1315 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
1316 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
1317 return -EINVAL;
1318 }
1319
1320 /* Call videobuf_querybuf to get information */
1321 ret = videobuf_querybuf(&layer->buffer_queue, buf);
1322
1323 return ret;
1324}
1325
1326static int vpbe_display_reqbufs(struct file *file, void *priv,
1327 struct v4l2_requestbuffers *req_buf)
1328{
1329 struct vpbe_fh *fh = file->private_data;
1330 struct vpbe_layer *layer = fh->layer;
1331 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1332 int ret;
1333
1334 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_reqbufs\n");
1335
1336 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
1337 v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
1338 return -EINVAL;
1339 }
1340
1341 /* If io users of the layer is not zero, return error */
1342 if (0 != layer->io_usrs) {
1343 v4l2_err(&vpbe_dev->v4l2_dev, "not IO user\n");
1344 return -EBUSY;
1345 }
1346 /* Initialize videobuf queue as per the buffer type */
1347 videobuf_queue_dma_contig_init(&layer->buffer_queue,
1348 &video_qops,
1349 vpbe_dev->pdev,
1350 &layer->irqlock,
1351 V4L2_BUF_TYPE_VIDEO_OUTPUT,
1352 layer->pix_fmt.field,
1353 sizeof(struct videobuf_buffer),
1354 fh, NULL);
1355
1356 /* Set io allowed member of file handle to TRUE */
1357 fh->io_allowed = 1;
1358 /* Increment io usrs member of layer object to 1 */
1359 layer->io_usrs = 1;
1360 /* Store type of memory requested in layer object */
1361 layer->memory = req_buf->memory;
1362 /* Initialize buffer queue */
1363 INIT_LIST_HEAD(&layer->dma_queue);
1364 /* Allocate buffers */
1365 ret = videobuf_reqbufs(&layer->buffer_queue, req_buf);
1366
1367 return ret;
1368}
1369
1370/*
1371 * vpbe_display_mmap()
1372 * It is used to map kernel space buffers into user spaces
1373 */
1374static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
1375{
1376 /* Get the layer object and file handle object */
1377 struct vpbe_fh *fh = filep->private_data;
1378 struct vpbe_layer *layer = fh->layer;
1379 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1380
1381 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_mmap\n");
1382
1383 return videobuf_mmap_mapper(&layer->buffer_queue, vma);
1384}
1385
1386/* vpbe_display_poll(): It is used for select/poll system call
1387 */
1388static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
1389{
1390 struct vpbe_fh *fh = filep->private_data;
1391 struct vpbe_layer *layer = fh->layer;
1392 struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
1393 unsigned int err = 0;
1394
1395 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
1396 if (layer->started)
1397 err = videobuf_poll_stream(filep, &layer->buffer_queue, wait);
1398 return err;
1399}
1400
1401/*
1402 * vpbe_display_open()
1403 * It creates object of file handle structure and stores it in private_data
1404 * member of filepointer
1405 */
1406static int vpbe_display_open(struct file *file)
1407{
1408 struct vpbe_fh *fh = NULL;
1409 struct vpbe_layer *layer = video_drvdata(file);
1410 struct vpbe_display *disp_dev = layer->disp_dev;
1411 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
1412 struct osd_state *osd_device = disp_dev->osd_device;
1413 int err;
1414
1415 /* Allocate memory for the file handle object */
1416 fh = kmalloc(sizeof(struct vpbe_fh), GFP_KERNEL);
1417 if (fh == NULL) {
1418 v4l2_err(&vpbe_dev->v4l2_dev,
1419 "unable to allocate memory for file handle object\n");
1420 return -ENOMEM;
1421 }
1422 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
1423 "vpbe display open plane = %d\n",
1424 layer->device_id);
1425
1426 /* store pointer to fh in private_data member of filep */
1427 file->private_data = fh;
1428 fh->layer = layer;
1429 fh->disp_dev = disp_dev;
1430
1431 if (!layer->usrs) {
1432
1433 /* First claim the layer for this device */
1434 err = osd_device->ops.request_layer(osd_device,
1435 layer->layer_info.id);
1436 if (err < 0) {
1437 /* Couldn't get layer */
1438 v4l2_err(&vpbe_dev->v4l2_dev,
1439 "Display Manager failed to allocate layer\n");
1440 kfree(fh);
1441 return -EINVAL;
1442 }
1443 }
1444 /* Increment layer usrs counter */
1445 layer->usrs++;
1446 /* Set io_allowed member to false */
1447 fh->io_allowed = 0;
1448 /* Initialize priority of this instance to default priority */
1449 fh->prio = V4L2_PRIORITY_UNSET;
1450 v4l2_prio_open(&layer->prio, &fh->prio);
1451 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
1452 "vpbe display device opened successfully\n");
1453 return 0;
1454}
1455
1456/*
1457 * vpbe_display_release()
1458 * This function deletes buffer queue, frees the buffers and the davinci
1459 * display file * handle
1460 */
1461static int vpbe_display_release(struct file *file)
1462{
1463 /* Get the layer object and file handle object */
1464 struct vpbe_fh *fh = file->private_data;
1465 struct vpbe_layer *layer = fh->layer;
1466 struct osd_layer_config *cfg = &layer->layer_info.config;
1467 struct vpbe_display *disp_dev = fh->disp_dev;
1468 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
1469 struct osd_state *osd_device = disp_dev->osd_device;
1470
1471 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_release\n");
1472
1473 /* if this instance is doing IO */
1474 if (fh->io_allowed) {
1475 /* Reset io_usrs member of layer object */
1476 layer->io_usrs = 0;
1477
1478 osd_device->ops.disable_layer(osd_device,
1479 layer->layer_info.id);
1480 layer->started = 0;
1481 /* Free buffers allocated */
1482 videobuf_queue_cancel(&layer->buffer_queue);
1483 videobuf_mmap_free(&layer->buffer_queue);
1484 }
1485
1486 /* Decrement layer usrs counter */
1487 layer->usrs--;
1488 /* If this file handle has initialize encoder device, reset it */
1489 if (!layer->usrs) {
1490 if (cfg->pixfmt == PIXFMT_NV12) {
1491 struct vpbe_layer *otherlayer;
1492 otherlayer =
1493 _vpbe_display_get_other_win_layer(disp_dev, layer);
1494 osd_device->ops.disable_layer(osd_device,
1495 otherlayer->layer_info.id);
1496 osd_device->ops.release_layer(osd_device,
1497 otherlayer->layer_info.id);
1498 }
1499 osd_device->ops.disable_layer(osd_device,
1500 layer->layer_info.id);
1501 osd_device->ops.release_layer(osd_device,
1502 layer->layer_info.id);
1503 }
1504 /* Close the priority */
1505 v4l2_prio_close(&layer->prio, fh->prio);
1506 file->private_data = NULL;
1507
1508 /* Free memory allocated to file handle object */
1509 kfree(fh);
1510
1511 disp_dev->cbcr_ofst = 0;
1512
1513 return 0;
1514}
1515
1516#ifdef CONFIG_VIDEO_ADV_DEBUG
1517static int vpbe_display_g_register(struct file *file, void *priv,
1518 struct v4l2_dbg_register *reg)
1519{
1520 struct v4l2_dbg_match *match = &reg->match;
1521
1522 if (match->type >= 2) {
1523 v4l2_subdev_call(vpbe_dev->venc,
1524 core,
1525 g_register,
1526 reg);
1527 }
1528
1529 return 0;
1530}
1531
1532static int vpbe_display_s_register(struct file *file, void *priv,
1533 struct v4l2_dbg_register *reg)
1534{
1535 return 0;
1536}
1537#endif
1538
1539/* vpbe capture ioctl operations */
1540static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {
1541 .vidioc_querycap = vpbe_display_querycap,
1542 .vidioc_g_fmt_vid_out = vpbe_display_g_fmt,
1543 .vidioc_enum_fmt_vid_out = vpbe_display_enum_fmt,
1544 .vidioc_s_fmt_vid_out = vpbe_display_s_fmt,
1545 .vidioc_try_fmt_vid_out = vpbe_display_try_fmt,
1546 .vidioc_reqbufs = vpbe_display_reqbufs,
1547 .vidioc_querybuf = vpbe_display_querybuf,
1548 .vidioc_qbuf = vpbe_display_qbuf,
1549 .vidioc_dqbuf = vpbe_display_dqbuf,
1550 .vidioc_streamon = vpbe_display_streamon,
1551 .vidioc_streamoff = vpbe_display_streamoff,
1552 .vidioc_cropcap = vpbe_display_cropcap,
1553 .vidioc_g_crop = vpbe_display_g_crop,
1554 .vidioc_s_crop = vpbe_display_s_crop,
1555 .vidioc_g_priority = vpbe_display_g_priority,
1556 .vidioc_s_priority = vpbe_display_s_priority,
1557 .vidioc_s_std = vpbe_display_s_std,
1558 .vidioc_g_std = vpbe_display_g_std,
1559 .vidioc_enum_output = vpbe_display_enum_output,
1560 .vidioc_s_output = vpbe_display_s_output,
1561 .vidioc_g_output = vpbe_display_g_output,
1562 .vidioc_s_dv_preset = vpbe_display_s_dv_preset,
1563 .vidioc_g_dv_preset = vpbe_display_g_dv_preset,
1564 .vidioc_enum_dv_presets = vpbe_display_enum_dv_presets,
1565#ifdef CONFIG_VIDEO_ADV_DEBUG
1566 .vidioc_g_register = vpbe_display_g_register,
1567 .vidioc_s_register = vpbe_display_s_register,
1568#endif
1569};
1570
1571static struct v4l2_file_operations vpbe_fops = {
1572 .owner = THIS_MODULE,
1573 .open = vpbe_display_open,
1574 .release = vpbe_display_release,
1575 .unlocked_ioctl = video_ioctl2,
1576 .mmap = vpbe_display_mmap,
1577 .poll = vpbe_display_poll
1578};
1579
1580static int vpbe_device_get(struct device *dev, void *data)
1581{
1582 struct platform_device *pdev = to_platform_device(dev);
1583 struct vpbe_display *vpbe_disp = data;
1584
1585 if (strcmp("vpbe_controller", pdev->name) == 0)
1586 vpbe_disp->vpbe_dev = platform_get_drvdata(pdev);
1587
1588 if (strcmp("vpbe-osd", pdev->name) == 0)
1589 vpbe_disp->osd_device = platform_get_drvdata(pdev);
1590
1591 return 0;
1592}
1593
1594static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
1595 struct platform_device *pdev)
1596{
1597 struct vpbe_layer *vpbe_display_layer = NULL;
1598 struct video_device *vbd = NULL;
1599
1600 /* Allocate memory for four plane display objects */
1601
1602 disp_dev->dev[i] =
1603 kzalloc(sizeof(struct vpbe_layer), GFP_KERNEL);
1604
1605 /* If memory allocation fails, return error */
1606 if (!disp_dev->dev[i]) {
1607 printk(KERN_ERR "ran out of memory\n");
1608 return -ENOMEM;
1609 }
1610 spin_lock_init(&disp_dev->dev[i]->irqlock);
1611 mutex_init(&disp_dev->dev[i]->opslock);
1612
1613 /* Get the pointer to the layer object */
1614 vpbe_display_layer = disp_dev->dev[i];
1615 vbd = &vpbe_display_layer->video_dev;
1616 /* Initialize field of video device */
1617 vbd->release = video_device_release_empty;
1618 vbd->fops = &vpbe_fops;
1619 vbd->ioctl_ops = &vpbe_ioctl_ops;
1620 vbd->minor = -1;
1621 vbd->v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev;
1622 vbd->lock = &vpbe_display_layer->opslock;
1623
1624 if (disp_dev->vpbe_dev->current_timings.timings_type &
1625 VPBE_ENC_STD) {
1626 vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
1627 vbd->current_norm =
1628 disp_dev->vpbe_dev->
1629 current_timings.timings.std_id;
1630 } else
1631 vbd->current_norm = 0;
1632
1633 snprintf(vbd->name, sizeof(vbd->name),
1634 "DaVinci_VPBE Display_DRIVER_V%d.%d.%d",
1635 (VPBE_DISPLAY_VERSION_CODE >> 16) & 0xff,
1636 (VPBE_DISPLAY_VERSION_CODE >> 8) & 0xff,
1637 (VPBE_DISPLAY_VERSION_CODE) & 0xff);
1638
1639 vpbe_display_layer->device_id = i;
1640
1641 vpbe_display_layer->layer_info.id =
1642 ((i == VPBE_DISPLAY_DEVICE_0) ? WIN_VID0 : WIN_VID1);
1643
1644 /* Initialize prio member of layer object */
1645 v4l2_prio_init(&vpbe_display_layer->prio);
1646
1647 return 0;
1648}
1649
1650static __devinit int register_device(struct vpbe_layer *vpbe_display_layer,
1651 struct vpbe_display *disp_dev,
1652 struct platform_device *pdev) {
1653 int err;
1654
1655 v4l2_info(&disp_dev->vpbe_dev->v4l2_dev,
1656 "Trying to register VPBE display device.\n");
1657 v4l2_info(&disp_dev->vpbe_dev->v4l2_dev,
1658 "layer=%x,layer->video_dev=%x\n",
1659 (int)vpbe_display_layer,
1660 (int)&vpbe_display_layer->video_dev);
1661
1662 err = video_register_device(&vpbe_display_layer->video_dev,
1663 VFL_TYPE_GRABBER,
1664 -1);
1665 if (err)
1666 return -ENODEV;
1667
1668 vpbe_display_layer->disp_dev = disp_dev;
1669 /* set the driver data in platform device */
1670 platform_set_drvdata(pdev, disp_dev);
1671 video_set_drvdata(&vpbe_display_layer->video_dev,
1672 vpbe_display_layer);
1673
1674 return 0;
1675}
1676
1677
1678
1679/*
1680 * vpbe_display_probe()
1681 * This function creates device entries by register itself to the V4L2 driver
1682 * and initializes fields of each layer objects
1683 */
1684static __devinit int vpbe_display_probe(struct platform_device *pdev)
1685{
1686 struct vpbe_layer *vpbe_display_layer;
1687 struct vpbe_display *disp_dev;
1688 struct resource *res = NULL;
1689 int k;
1690 int i;
1691 int err;
1692 int irq;
1693
1694 printk(KERN_DEBUG "vpbe_display_probe\n");
1695 /* Allocate memory for vpbe_display */
1696 disp_dev = kzalloc(sizeof(struct vpbe_display), GFP_KERNEL);
1697 if (!disp_dev) {
1698 printk(KERN_ERR "ran out of memory\n");
1699 return -ENOMEM;
1700 }
1701
1702 spin_lock_init(&disp_dev->dma_queue_lock);
1703 /*
1704 * Scan all the platform devices to find the vpbe
1705 * controller device and get the vpbe_dev object
1706 */
1707 err = bus_for_each_dev(&platform_bus_type, NULL, disp_dev,
1708 vpbe_device_get);
1709 if (err < 0)
1710 return err;
1711 /* Initialize the vpbe display controller */
1712 if (NULL != disp_dev->vpbe_dev->ops.initialize) {
1713 err = disp_dev->vpbe_dev->ops.initialize(&pdev->dev,
1714 disp_dev->vpbe_dev);
1715 if (err) {
1716 v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
1717 "Error initing vpbe\n");
1718 err = -ENOMEM;
1719 goto probe_out;
1720 }
1721 }
1722
1723 for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
1724 if (init_vpbe_layer(i, disp_dev, pdev)) {
1725 err = -ENODEV;
1726 goto probe_out;
1727 }
1728 }
1729
1730 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1731 if (!res) {
1732 v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
1733 "Unable to get VENC interrupt resource\n");
1734 err = -ENODEV;
1735 goto probe_out;
1736 }
1737
1738 irq = res->start;
1739 if (request_irq(irq, venc_isr, IRQF_DISABLED, VPBE_DISPLAY_DRIVER,
1740 disp_dev)) {
1741 v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
1742 "Unable to request interrupt\n");
1743 err = -ENODEV;
1744 goto probe_out;
1745 }
1746
1747 for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
1748 if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
1749 err = -ENODEV;
1750 goto probe_out;
1751 }
1752 }
1753
1754 printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
1755 return 0;
1756
1757probe_out:
1758 free_irq(res->start, disp_dev);
1759 for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
1760 /* Get the pointer to the layer object */
1761 vpbe_display_layer = disp_dev->dev[k];
1762 /* Unregister video device */
1763 if (vpbe_display_layer) {
1764 video_unregister_device(
1765 &vpbe_display_layer->video_dev);
1766 kfree(disp_dev->dev[k]);
1767 }
1768 }
1769 kfree(disp_dev);
1770 return err;
1771}
1772
1773/*
1774 * vpbe_display_remove()
1775 * It un-register hardware layer from V4L2 driver
1776 */
1777static int vpbe_display_remove(struct platform_device *pdev)
1778{
1779 struct vpbe_layer *vpbe_display_layer;
1780 struct vpbe_display *disp_dev = platform_get_drvdata(pdev);
1781 struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
1782 struct resource *res;
1783 int i;
1784
1785 v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_remove\n");
1786
1787 /* unregister irq */
1788 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1789 free_irq(res->start, disp_dev);
1790
1791 /* deinitialize the vpbe display controller */
1792 if (NULL != vpbe_dev->ops.deinitialize)
1793 vpbe_dev->ops.deinitialize(&pdev->dev, vpbe_dev);
1794 /* un-register device */
1795 for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
1796 /* Get the pointer to the layer object */
1797 vpbe_display_layer = disp_dev->dev[i];
1798 /* Unregister video device */
1799 video_unregister_device(&vpbe_display_layer->video_dev);
1800
1801 }
1802 for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
1803 kfree(disp_dev->dev[i]);
1804 disp_dev->dev[i] = NULL;
1805 }
1806
1807 return 0;
1808}
1809
1810static struct platform_driver vpbe_display_driver = {
1811 .driver = {
1812 .name = VPBE_DISPLAY_DRIVER,
1813 .owner = THIS_MODULE,
1814 .bus = &platform_bus_type,
1815 },
1816 .probe = vpbe_display_probe,
1817 .remove = __devexit_p(vpbe_display_remove),
1818};
1819
1820/*
1821 * vpbe_display_init()
1822 * This function registers device and driver to the kernel, requests irq
1823 * handler and allocates memory for layer objects
1824 */
1825static __devinit int vpbe_display_init(void)
1826{
1827 int err;
1828
1829 printk(KERN_DEBUG "vpbe_display_init\n");
1830
1831 /* Register driver to the kernel */
1832 err = platform_driver_register(&vpbe_display_driver);
1833 if (0 != err)
1834 return err;
1835
1836 printk(KERN_DEBUG "vpbe_display_init:"
1837 "VPBE V4L2 Display Driver V1.0 loaded\n");
1838 return 0;
1839}
1840
1841/*
1842 * vpbe_display_cleanup()
1843 * This function un-registers device and driver to the kernel, frees requested
1844 * irq handler and de-allocates memory allocated for layer objects.
1845 */
1846static void vpbe_display_cleanup(void)
1847{
1848 printk(KERN_DEBUG "vpbe_display_cleanup\n");
1849
1850 /* platform driver unregister */
1851 platform_driver_unregister(&vpbe_display_driver);
1852}
1853
1854/* Function for module initialization and cleanup */
1855module_init(vpbe_display_init);
1856module_exit(vpbe_display_cleanup);
1857
1858MODULE_DESCRIPTION("TI DM644x/DM355/DM365 VPBE Display controller");
1859MODULE_LICENSE("GPL");
1860MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/media/video/davinci/vpbe_osd.c b/drivers/media/video/davinci/vpbe_osd.c
new file mode 100644
index 00000000000..5352884998f
--- /dev/null
+++ b/drivers/media/video/davinci/vpbe_osd.c
@@ -0,0 +1,1231 @@
1/*
2 * Copyright (C) 2007-2010 Texas Instruments Inc
3 * Copyright (C) 2007 MontaVista Software, Inc.
4 *
5 * Andy Lowe (alowe@mvista.com), MontaVista Software
6 * - Initial version
7 * Murali Karicheri (mkaricheri@gmail.com), Texas Instruments Ltd.
8 * - ported to sub device interface
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation version 2.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/interrupt.h>
27#include <linux/platform_device.h>
28#include <linux/clk.h>
29#include <linux/slab.h>
30
31#include <mach/io.h>
32#include <mach/cputype.h>
33#include <mach/hardware.h>
34
35#include <media/davinci/vpss.h>
36#include <media/v4l2-device.h>
37#include <media/davinci/vpbe_types.h>
38#include <media/davinci/vpbe_osd.h>
39
40#include <linux/io.h>
41#include "vpbe_osd_regs.h"
42
43#define MODULE_NAME VPBE_OSD_SUBDEV_NAME
44
45/* register access routines */
46static inline u32 osd_read(struct osd_state *sd, u32 offset)
47{
48 struct osd_state *osd = sd;
49
50 return readl(osd->osd_base + offset);
51}
52
53static inline u32 osd_write(struct osd_state *sd, u32 val, u32 offset)
54{
55 struct osd_state *osd = sd;
56
57 writel(val, osd->osd_base + offset);
58
59 return val;
60}
61
62static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset)
63{
64 struct osd_state *osd = sd;
65
66 u32 addr = osd->osd_base + offset;
67 u32 val = readl(addr) | mask;
68
69 writel(val, addr);
70
71 return val;
72}
73
74static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset)
75{
76 struct osd_state *osd = sd;
77
78 u32 addr = osd->osd_base + offset;
79 u32 val = readl(addr) & ~mask;
80
81 writel(val, addr);
82
83 return val;
84}
85
86static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val,
87 u32 offset)
88{
89 struct osd_state *osd = sd;
90
91 u32 addr = osd->osd_base + offset;
92 u32 new_val = (readl(addr) & ~mask) | (val & mask);
93
94 writel(new_val, addr);
95
96 return new_val;
97}
98
99/* define some macros for layer and pixfmt classification */
100#define is_osd_win(layer) (((layer) == WIN_OSD0) || ((layer) == WIN_OSD1))
101#define is_vid_win(layer) (((layer) == WIN_VID0) || ((layer) == WIN_VID1))
102#define is_rgb_pixfmt(pixfmt) \
103 (((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888))
104#define is_yc_pixfmt(pixfmt) \
105 (((pixfmt) == PIXFMT_YCbCrI) || ((pixfmt) == PIXFMT_YCrCbI) || \
106 ((pixfmt) == PIXFMT_NV12))
107#define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X
108#define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5)
109
110/**
111 * _osd_dm6446_vid0_pingpong() - field inversion fix for DM6446
112 * @sd - ptr to struct osd_state
113 * @field_inversion - inversion flag
114 * @fb_base_phys - frame buffer address
115 * @lconfig - ptr to layer config
116 *
117 * This routine implements a workaround for the field signal inversion silicon
118 * erratum described in Advisory 1.3.8 for the DM6446. The fb_base_phys and
119 * lconfig parameters apply to the vid0 window. This routine should be called
120 * whenever the vid0 layer configuration or start address is modified, or when
121 * the OSD field inversion setting is modified.
122 * Returns: 1 if the ping-pong buffers need to be toggled in the vsync isr, or
123 * 0 otherwise
124 */
125static int _osd_dm6446_vid0_pingpong(struct osd_state *sd,
126 int field_inversion,
127 unsigned long fb_base_phys,
128 const struct osd_layer_config *lconfig)
129{
130 struct osd_platform_data *pdata;
131
132 pdata = (struct osd_platform_data *)sd->dev->platform_data;
133 if (pdata->field_inv_wa_enable) {
134
135 if (!field_inversion || !lconfig->interlaced) {
136 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
137 osd_write(sd, fb_base_phys & ~0x1F, OSD_PPVWIN0ADR);
138 osd_modify(sd, OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, 0,
139 OSD_MISCCTL);
140 return 0;
141 } else {
142 unsigned miscctl = OSD_MISCCTL_PPRV;
143
144 osd_write(sd,
145 (fb_base_phys & ~0x1F) - lconfig->line_length,
146 OSD_VIDWIN0ADR);
147 osd_write(sd,
148 (fb_base_phys & ~0x1F) + lconfig->line_length,
149 OSD_PPVWIN0ADR);
150 osd_modify(sd,
151 OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, miscctl,
152 OSD_MISCCTL);
153
154 return 1;
155 }
156 }
157
158 return 0;
159}
160
161static void _osd_set_field_inversion(struct osd_state *sd, int enable)
162{
163 unsigned fsinv = 0;
164
165 if (enable)
166 fsinv = OSD_MODE_FSINV;
167
168 osd_modify(sd, OSD_MODE_FSINV, fsinv, OSD_MODE);
169}
170
171static void _osd_set_blink_attribute(struct osd_state *sd, int enable,
172 enum osd_blink_interval blink)
173{
174 u32 osdatrmd = 0;
175
176 if (enable) {
177 osdatrmd |= OSD_OSDATRMD_BLNK;
178 osdatrmd |= blink << OSD_OSDATRMD_BLNKINT_SHIFT;
179 }
180 /* caller must ensure that OSD1 is configured in attribute mode */
181 osd_modify(sd, OSD_OSDATRMD_BLNKINT | OSD_OSDATRMD_BLNK, osdatrmd,
182 OSD_OSDATRMD);
183}
184
185static void _osd_set_rom_clut(struct osd_state *sd,
186 enum osd_rom_clut rom_clut)
187{
188 if (rom_clut == ROM_CLUT0)
189 osd_clear(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
190 else
191 osd_set(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL);
192}
193
194static void _osd_set_palette_map(struct osd_state *sd,
195 enum osd_win_layer osdwin,
196 unsigned char pixel_value,
197 unsigned char clut_index,
198 enum osd_pix_format pixfmt)
199{
200 static const int map_2bpp[] = { 0, 5, 10, 15 };
201 static const int map_1bpp[] = { 0, 15 };
202 int bmp_offset;
203 int bmp_shift;
204 int bmp_mask;
205 int bmp_reg;
206
207 switch (pixfmt) {
208 case PIXFMT_1BPP:
209 bmp_reg = map_1bpp[pixel_value & 0x1];
210 break;
211 case PIXFMT_2BPP:
212 bmp_reg = map_2bpp[pixel_value & 0x3];
213 break;
214 case PIXFMT_4BPP:
215 bmp_reg = pixel_value & 0xf;
216 break;
217 default:
218 return;
219 }
220
221 switch (osdwin) {
222 case OSDWIN_OSD0:
223 bmp_offset = OSD_W0BMP01 + (bmp_reg >> 1) * sizeof(u32);
224 break;
225 case OSDWIN_OSD1:
226 bmp_offset = OSD_W1BMP01 + (bmp_reg >> 1) * sizeof(u32);
227 break;
228 default:
229 return;
230 }
231
232 if (bmp_reg & 1) {
233 bmp_shift = 8;
234 bmp_mask = 0xff << 8;
235 } else {
236 bmp_shift = 0;
237 bmp_mask = 0xff;
238 }
239
240 osd_modify(sd, bmp_mask, clut_index << bmp_shift, bmp_offset);
241}
242
243static void _osd_set_rec601_attenuation(struct osd_state *sd,
244 enum osd_win_layer osdwin, int enable)
245{
246 switch (osdwin) {
247 case OSDWIN_OSD0:
248 osd_modify(sd, OSD_OSDWIN0MD_ATN0E,
249 enable ? OSD_OSDWIN0MD_ATN0E : 0,
250 OSD_OSDWIN0MD);
251 break;
252 case OSDWIN_OSD1:
253 osd_modify(sd, OSD_OSDWIN1MD_ATN1E,
254 enable ? OSD_OSDWIN1MD_ATN1E : 0,
255 OSD_OSDWIN1MD);
256 break;
257 }
258}
259
260static void _osd_set_blending_factor(struct osd_state *sd,
261 enum osd_win_layer osdwin,
262 enum osd_blending_factor blend)
263{
264 switch (osdwin) {
265 case OSDWIN_OSD0:
266 osd_modify(sd, OSD_OSDWIN0MD_BLND0,
267 blend << OSD_OSDWIN0MD_BLND0_SHIFT, OSD_OSDWIN0MD);
268 break;
269 case OSDWIN_OSD1:
270 osd_modify(sd, OSD_OSDWIN1MD_BLND1,
271 blend << OSD_OSDWIN1MD_BLND1_SHIFT, OSD_OSDWIN1MD);
272 break;
273 }
274}
275
276static void _osd_enable_color_key(struct osd_state *sd,
277 enum osd_win_layer osdwin,
278 unsigned colorkey,
279 enum osd_pix_format pixfmt)
280{
281 switch (pixfmt) {
282 case PIXFMT_RGB565:
283 osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS,
284 OSD_TRANSPVAL);
285 break;
286 default:
287 break;
288 }
289
290 switch (osdwin) {
291 case OSDWIN_OSD0:
292 osd_set(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
293 break;
294 case OSDWIN_OSD1:
295 osd_set(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
296 break;
297 }
298}
299
300static void _osd_disable_color_key(struct osd_state *sd,
301 enum osd_win_layer osdwin)
302{
303 switch (osdwin) {
304 case OSDWIN_OSD0:
305 osd_clear(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD);
306 break;
307 case OSDWIN_OSD1:
308 osd_clear(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD);
309 break;
310 }
311}
312
313static void _osd_set_osd_clut(struct osd_state *sd,
314 enum osd_win_layer osdwin,
315 enum osd_clut clut)
316{
317 u32 winmd = 0;
318
319 switch (osdwin) {
320 case OSDWIN_OSD0:
321 if (clut == RAM_CLUT)
322 winmd |= OSD_OSDWIN0MD_CLUTS0;
323 osd_modify(sd, OSD_OSDWIN0MD_CLUTS0, winmd, OSD_OSDWIN0MD);
324 break;
325 case OSDWIN_OSD1:
326 if (clut == RAM_CLUT)
327 winmd |= OSD_OSDWIN1MD_CLUTS1;
328 osd_modify(sd, OSD_OSDWIN1MD_CLUTS1, winmd, OSD_OSDWIN1MD);
329 break;
330 }
331}
332
333static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer,
334 enum osd_zoom_factor h_zoom,
335 enum osd_zoom_factor v_zoom)
336{
337 u32 winmd = 0;
338
339 switch (layer) {
340 case WIN_OSD0:
341 winmd |= (h_zoom << OSD_OSDWIN0MD_OHZ0_SHIFT);
342 winmd |= (v_zoom << OSD_OSDWIN0MD_OVZ0_SHIFT);
343 osd_modify(sd, OSD_OSDWIN0MD_OHZ0 | OSD_OSDWIN0MD_OVZ0, winmd,
344 OSD_OSDWIN0MD);
345 break;
346 case WIN_VID0:
347 winmd |= (h_zoom << OSD_VIDWINMD_VHZ0_SHIFT);
348 winmd |= (v_zoom << OSD_VIDWINMD_VVZ0_SHIFT);
349 osd_modify(sd, OSD_VIDWINMD_VHZ0 | OSD_VIDWINMD_VVZ0, winmd,
350 OSD_VIDWINMD);
351 break;
352 case WIN_OSD1:
353 winmd |= (h_zoom << OSD_OSDWIN1MD_OHZ1_SHIFT);
354 winmd |= (v_zoom << OSD_OSDWIN1MD_OVZ1_SHIFT);
355 osd_modify(sd, OSD_OSDWIN1MD_OHZ1 | OSD_OSDWIN1MD_OVZ1, winmd,
356 OSD_OSDWIN1MD);
357 break;
358 case WIN_VID1:
359 winmd |= (h_zoom << OSD_VIDWINMD_VHZ1_SHIFT);
360 winmd |= (v_zoom << OSD_VIDWINMD_VVZ1_SHIFT);
361 osd_modify(sd, OSD_VIDWINMD_VHZ1 | OSD_VIDWINMD_VVZ1, winmd,
362 OSD_VIDWINMD);
363 break;
364 }
365}
366
367static void _osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
368{
369 switch (layer) {
370 case WIN_OSD0:
371 osd_clear(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
372 break;
373 case WIN_VID0:
374 osd_clear(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
375 break;
376 case WIN_OSD1:
377 /* disable attribute mode as well as disabling the window */
378 osd_clear(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
379 OSD_OSDWIN1MD);
380 break;
381 case WIN_VID1:
382 osd_clear(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
383 break;
384 }
385}
386
387static void osd_disable_layer(struct osd_state *sd, enum osd_layer layer)
388{
389 struct osd_state *osd = sd;
390 struct osd_window_state *win = &osd->win[layer];
391 unsigned long flags;
392
393 spin_lock_irqsave(&osd->lock, flags);
394
395 if (!win->is_enabled) {
396 spin_unlock_irqrestore(&osd->lock, flags);
397 return;
398 }
399 win->is_enabled = 0;
400
401 _osd_disable_layer(sd, layer);
402
403 spin_unlock_irqrestore(&osd->lock, flags);
404}
405
406static void _osd_enable_attribute_mode(struct osd_state *sd)
407{
408 /* enable attribute mode for OSD1 */
409 osd_set(sd, OSD_OSDWIN1MD_OASW, OSD_OSDWIN1MD);
410}
411
412static void _osd_enable_layer(struct osd_state *sd, enum osd_layer layer)
413{
414 switch (layer) {
415 case WIN_OSD0:
416 osd_set(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD);
417 break;
418 case WIN_VID0:
419 osd_set(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD);
420 break;
421 case WIN_OSD1:
422 /* enable OSD1 and disable attribute mode */
423 osd_modify(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1,
424 OSD_OSDWIN1MD_OACT1, OSD_OSDWIN1MD);
425 break;
426 case WIN_VID1:
427 osd_set(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD);
428 break;
429 }
430}
431
432static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer,
433 int otherwin)
434{
435 struct osd_state *osd = sd;
436 struct osd_window_state *win = &osd->win[layer];
437 struct osd_layer_config *cfg = &win->lconfig;
438 unsigned long flags;
439
440 spin_lock_irqsave(&osd->lock, flags);
441
442 /*
443 * use otherwin flag to know this is the other vid window
444 * in YUV420 mode, if is, skip this check
445 */
446 if (!otherwin && (!win->is_allocated ||
447 !win->fb_base_phys ||
448 !cfg->line_length ||
449 !cfg->xsize ||
450 !cfg->ysize)) {
451 spin_unlock_irqrestore(&osd->lock, flags);
452 return -1;
453 }
454
455 if (win->is_enabled) {
456 spin_unlock_irqrestore(&osd->lock, flags);
457 return 0;
458 }
459 win->is_enabled = 1;
460
461 if (cfg->pixfmt != PIXFMT_OSD_ATTR)
462 _osd_enable_layer(sd, layer);
463 else {
464 _osd_enable_attribute_mode(sd);
465 _osd_set_blink_attribute(sd, osd->is_blinking, osd->blink);
466 }
467
468 spin_unlock_irqrestore(&osd->lock, flags);
469
470 return 0;
471}
472
473static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer,
474 unsigned long fb_base_phys,
475 unsigned long cbcr_ofst)
476{
477 switch (layer) {
478 case WIN_OSD0:
479 osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR);
480 break;
481 case WIN_VID0:
482 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR);
483 break;
484 case WIN_OSD1:
485 osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR);
486 break;
487 case WIN_VID1:
488 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR);
489 break;
490 }
491}
492
493static void osd_start_layer(struct osd_state *sd, enum osd_layer layer,
494 unsigned long fb_base_phys,
495 unsigned long cbcr_ofst)
496{
497 struct osd_state *osd = sd;
498 struct osd_window_state *win = &osd->win[layer];
499 struct osd_layer_config *cfg = &win->lconfig;
500 unsigned long flags;
501
502 spin_lock_irqsave(&osd->lock, flags);
503
504 win->fb_base_phys = fb_base_phys & ~0x1F;
505 _osd_start_layer(sd, layer, fb_base_phys, cbcr_ofst);
506
507 if (layer == WIN_VID0) {
508 osd->pingpong =
509 _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
510 win->fb_base_phys,
511 cfg);
512 }
513
514 spin_unlock_irqrestore(&osd->lock, flags);
515}
516
517static void osd_get_layer_config(struct osd_state *sd, enum osd_layer layer,
518 struct osd_layer_config *lconfig)
519{
520 struct osd_state *osd = sd;
521 struct osd_window_state *win = &osd->win[layer];
522 unsigned long flags;
523
524 spin_lock_irqsave(&osd->lock, flags);
525
526 *lconfig = win->lconfig;
527
528 spin_unlock_irqrestore(&osd->lock, flags);
529}
530
531/**
532 * try_layer_config() - Try a specific configuration for the layer
533 * @sd - ptr to struct osd_state
534 * @layer - layer to configure
535 * @lconfig - layer configuration to try
536 *
537 * If the requested lconfig is completely rejected and the value of lconfig on
538 * exit is the current lconfig, then try_layer_config() returns 1. Otherwise,
539 * try_layer_config() returns 0. A return value of 0 does not necessarily mean
540 * that the value of lconfig on exit is identical to the value of lconfig on
541 * entry, but merely that it represents a change from the current lconfig.
542 */
543static int try_layer_config(struct osd_state *sd, enum osd_layer layer,
544 struct osd_layer_config *lconfig)
545{
546 struct osd_state *osd = sd;
547 struct osd_window_state *win = &osd->win[layer];
548 int bad_config;
549
550 /* verify that the pixel format is compatible with the layer */
551 switch (lconfig->pixfmt) {
552 case PIXFMT_1BPP:
553 case PIXFMT_2BPP:
554 case PIXFMT_4BPP:
555 case PIXFMT_8BPP:
556 case PIXFMT_RGB565:
557 bad_config = !is_osd_win(layer);
558 break;
559 case PIXFMT_YCbCrI:
560 case PIXFMT_YCrCbI:
561 bad_config = !is_vid_win(layer);
562 break;
563 case PIXFMT_RGB888:
564 bad_config = !is_vid_win(layer);
565 break;
566 case PIXFMT_NV12:
567 bad_config = 1;
568 break;
569 case PIXFMT_OSD_ATTR:
570 bad_config = (layer != WIN_OSD1);
571 break;
572 default:
573 bad_config = 1;
574 break;
575 }
576 if (bad_config) {
577 /*
578 * The requested pixel format is incompatible with the layer,
579 * so keep the current layer configuration.
580 */
581 *lconfig = win->lconfig;
582 return bad_config;
583 }
584
585 /* DM6446: */
586 /* only one OSD window at a time can use RGB pixel formats */
587 if (is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) {
588 enum osd_pix_format pixfmt;
589 if (layer == WIN_OSD0)
590 pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt;
591 else
592 pixfmt = osd->win[WIN_OSD0].lconfig.pixfmt;
593
594 if (is_rgb_pixfmt(pixfmt)) {
595 /*
596 * The other OSD window is already configured for an
597 * RGB, so keep the current layer configuration.
598 */
599 *lconfig = win->lconfig;
600 return 1;
601 }
602 }
603
604 /* DM6446: only one video window at a time can use RGB888 */
605 if (is_vid_win(layer) && lconfig->pixfmt == PIXFMT_RGB888) {
606 enum osd_pix_format pixfmt;
607
608 if (layer == WIN_VID0)
609 pixfmt = osd->win[WIN_VID1].lconfig.pixfmt;
610 else
611 pixfmt = osd->win[WIN_VID0].lconfig.pixfmt;
612
613 if (pixfmt == PIXFMT_RGB888) {
614 /*
615 * The other video window is already configured for
616 * RGB888, so keep the current layer configuration.
617 */
618 *lconfig = win->lconfig;
619 return 1;
620 }
621 }
622
623 /* window dimensions must be non-zero */
624 if (!lconfig->line_length || !lconfig->xsize || !lconfig->ysize) {
625 *lconfig = win->lconfig;
626 return 1;
627 }
628
629 /* round line_length up to a multiple of 32 */
630 lconfig->line_length = ((lconfig->line_length + 31) / 32) * 32;
631 lconfig->line_length =
632 min(lconfig->line_length, (unsigned)MAX_LINE_LENGTH);
633 lconfig->xsize = min(lconfig->xsize, (unsigned)MAX_WIN_SIZE);
634 lconfig->ysize = min(lconfig->ysize, (unsigned)MAX_WIN_SIZE);
635 lconfig->xpos = min(lconfig->xpos, (unsigned)MAX_WIN_SIZE);
636 lconfig->ypos = min(lconfig->ypos, (unsigned)MAX_WIN_SIZE);
637 lconfig->interlaced = (lconfig->interlaced != 0);
638 if (lconfig->interlaced) {
639 /* ysize and ypos must be even for interlaced displays */
640 lconfig->ysize &= ~1;
641 lconfig->ypos &= ~1;
642 }
643
644 return 0;
645}
646
647static void _osd_disable_vid_rgb888(struct osd_state *sd)
648{
649 /*
650 * The DM6446 supports RGB888 pixel format in a single video window.
651 * This routine disables RGB888 pixel format for both video windows.
652 * The caller must ensure that neither video window is currently
653 * configured for RGB888 pixel format.
654 */
655 osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL);
656}
657
658static void _osd_enable_vid_rgb888(struct osd_state *sd,
659 enum osd_layer layer)
660{
661 /*
662 * The DM6446 supports RGB888 pixel format in a single video window.
663 * This routine enables RGB888 pixel format for the specified video
664 * window. The caller must ensure that the other video window is not
665 * currently configured for RGB888 pixel format, as this routine will
666 * disable RGB888 pixel format for the other window.
667 */
668 if (layer == WIN_VID0) {
669 osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
670 OSD_MISCCTL_RGBEN, OSD_MISCCTL);
671 } else if (layer == WIN_VID1) {
672 osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
673 OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN,
674 OSD_MISCCTL);
675 }
676}
677
678static void _osd_set_cbcr_order(struct osd_state *sd,
679 enum osd_pix_format pixfmt)
680{
681 /*
682 * The caller must ensure that all windows using YC pixfmt use the same
683 * Cb/Cr order.
684 */
685 if (pixfmt == PIXFMT_YCbCrI)
686 osd_clear(sd, OSD_MODE_CS, OSD_MODE);
687 else if (pixfmt == PIXFMT_YCrCbI)
688 osd_set(sd, OSD_MODE_CS, OSD_MODE);
689}
690
691static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
692 const struct osd_layer_config *lconfig)
693{
694 u32 winmd = 0, winmd_mask = 0, bmw = 0;
695
696 _osd_set_cbcr_order(sd, lconfig->pixfmt);
697
698 switch (layer) {
699 case WIN_OSD0:
700 winmd_mask |= OSD_OSDWIN0MD_RGB0E;
701 if (lconfig->pixfmt == PIXFMT_RGB565)
702 winmd |= OSD_OSDWIN0MD_RGB0E;
703
704 winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0;
705
706 switch (lconfig->pixfmt) {
707 case PIXFMT_1BPP:
708 bmw = 0;
709 break;
710 case PIXFMT_2BPP:
711 bmw = 1;
712 break;
713 case PIXFMT_4BPP:
714 bmw = 2;
715 break;
716 case PIXFMT_8BPP:
717 bmw = 3;
718 break;
719 default:
720 break;
721 }
722 winmd |= (bmw << OSD_OSDWIN0MD_BMW0_SHIFT);
723
724 if (lconfig->interlaced)
725 winmd |= OSD_OSDWIN0MD_OFF0;
726
727 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN0MD);
728 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN0OFST);
729 osd_write(sd, lconfig->xpos, OSD_OSDWIN0XP);
730 osd_write(sd, lconfig->xsize, OSD_OSDWIN0XL);
731 if (lconfig->interlaced) {
732 osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN0YP);
733 osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN0YL);
734 } else {
735 osd_write(sd, lconfig->ypos, OSD_OSDWIN0YP);
736 osd_write(sd, lconfig->ysize, OSD_OSDWIN0YL);
737 }
738 break;
739 case WIN_VID0:
740 winmd_mask |= OSD_VIDWINMD_VFF0;
741 if (lconfig->interlaced)
742 winmd |= OSD_VIDWINMD_VFF0;
743
744 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
745 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN0OFST);
746 osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP);
747 osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL);
748 /*
749 * For YUV420P format the register contents are
750 * duplicated in both VID registers
751 */
752 if (lconfig->interlaced) {
753 osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP);
754 osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL);
755 } else {
756 osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP);
757 osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL);
758 }
759 break;
760 case WIN_OSD1:
761 /*
762 * The caller must ensure that OSD1 is disabled prior to
763 * switching from a normal mode to attribute mode or from
764 * attribute mode to a normal mode.
765 */
766 if (lconfig->pixfmt == PIXFMT_OSD_ATTR) {
767 winmd_mask |=
768 OSD_OSDWIN1MD_ATN1E | OSD_OSDWIN1MD_RGB1E |
769 OSD_OSDWIN1MD_CLUTS1 |
770 OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1;
771 } else {
772 winmd_mask |= OSD_OSDWIN1MD_RGB1E;
773 if (lconfig->pixfmt == PIXFMT_RGB565)
774 winmd |= OSD_OSDWIN1MD_RGB1E;
775
776 winmd_mask |= OSD_OSDWIN1MD_BMW1;
777 switch (lconfig->pixfmt) {
778 case PIXFMT_1BPP:
779 bmw = 0;
780 break;
781 case PIXFMT_2BPP:
782 bmw = 1;
783 break;
784 case PIXFMT_4BPP:
785 bmw = 2;
786 break;
787 case PIXFMT_8BPP:
788 bmw = 3;
789 break;
790 default:
791 break;
792 }
793 winmd |= (bmw << OSD_OSDWIN1MD_BMW1_SHIFT);
794 }
795
796 winmd_mask |= OSD_OSDWIN1MD_OFF1;
797 if (lconfig->interlaced)
798 winmd |= OSD_OSDWIN1MD_OFF1;
799
800 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN1MD);
801 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN1OFST);
802 osd_write(sd, lconfig->xpos, OSD_OSDWIN1XP);
803 osd_write(sd, lconfig->xsize, OSD_OSDWIN1XL);
804 if (lconfig->interlaced) {
805 osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN1YP);
806 osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN1YL);
807 } else {
808 osd_write(sd, lconfig->ypos, OSD_OSDWIN1YP);
809 osd_write(sd, lconfig->ysize, OSD_OSDWIN1YL);
810 }
811 break;
812 case WIN_VID1:
813 winmd_mask |= OSD_VIDWINMD_VFF1;
814 if (lconfig->interlaced)
815 winmd |= OSD_VIDWINMD_VFF1;
816
817 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD);
818 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN1OFST);
819 osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP);
820 osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL);
821 /*
822 * For YUV420P format the register contents are
823 * duplicated in both VID registers
824 */
825 osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D,
826 OSD_MISCCTL);
827
828 if (lconfig->interlaced) {
829 osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP);
830 osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL);
831 } else {
832 osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP);
833 osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL);
834 }
835 break;
836 }
837}
838
839static int osd_set_layer_config(struct osd_state *sd, enum osd_layer layer,
840 struct osd_layer_config *lconfig)
841{
842 struct osd_state *osd = sd;
843 struct osd_window_state *win = &osd->win[layer];
844 struct osd_layer_config *cfg = &win->lconfig;
845 unsigned long flags;
846 int reject_config;
847
848 spin_lock_irqsave(&osd->lock, flags);
849
850 reject_config = try_layer_config(sd, layer, lconfig);
851 if (reject_config) {
852 spin_unlock_irqrestore(&osd->lock, flags);
853 return reject_config;
854 }
855
856 /* update the current Cb/Cr order */
857 if (is_yc_pixfmt(lconfig->pixfmt))
858 osd->yc_pixfmt = lconfig->pixfmt;
859
860 /*
861 * If we are switching OSD1 from normal mode to attribute mode or from
862 * attribute mode to normal mode, then we must disable the window.
863 */
864 if (layer == WIN_OSD1) {
865 if (((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
866 (cfg->pixfmt != PIXFMT_OSD_ATTR)) ||
867 ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
868 (cfg->pixfmt == PIXFMT_OSD_ATTR))) {
869 win->is_enabled = 0;
870 _osd_disable_layer(sd, layer);
871 }
872 }
873
874 _osd_set_layer_config(sd, layer, lconfig);
875
876 if (layer == WIN_OSD1) {
877 struct osd_osdwin_state *osdwin_state =
878 &osd->osdwin[OSDWIN_OSD1];
879
880 if ((lconfig->pixfmt != PIXFMT_OSD_ATTR) &&
881 (cfg->pixfmt == PIXFMT_OSD_ATTR)) {
882 /*
883 * We just switched OSD1 from attribute mode to normal
884 * mode, so we must initialize the CLUT select, the
885 * blend factor, transparency colorkey enable, and
886 * attenuation enable (DM6446 only) bits in the
887 * OSDWIN1MD register.
888 */
889 _osd_set_osd_clut(sd, OSDWIN_OSD1,
890 osdwin_state->clut);
891 _osd_set_blending_factor(sd, OSDWIN_OSD1,
892 osdwin_state->blend);
893 if (osdwin_state->colorkey_blending) {
894 _osd_enable_color_key(sd, OSDWIN_OSD1,
895 osdwin_state->
896 colorkey,
897 lconfig->pixfmt);
898 } else
899 _osd_disable_color_key(sd, OSDWIN_OSD1);
900 _osd_set_rec601_attenuation(sd, OSDWIN_OSD1,
901 osdwin_state->
902 rec601_attenuation);
903 } else if ((lconfig->pixfmt == PIXFMT_OSD_ATTR) &&
904 (cfg->pixfmt != PIXFMT_OSD_ATTR)) {
905 /*
906 * We just switched OSD1 from normal mode to attribute
907 * mode, so we must initialize the blink enable and
908 * blink interval bits in the OSDATRMD register.
909 */
910 _osd_set_blink_attribute(sd, osd->is_blinking,
911 osd->blink);
912 }
913 }
914
915 /*
916 * If we just switched to a 1-, 2-, or 4-bits-per-pixel bitmap format
917 * then configure a default palette map.
918 */
919 if ((lconfig->pixfmt != cfg->pixfmt) &&
920 ((lconfig->pixfmt == PIXFMT_1BPP) ||
921 (lconfig->pixfmt == PIXFMT_2BPP) ||
922 (lconfig->pixfmt == PIXFMT_4BPP))) {
923 enum osd_win_layer osdwin =
924 ((layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1);
925 struct osd_osdwin_state *osdwin_state =
926 &osd->osdwin[osdwin];
927 unsigned char clut_index;
928 unsigned char clut_entries = 0;
929
930 switch (lconfig->pixfmt) {
931 case PIXFMT_1BPP:
932 clut_entries = 2;
933 break;
934 case PIXFMT_2BPP:
935 clut_entries = 4;
936 break;
937 case PIXFMT_4BPP:
938 clut_entries = 16;
939 break;
940 default:
941 break;
942 }
943 /*
944 * The default palette map maps the pixel value to the clut
945 * index, i.e. pixel value 0 maps to clut entry 0, pixel value
946 * 1 maps to clut entry 1, etc.
947 */
948 for (clut_index = 0; clut_index < 16; clut_index++) {
949 osdwin_state->palette_map[clut_index] = clut_index;
950 if (clut_index < clut_entries) {
951 _osd_set_palette_map(sd, osdwin, clut_index,
952 clut_index,
953 lconfig->pixfmt);
954 }
955 }
956 }
957
958 *cfg = *lconfig;
959 /* DM6446: configure the RGB888 enable and window selection */
960 if (osd->win[WIN_VID0].lconfig.pixfmt == PIXFMT_RGB888)
961 _osd_enable_vid_rgb888(sd, WIN_VID0);
962 else if (osd->win[WIN_VID1].lconfig.pixfmt == PIXFMT_RGB888)
963 _osd_enable_vid_rgb888(sd, WIN_VID1);
964 else
965 _osd_disable_vid_rgb888(sd);
966
967 if (layer == WIN_VID0) {
968 osd->pingpong =
969 _osd_dm6446_vid0_pingpong(sd, osd->field_inversion,
970 win->fb_base_phys,
971 cfg);
972 }
973
974 spin_unlock_irqrestore(&osd->lock, flags);
975
976 return 0;
977}
978
979static void osd_init_layer(struct osd_state *sd, enum osd_layer layer)
980{
981 struct osd_state *osd = sd;
982 struct osd_window_state *win = &osd->win[layer];
983 enum osd_win_layer osdwin;
984 struct osd_osdwin_state *osdwin_state;
985 struct osd_layer_config *cfg = &win->lconfig;
986 unsigned long flags;
987
988 spin_lock_irqsave(&osd->lock, flags);
989
990 win->is_enabled = 0;
991 _osd_disable_layer(sd, layer);
992
993 win->h_zoom = ZOOM_X1;
994 win->v_zoom = ZOOM_X1;
995 _osd_set_zoom(sd, layer, win->h_zoom, win->v_zoom);
996
997 win->fb_base_phys = 0;
998 _osd_start_layer(sd, layer, win->fb_base_phys, 0);
999
1000 cfg->line_length = 0;
1001 cfg->xsize = 0;
1002 cfg->ysize = 0;
1003 cfg->xpos = 0;
1004 cfg->ypos = 0;
1005 cfg->interlaced = 0;
1006 switch (layer) {
1007 case WIN_OSD0:
1008 case WIN_OSD1:
1009 osdwin = (layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1;
1010 osdwin_state = &osd->osdwin[osdwin];
1011 /*
1012 * Other code relies on the fact that OSD windows default to a
1013 * bitmap pixel format when they are deallocated, so don't
1014 * change this default pixel format.
1015 */
1016 cfg->pixfmt = PIXFMT_8BPP;
1017 _osd_set_layer_config(sd, layer, cfg);
1018 osdwin_state->clut = RAM_CLUT;
1019 _osd_set_osd_clut(sd, osdwin, osdwin_state->clut);
1020 osdwin_state->colorkey_blending = 0;
1021 _osd_disable_color_key(sd, osdwin);
1022 osdwin_state->blend = OSD_8_VID_0;
1023 _osd_set_blending_factor(sd, osdwin, osdwin_state->blend);
1024 osdwin_state->rec601_attenuation = 0;
1025 _osd_set_rec601_attenuation(sd, osdwin,
1026 osdwin_state->
1027 rec601_attenuation);
1028 if (osdwin == OSDWIN_OSD1) {
1029 osd->is_blinking = 0;
1030 osd->blink = BLINK_X1;
1031 }
1032 break;
1033 case WIN_VID0:
1034 case WIN_VID1:
1035 cfg->pixfmt = osd->yc_pixfmt;
1036 _osd_set_layer_config(sd, layer, cfg);
1037 break;
1038 }
1039
1040 spin_unlock_irqrestore(&osd->lock, flags);
1041}
1042
1043static void osd_release_layer(struct osd_state *sd, enum osd_layer layer)
1044{
1045 struct osd_state *osd = sd;
1046 struct osd_window_state *win = &osd->win[layer];
1047 unsigned long flags;
1048
1049 spin_lock_irqsave(&osd->lock, flags);
1050
1051 if (!win->is_allocated) {
1052 spin_unlock_irqrestore(&osd->lock, flags);
1053 return;
1054 }
1055
1056 spin_unlock_irqrestore(&osd->lock, flags);
1057 osd_init_layer(sd, layer);
1058 spin_lock_irqsave(&osd->lock, flags);
1059
1060 win->is_allocated = 0;
1061
1062 spin_unlock_irqrestore(&osd->lock, flags);
1063}
1064
1065static int osd_request_layer(struct osd_state *sd, enum osd_layer layer)
1066{
1067 struct osd_state *osd = sd;
1068 struct osd_window_state *win = &osd->win[layer];
1069 unsigned long flags;
1070
1071 spin_lock_irqsave(&osd->lock, flags);
1072
1073 if (win->is_allocated) {
1074 spin_unlock_irqrestore(&osd->lock, flags);
1075 return -1;
1076 }
1077 win->is_allocated = 1;
1078
1079 spin_unlock_irqrestore(&osd->lock, flags);
1080
1081 return 0;
1082}
1083
1084static void _osd_init(struct osd_state *sd)
1085{
1086 osd_write(sd, 0, OSD_MODE);
1087 osd_write(sd, 0, OSD_VIDWINMD);
1088 osd_write(sd, 0, OSD_OSDWIN0MD);
1089 osd_write(sd, 0, OSD_OSDWIN1MD);
1090 osd_write(sd, 0, OSD_RECTCUR);
1091 osd_write(sd, 0, OSD_MISCCTL);
1092}
1093
1094static void osd_set_left_margin(struct osd_state *sd, u32 val)
1095{
1096 osd_write(sd, val, OSD_BASEPX);
1097}
1098
1099static void osd_set_top_margin(struct osd_state *sd, u32 val)
1100{
1101 osd_write(sd, val, OSD_BASEPY);
1102}
1103
1104static int osd_initialize(struct osd_state *osd)
1105{
1106 if (osd == NULL)
1107 return -ENODEV;
1108 _osd_init(osd);
1109
1110 /* set default Cb/Cr order */
1111 osd->yc_pixfmt = PIXFMT_YCbCrI;
1112
1113 _osd_set_field_inversion(osd, osd->field_inversion);
1114 _osd_set_rom_clut(osd, osd->rom_clut);
1115
1116 osd_init_layer(osd, WIN_OSD0);
1117 osd_init_layer(osd, WIN_VID0);
1118 osd_init_layer(osd, WIN_OSD1);
1119 osd_init_layer(osd, WIN_VID1);
1120
1121 return 0;
1122}
1123
1124static const struct vpbe_osd_ops osd_ops = {
1125 .initialize = osd_initialize,
1126 .request_layer = osd_request_layer,
1127 .release_layer = osd_release_layer,
1128 .enable_layer = osd_enable_layer,
1129 .disable_layer = osd_disable_layer,
1130 .set_layer_config = osd_set_layer_config,
1131 .get_layer_config = osd_get_layer_config,
1132 .start_layer = osd_start_layer,
1133 .set_left_margin = osd_set_left_margin,
1134 .set_top_margin = osd_set_top_margin,
1135};
1136
1137static int osd_probe(struct platform_device *pdev)
1138{
1139 struct osd_platform_data *pdata;
1140 struct osd_state *osd;
1141 struct resource *res;
1142 int ret = 0;
1143
1144 osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL);
1145 if (osd == NULL)
1146 return -ENOMEM;
1147
1148 osd->dev = &pdev->dev;
1149 pdata = (struct osd_platform_data *)pdev->dev.platform_data;
1150 osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type;
1151 if (NULL == pdev->dev.platform_data) {
1152 dev_err(osd->dev, "No platform data defined for OSD"
1153 " sub device\n");
1154 ret = -ENOENT;
1155 goto free_mem;
1156 }
1157
1158 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1159 if (!res) {
1160 dev_err(osd->dev, "Unable to get OSD register address map\n");
1161 ret = -ENODEV;
1162 goto free_mem;
1163 }
1164 osd->osd_base_phys = res->start;
1165 osd->osd_size = res->end - res->start + 1;
1166 if (!request_mem_region(osd->osd_base_phys, osd->osd_size,
1167 MODULE_NAME)) {
1168 dev_err(osd->dev, "Unable to reserve OSD MMIO region\n");
1169 ret = -ENODEV;
1170 goto free_mem;
1171 }
1172 osd->osd_base = (unsigned long)ioremap_nocache(res->start,
1173 osd->osd_size);
1174 if (!osd->osd_base) {
1175 dev_err(osd->dev, "Unable to map the OSD region\n");
1176 ret = -ENODEV;
1177 goto release_mem_region;
1178 }
1179 spin_lock_init(&osd->lock);
1180 osd->ops = osd_ops;
1181 platform_set_drvdata(pdev, osd);
1182 dev_notice(osd->dev, "OSD sub device probe success\n");
1183 return ret;
1184
1185release_mem_region:
1186 release_mem_region(osd->osd_base_phys, osd->osd_size);
1187free_mem:
1188 kfree(osd);
1189 return ret;
1190}
1191
1192static int osd_remove(struct platform_device *pdev)
1193{
1194 struct osd_state *osd = platform_get_drvdata(pdev);
1195
1196 iounmap((void *)osd->osd_base);
1197 release_mem_region(osd->osd_base_phys, osd->osd_size);
1198 kfree(osd);
1199 return 0;
1200}
1201
1202static struct platform_driver osd_driver = {
1203 .probe = osd_probe,
1204 .remove = osd_remove,
1205 .driver = {
1206 .name = MODULE_NAME,
1207 .owner = THIS_MODULE,
1208 },
1209};
1210
1211static int osd_init(void)
1212{
1213 if (platform_driver_register(&osd_driver)) {
1214 printk(KERN_ERR "Unable to register davinci osd driver\n");
1215 return -ENODEV;
1216 }
1217
1218 return 0;
1219}
1220
1221static void osd_exit(void)
1222{
1223 platform_driver_unregister(&osd_driver);
1224}
1225
1226module_init(osd_init);
1227module_exit(osd_exit);
1228
1229MODULE_LICENSE("GPL");
1230MODULE_DESCRIPTION("DaVinci OSD Manager Driver");
1231MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/media/video/davinci/vpbe_osd_regs.h b/drivers/media/video/davinci/vpbe_osd_regs.h
new file mode 100644
index 00000000000..584520f3af6
--- /dev/null
+++ b/drivers/media/video/davinci/vpbe_osd_regs.h
@@ -0,0 +1,364 @@
1/*
2 * Copyright (C) 2006-2010 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17#ifndef _VPBE_OSD_REGS_H
18#define _VPBE_OSD_REGS_H
19
20/* VPBE Global Registers */
21#define VPBE_PID 0x0
22#define VPBE_PCR 0x4
23
24/* VPSS CLock Registers */
25#define VPSSCLK_PID 0x00
26#define VPSSCLK_CLKCTRL 0x04
27
28/* VPSS Buffer Logic Registers */
29#define VPSSBL_PID 0x00
30#define VPSSBL_PCR 0x04
31#define VPSSBL_BCR 0x08
32#define VPSSBL_INTSTAT 0x0C
33#define VPSSBL_INTSEL 0x10
34#define VPSSBL_EVTSEL 0x14
35#define VPSSBL_MEMCTRL 0x18
36#define VPSSBL_CCDCMUX 0x1C
37
38/* DM365 ISP5 system configuration */
39#define ISP5_PID 0x0
40#define ISP5_PCCR 0x4
41#define ISP5_BCR 0x8
42#define ISP5_INTSTAT 0xC
43#define ISP5_INTSEL1 0x10
44#define ISP5_INTSEL2 0x14
45#define ISP5_INTSEL3 0x18
46#define ISP5_EVTSEL 0x1c
47#define ISP5_CCDCMUX 0x20
48
49/* VPBE On-Screen Display Subsystem Registers (OSD) */
50#define OSD_MODE 0x00
51#define OSD_VIDWINMD 0x04
52#define OSD_OSDWIN0MD 0x08
53#define OSD_OSDWIN1MD 0x0C
54#define OSD_OSDATRMD 0x0C
55#define OSD_RECTCUR 0x10
56#define OSD_VIDWIN0OFST 0x18
57#define OSD_VIDWIN1OFST 0x1C
58#define OSD_OSDWIN0OFST 0x20
59#define OSD_OSDWIN1OFST 0x24
60#define OSD_VIDWINADH 0x28
61#define OSD_VIDWIN0ADL 0x2C
62#define OSD_VIDWIN0ADR 0x2C
63#define OSD_VIDWIN1ADL 0x30
64#define OSD_VIDWIN1ADR 0x30
65#define OSD_OSDWINADH 0x34
66#define OSD_OSDWIN0ADL 0x38
67#define OSD_OSDWIN0ADR 0x38
68#define OSD_OSDWIN1ADL 0x3C
69#define OSD_OSDWIN1ADR 0x3C
70#define OSD_BASEPX 0x40
71#define OSD_BASEPY 0x44
72#define OSD_VIDWIN0XP 0x48
73#define OSD_VIDWIN0YP 0x4C
74#define OSD_VIDWIN0XL 0x50
75#define OSD_VIDWIN0YL 0x54
76#define OSD_VIDWIN1XP 0x58
77#define OSD_VIDWIN1YP 0x5C
78#define OSD_VIDWIN1XL 0x60
79#define OSD_VIDWIN1YL 0x64
80#define OSD_OSDWIN0XP 0x68
81#define OSD_OSDWIN0YP 0x6C
82#define OSD_OSDWIN0XL 0x70
83#define OSD_OSDWIN0YL 0x74
84#define OSD_OSDWIN1XP 0x78
85#define OSD_OSDWIN1YP 0x7C
86#define OSD_OSDWIN1XL 0x80
87#define OSD_OSDWIN1YL 0x84
88#define OSD_CURXP 0x88
89#define OSD_CURYP 0x8C
90#define OSD_CURXL 0x90
91#define OSD_CURYL 0x94
92#define OSD_W0BMP01 0xA0
93#define OSD_W0BMP23 0xA4
94#define OSD_W0BMP45 0xA8
95#define OSD_W0BMP67 0xAC
96#define OSD_W0BMP89 0xB0
97#define OSD_W0BMPAB 0xB4
98#define OSD_W0BMPCD 0xB8
99#define OSD_W0BMPEF 0xBC
100#define OSD_W1BMP01 0xC0
101#define OSD_W1BMP23 0xC4
102#define OSD_W1BMP45 0xC8
103#define OSD_W1BMP67 0xCC
104#define OSD_W1BMP89 0xD0
105#define OSD_W1BMPAB 0xD4
106#define OSD_W1BMPCD 0xD8
107#define OSD_W1BMPEF 0xDC
108#define OSD_VBNDRY 0xE0
109#define OSD_EXTMODE 0xE4
110#define OSD_MISCCTL 0xE8
111#define OSD_CLUTRAMYCB 0xEC
112#define OSD_CLUTRAMCR 0xF0
113#define OSD_TRANSPVAL 0xF4
114#define OSD_TRANSPVALL 0xF4
115#define OSD_TRANSPVALU 0xF8
116#define OSD_TRANSPBMPIDX 0xFC
117#define OSD_PPVWIN0ADR 0xFC
118
119/* bit definitions */
120#define VPBE_PCR_VENC_DIV (1 << 1)
121#define VPBE_PCR_CLK_OFF (1 << 0)
122
123#define VPSSBL_INTSTAT_HSSIINT (1 << 14)
124#define VPSSBL_INTSTAT_CFALDINT (1 << 13)
125#define VPSSBL_INTSTAT_IPIPE_INT5 (1 << 12)
126#define VPSSBL_INTSTAT_IPIPE_INT4 (1 << 11)
127#define VPSSBL_INTSTAT_IPIPE_INT3 (1 << 10)
128#define VPSSBL_INTSTAT_IPIPE_INT2 (1 << 9)
129#define VPSSBL_INTSTAT_IPIPE_INT1 (1 << 8)
130#define VPSSBL_INTSTAT_IPIPE_INT0 (1 << 7)
131#define VPSSBL_INTSTAT_IPIPEIFINT (1 << 6)
132#define VPSSBL_INTSTAT_OSDINT (1 << 5)
133#define VPSSBL_INTSTAT_VENCINT (1 << 4)
134#define VPSSBL_INTSTAT_H3AINT (1 << 3)
135#define VPSSBL_INTSTAT_CCDC_VDINT2 (1 << 2)
136#define VPSSBL_INTSTAT_CCDC_VDINT1 (1 << 1)
137#define VPSSBL_INTSTAT_CCDC_VDINT0 (1 << 0)
138
139/* DM365 ISP5 bit definitions */
140#define ISP5_INTSTAT_VENCINT (1 << 21)
141#define ISP5_INTSTAT_OSDINT (1 << 20)
142
143/* VMOD TVTYP options for HDMD=0 */
144#define SDTV_NTSC 0
145#define SDTV_PAL 1
146/* VMOD TVTYP options for HDMD=1 */
147#define HDTV_525P 0
148#define HDTV_625P 1
149#define HDTV_1080I 2
150#define HDTV_720P 3
151
152#define OSD_MODE_CS (1 << 15)
153#define OSD_MODE_OVRSZ (1 << 14)
154#define OSD_MODE_OHRSZ (1 << 13)
155#define OSD_MODE_EF (1 << 12)
156#define OSD_MODE_VVRSZ (1 << 11)
157#define OSD_MODE_VHRSZ (1 << 10)
158#define OSD_MODE_FSINV (1 << 9)
159#define OSD_MODE_BCLUT (1 << 8)
160#define OSD_MODE_CABG_SHIFT 0
161#define OSD_MODE_CABG (0xff << 0)
162
163#define OSD_VIDWINMD_VFINV (1 << 15)
164#define OSD_VIDWINMD_V1EFC (1 << 14)
165#define OSD_VIDWINMD_VHZ1_SHIFT 12
166#define OSD_VIDWINMD_VHZ1 (3 << 12)
167#define OSD_VIDWINMD_VVZ1_SHIFT 10
168#define OSD_VIDWINMD_VVZ1 (3 << 10)
169#define OSD_VIDWINMD_VFF1 (1 << 9)
170#define OSD_VIDWINMD_ACT1 (1 << 8)
171#define OSD_VIDWINMD_V0EFC (1 << 6)
172#define OSD_VIDWINMD_VHZ0_SHIFT 4
173#define OSD_VIDWINMD_VHZ0 (3 << 4)
174#define OSD_VIDWINMD_VVZ0_SHIFT 2
175#define OSD_VIDWINMD_VVZ0 (3 << 2)
176#define OSD_VIDWINMD_VFF0 (1 << 1)
177#define OSD_VIDWINMD_ACT0 (1 << 0)
178
179#define OSD_OSDWIN0MD_ATN0E (1 << 14)
180#define OSD_OSDWIN0MD_RGB0E (1 << 13)
181#define OSD_OSDWIN0MD_BMP0MD_SHIFT 13
182#define OSD_OSDWIN0MD_BMP0MD (3 << 13)
183#define OSD_OSDWIN0MD_CLUTS0 (1 << 12)
184#define OSD_OSDWIN0MD_OHZ0_SHIFT 10
185#define OSD_OSDWIN0MD_OHZ0 (3 << 10)
186#define OSD_OSDWIN0MD_OVZ0_SHIFT 8
187#define OSD_OSDWIN0MD_OVZ0 (3 << 8)
188#define OSD_OSDWIN0MD_BMW0_SHIFT 6
189#define OSD_OSDWIN0MD_BMW0 (3 << 6)
190#define OSD_OSDWIN0MD_BLND0_SHIFT 3
191#define OSD_OSDWIN0MD_BLND0 (7 << 3)
192#define OSD_OSDWIN0MD_TE0 (1 << 2)
193#define OSD_OSDWIN0MD_OFF0 (1 << 1)
194#define OSD_OSDWIN0MD_OACT0 (1 << 0)
195
196#define OSD_OSDWIN1MD_OASW (1 << 15)
197#define OSD_OSDWIN1MD_ATN1E (1 << 14)
198#define OSD_OSDWIN1MD_RGB1E (1 << 13)
199#define OSD_OSDWIN1MD_BMP1MD_SHIFT 13
200#define OSD_OSDWIN1MD_BMP1MD (3 << 13)
201#define OSD_OSDWIN1MD_CLUTS1 (1 << 12)
202#define OSD_OSDWIN1MD_OHZ1_SHIFT 10
203#define OSD_OSDWIN1MD_OHZ1 (3 << 10)
204#define OSD_OSDWIN1MD_OVZ1_SHIFT 8
205#define OSD_OSDWIN1MD_OVZ1 (3 << 8)
206#define OSD_OSDWIN1MD_BMW1_SHIFT 6
207#define OSD_OSDWIN1MD_BMW1 (3 << 6)
208#define OSD_OSDWIN1MD_BLND1_SHIFT 3
209#define OSD_OSDWIN1MD_BLND1 (7 << 3)
210#define OSD_OSDWIN1MD_TE1 (1 << 2)
211#define OSD_OSDWIN1MD_OFF1 (1 << 1)
212#define OSD_OSDWIN1MD_OACT1 (1 << 0)
213
214#define OSD_OSDATRMD_OASW (1 << 15)
215#define OSD_OSDATRMD_OHZA_SHIFT 10
216#define OSD_OSDATRMD_OHZA (3 << 10)
217#define OSD_OSDATRMD_OVZA_SHIFT 8
218#define OSD_OSDATRMD_OVZA (3 << 8)
219#define OSD_OSDATRMD_BLNKINT_SHIFT 6
220#define OSD_OSDATRMD_BLNKINT (3 << 6)
221#define OSD_OSDATRMD_OFFA (1 << 1)
222#define OSD_OSDATRMD_BLNK (1 << 0)
223
224#define OSD_RECTCUR_RCAD_SHIFT 8
225#define OSD_RECTCUR_RCAD (0xff << 8)
226#define OSD_RECTCUR_CLUTSR (1 << 7)
227#define OSD_RECTCUR_RCHW_SHIFT 4
228#define OSD_RECTCUR_RCHW (7 << 4)
229#define OSD_RECTCUR_RCVW_SHIFT 1
230#define OSD_RECTCUR_RCVW (7 << 1)
231#define OSD_RECTCUR_RCACT (1 << 0)
232
233#define OSD_VIDWIN0OFST_V0LO (0x1ff << 0)
234
235#define OSD_VIDWIN1OFST_V1LO (0x1ff << 0)
236
237#define OSD_OSDWIN0OFST_O0LO (0x1ff << 0)
238
239#define OSD_OSDWIN1OFST_O1LO (0x1ff << 0)
240
241#define OSD_WINOFST_AH_SHIFT 9
242
243#define OSD_VIDWIN0OFST_V0AH (0xf << 9)
244#define OSD_VIDWIN1OFST_V1AH (0xf << 9)
245#define OSD_OSDWIN0OFST_O0AH (0xf << 9)
246#define OSD_OSDWIN1OFST_O1AH (0xf << 9)
247
248#define OSD_VIDWINADH_V1AH_SHIFT 8
249#define OSD_VIDWINADH_V1AH (0x7f << 8)
250#define OSD_VIDWINADH_V0AH_SHIFT 0
251#define OSD_VIDWINADH_V0AH (0x7f << 0)
252
253#define OSD_VIDWIN0ADL_V0AL (0xffff << 0)
254
255#define OSD_VIDWIN1ADL_V1AL (0xffff << 0)
256
257#define OSD_OSDWINADH_O1AH_SHIFT 8
258#define OSD_OSDWINADH_O1AH (0x7f << 8)
259#define OSD_OSDWINADH_O0AH_SHIFT 0
260#define OSD_OSDWINADH_O0AH (0x7f << 0)
261
262#define OSD_OSDWIN0ADL_O0AL (0xffff << 0)
263
264#define OSD_OSDWIN1ADL_O1AL (0xffff << 0)
265
266#define OSD_BASEPX_BPX (0x3ff << 0)
267
268#define OSD_BASEPY_BPY (0x1ff << 0)
269
270#define OSD_VIDWIN0XP_V0X (0x7ff << 0)
271
272#define OSD_VIDWIN0YP_V0Y (0x7ff << 0)
273
274#define OSD_VIDWIN0XL_V0W (0x7ff << 0)
275
276#define OSD_VIDWIN0YL_V0H (0x7ff << 0)
277
278#define OSD_VIDWIN1XP_V1X (0x7ff << 0)
279
280#define OSD_VIDWIN1YP_V1Y (0x7ff << 0)
281
282#define OSD_VIDWIN1XL_V1W (0x7ff << 0)
283
284#define OSD_VIDWIN1YL_V1H (0x7ff << 0)
285
286#define OSD_OSDWIN0XP_W0X (0x7ff << 0)
287
288#define OSD_OSDWIN0YP_W0Y (0x7ff << 0)
289
290#define OSD_OSDWIN0XL_W0W (0x7ff << 0)
291
292#define OSD_OSDWIN0YL_W0H (0x7ff << 0)
293
294#define OSD_OSDWIN1XP_W1X (0x7ff << 0)
295
296#define OSD_OSDWIN1YP_W1Y (0x7ff << 0)
297
298#define OSD_OSDWIN1XL_W1W (0x7ff << 0)
299
300#define OSD_OSDWIN1YL_W1H (0x7ff << 0)
301
302#define OSD_CURXP_RCSX (0x7ff << 0)
303
304#define OSD_CURYP_RCSY (0x7ff << 0)
305
306#define OSD_CURXL_RCSW (0x7ff << 0)
307
308#define OSD_CURYL_RCSH (0x7ff << 0)
309
310#define OSD_EXTMODE_EXPMDSEL (1 << 15)
311#define OSD_EXTMODE_SCRNHEXP_SHIFT 13
312#define OSD_EXTMODE_SCRNHEXP (3 << 13)
313#define OSD_EXTMODE_SCRNVEXP (1 << 12)
314#define OSD_EXTMODE_OSD1BLDCHR (1 << 11)
315#define OSD_EXTMODE_OSD0BLDCHR (1 << 10)
316#define OSD_EXTMODE_ATNOSD1EN (1 << 9)
317#define OSD_EXTMODE_ATNOSD0EN (1 << 8)
318#define OSD_EXTMODE_OSDHRSZ15 (1 << 7)
319#define OSD_EXTMODE_VIDHRSZ15 (1 << 6)
320#define OSD_EXTMODE_ZMFILV1HEN (1 << 5)
321#define OSD_EXTMODE_ZMFILV1VEN (1 << 4)
322#define OSD_EXTMODE_ZMFILV0HEN (1 << 3)
323#define OSD_EXTMODE_ZMFILV0VEN (1 << 2)
324#define OSD_EXTMODE_EXPFILHEN (1 << 1)
325#define OSD_EXTMODE_EXPFILVEN (1 << 0)
326
327#define OSD_MISCCTL_BLDSEL (1 << 15)
328#define OSD_MISCCTL_S420D (1 << 14)
329#define OSD_MISCCTL_BMAPT (1 << 13)
330#define OSD_MISCCTL_DM365M (1 << 12)
331#define OSD_MISCCTL_RGBEN (1 << 7)
332#define OSD_MISCCTL_RGBWIN (1 << 6)
333#define OSD_MISCCTL_DMANG (1 << 6)
334#define OSD_MISCCTL_TMON (1 << 5)
335#define OSD_MISCCTL_RSEL (1 << 4)
336#define OSD_MISCCTL_CPBSY (1 << 3)
337#define OSD_MISCCTL_PPSW (1 << 2)
338#define OSD_MISCCTL_PPRV (1 << 1)
339
340#define OSD_CLUTRAMYCB_Y_SHIFT 8
341#define OSD_CLUTRAMYCB_Y (0xff << 8)
342#define OSD_CLUTRAMYCB_CB_SHIFT 0
343#define OSD_CLUTRAMYCB_CB (0xff << 0)
344
345#define OSD_CLUTRAMCR_CR_SHIFT 8
346#define OSD_CLUTRAMCR_CR (0xff << 8)
347#define OSD_CLUTRAMCR_CADDR_SHIFT 0
348#define OSD_CLUTRAMCR_CADDR (0xff << 0)
349
350#define OSD_TRANSPVAL_RGBTRANS (0xffff << 0)
351
352#define OSD_TRANSPVALL_RGBL (0xffff << 0)
353
354#define OSD_TRANSPVALU_Y_SHIFT 8
355#define OSD_TRANSPVALU_Y (0xff << 8)
356#define OSD_TRANSPVALU_RGBU_SHIFT 0
357#define OSD_TRANSPVALU_RGBU (0xff << 0)
358
359#define OSD_TRANSPBMPIDX_BMP1_SHIFT 8
360#define OSD_TRANSPBMPIDX_BMP1 (0xff << 8)
361#define OSD_TRANSPBMPIDX_BMP0_SHIFT 0
362#define OSD_TRANSPBMPIDX_BMP0 0xff
363
364#endif /* _DAVINCI_VPBE_H_ */
diff --git a/drivers/media/video/davinci/vpbe_venc.c b/drivers/media/video/davinci/vpbe_venc.c
new file mode 100644
index 00000000000..03a3e5c65ee
--- /dev/null
+++ b/drivers/media/video/davinci/vpbe_venc.c
@@ -0,0 +1,566 @@
1/*
2 * Copyright (C) 2010 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/ctype.h>
21#include <linux/delay.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
24#include <linux/platform_device.h>
25#include <linux/videodev2.h>
26#include <linux/slab.h>
27
28#include <mach/hardware.h>
29#include <mach/mux.h>
30#include <mach/io.h>
31#include <mach/i2c.h>
32
33#include <linux/io.h>
34
35#include <media/davinci/vpbe_types.h>
36#include <media/davinci/vpbe_venc.h>
37#include <media/davinci/vpss.h>
38#include <media/v4l2-device.h>
39
40#include "vpbe_venc_regs.h"
41
42#define MODULE_NAME VPBE_VENC_SUBDEV_NAME
43
44static int debug = 2;
45module_param(debug, int, 0644);
46MODULE_PARM_DESC(debug, "Debug level 0-2");
47
48struct venc_state {
49 struct v4l2_subdev sd;
50 struct venc_callback *callback;
51 struct venc_platform_data *pdata;
52 struct device *pdev;
53 u32 output;
54 v4l2_std_id std;
55 spinlock_t lock;
56 void __iomem *venc_base;
57 void __iomem *vdaccfg_reg;
58};
59
60static inline struct venc_state *to_state(struct v4l2_subdev *sd)
61{
62 return container_of(sd, struct venc_state, sd);
63}
64
65static inline u32 venc_read(struct v4l2_subdev *sd, u32 offset)
66{
67 struct venc_state *venc = to_state(sd);
68
69 return readl(venc->venc_base + offset);
70}
71
72static inline u32 venc_write(struct v4l2_subdev *sd, u32 offset, u32 val)
73{
74 struct venc_state *venc = to_state(sd);
75
76 writel(val, (venc->venc_base + offset));
77
78 return val;
79}
80
81static inline u32 venc_modify(struct v4l2_subdev *sd, u32 offset,
82 u32 val, u32 mask)
83{
84 u32 new_val = (venc_read(sd, offset) & ~mask) | (val & mask);
85
86 venc_write(sd, offset, new_val);
87
88 return new_val;
89}
90
91static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
92{
93 struct venc_state *venc = to_state(sd);
94
95 writel(val, venc->vdaccfg_reg);
96
97 val = readl(venc->vdaccfg_reg);
98
99 return val;
100}
101
102/* This function sets the dac of the VPBE for various outputs
103 */
104static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
105{
106 switch (out_index) {
107 case 0:
108 v4l2_dbg(debug, 1, sd, "Setting output to Composite\n");
109 venc_write(sd, VENC_DACSEL, 0);
110 break;
111 case 1:
112 v4l2_dbg(debug, 1, sd, "Setting output to S-Video\n");
113 venc_write(sd, VENC_DACSEL, 0x210);
114 break;
115 case 2:
116 venc_write(sd, VENC_DACSEL, 0x543);
117 break;
118 default:
119 return -EINVAL;
120 }
121
122 return 0;
123}
124
125static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
126{
127 v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
128
129 if (benable) {
130 venc_write(sd, VENC_VMOD, 0);
131 venc_write(sd, VENC_CVBS, 0);
132 venc_write(sd, VENC_LCDOUT, 0);
133 venc_write(sd, VENC_HSPLS, 0);
134 venc_write(sd, VENC_HSTART, 0);
135 venc_write(sd, VENC_HVALID, 0);
136 venc_write(sd, VENC_HINT, 0);
137 venc_write(sd, VENC_VSPLS, 0);
138 venc_write(sd, VENC_VSTART, 0);
139 venc_write(sd, VENC_VVALID, 0);
140 venc_write(sd, VENC_VINT, 0);
141 venc_write(sd, VENC_YCCCTL, 0);
142 venc_write(sd, VENC_DACSEL, 0);
143
144 } else {
145 venc_write(sd, VENC_VMOD, 0);
146 /* disable VCLK output pin enable */
147 venc_write(sd, VENC_VIDCTL, 0x141);
148
149 /* Disable output sync pins */
150 venc_write(sd, VENC_SYNCCTL, 0);
151
152 /* Disable DCLOCK */
153 venc_write(sd, VENC_DCLKCTL, 0);
154 venc_write(sd, VENC_DRGBX1, 0x0000057C);
155
156 /* Disable LCD output control (accepting default polarity) */
157 venc_write(sd, VENC_LCDOUT, 0);
158 venc_write(sd, VENC_CMPNT, 0x100);
159 venc_write(sd, VENC_HSPLS, 0);
160 venc_write(sd, VENC_HINT, 0);
161 venc_write(sd, VENC_HSTART, 0);
162 venc_write(sd, VENC_HVALID, 0);
163
164 venc_write(sd, VENC_VSPLS, 0);
165 venc_write(sd, VENC_VINT, 0);
166 venc_write(sd, VENC_VSTART, 0);
167 venc_write(sd, VENC_VVALID, 0);
168
169 venc_write(sd, VENC_HSDLY, 0);
170 venc_write(sd, VENC_VSDLY, 0);
171
172 venc_write(sd, VENC_YCCCTL, 0);
173 venc_write(sd, VENC_VSTARTA, 0);
174
175 /* Set OSD clock and OSD Sync Adavance registers */
176 venc_write(sd, VENC_OSDCLK0, 1);
177 venc_write(sd, VENC_OSDCLK1, 2);
178 }
179}
180
181/*
182 * setting NTSC mode
183 */
184static int venc_set_ntsc(struct v4l2_subdev *sd)
185{
186 struct venc_state *venc = to_state(sd);
187 struct venc_platform_data *pdata = venc->pdata;
188
189 v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
190
191 /* Setup clock at VPSS & VENC for SD */
192 vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
193 if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
194 return -EINVAL;
195
196 venc_enabledigitaloutput(sd, 0);
197
198 /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
199 venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
200 /* Set REC656 Mode */
201 venc_write(sd, VENC_YCCCTL, 0x1);
202 venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
203 venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
204
205 venc_write(sd, VENC_VMOD, 0);
206 venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
207 VENC_VMOD_VIE);
208 venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
209 venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
210 VENC_VMOD_TVTYP);
211 venc_write(sd, VENC_DACTST, 0x0);
212 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
213
214 return 0;
215}
216
217/*
218 * setting PAL mode
219 */
220static int venc_set_pal(struct v4l2_subdev *sd)
221{
222 struct venc_state *venc = to_state(sd);
223
224 v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
225
226 /* Setup clock at VPSS & VENC for SD */
227 vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
228 if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
229 return -EINVAL;
230
231 venc_enabledigitaloutput(sd, 0);
232
233 /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
234 venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
235 /* Set REC656 Mode */
236 venc_write(sd, VENC_YCCCTL, 0x1);
237
238 venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
239 VENC_SYNCCTL_OVD);
240 venc_write(sd, VENC_VMOD, 0);
241 venc_modify(sd, VENC_VMOD,
242 (1 << VENC_VMOD_VIE_SHIFT),
243 VENC_VMOD_VIE);
244 venc_modify(sd, VENC_VMOD,
245 (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
246 venc_modify(sd, VENC_VMOD,
247 (1 << VENC_VMOD_TVTYP_SHIFT),
248 VENC_VMOD_TVTYP);
249 venc_write(sd, VENC_DACTST, 0x0);
250 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
251
252 return 0;
253}
254
255/*
256 * venc_set_480p59_94
257 *
258 * This function configures the video encoder to EDTV(525p) component setting.
259 */
260static int venc_set_480p59_94(struct v4l2_subdev *sd)
261{
262 struct venc_state *venc = to_state(sd);
263 struct venc_platform_data *pdata = venc->pdata;
264
265 v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
266
267 /* Setup clock at VPSS & VENC for SD */
268 if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
269 return -EINVAL;
270
271 venc_enabledigitaloutput(sd, 0);
272
273 venc_write(sd, VENC_OSDCLK0, 0);
274 venc_write(sd, VENC_OSDCLK1, 1);
275 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
276 VENC_VDPRO_DAFRQ);
277 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
278 VENC_VDPRO_DAUPS);
279 venc_write(sd, VENC_VMOD, 0);
280 venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
281 VENC_VMOD_VIE);
282 venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
283 venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
284 VENC_VMOD_TVTYP);
285 venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
286 VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
287
288 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
289
290 return 0;
291}
292
293/*
294 * venc_set_625p
295 *
296 * This function configures the video encoder to HDTV(625p) component setting
297 */
298static int venc_set_576p50(struct v4l2_subdev *sd)
299{
300 struct venc_state *venc = to_state(sd);
301 struct venc_platform_data *pdata = venc->pdata;
302
303 v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
304
305 /* Setup clock at VPSS & VENC for SD */
306 if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
307 return -EINVAL;
308
309 venc_enabledigitaloutput(sd, 0);
310
311 venc_write(sd, VENC_OSDCLK0, 0);
312 venc_write(sd, VENC_OSDCLK1, 1);
313
314 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
315 VENC_VDPRO_DAFRQ);
316 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
317 VENC_VDPRO_DAUPS);
318
319 venc_write(sd, VENC_VMOD, 0);
320 venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
321 VENC_VMOD_VIE);
322 venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
323 venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
324 VENC_VMOD_TVTYP);
325
326 venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
327 VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
328 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
329
330 return 0;
331}
332
333static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
334{
335 v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
336
337 if (norm & V4L2_STD_525_60)
338 return venc_set_ntsc(sd);
339 else if (norm & V4L2_STD_625_50)
340 return venc_set_pal(sd);
341
342 return -EINVAL;
343}
344
345static int venc_s_dv_preset(struct v4l2_subdev *sd,
346 struct v4l2_dv_preset *dv_preset)
347{
348 v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
349
350 if (dv_preset->preset == V4L2_DV_576P50)
351 return venc_set_576p50(sd);
352 else if (dv_preset->preset == V4L2_DV_480P59_94)
353 return venc_set_480p59_94(sd);
354
355 return -EINVAL;
356}
357
358static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
359 u32 config)
360{
361 struct venc_state *venc = to_state(sd);
362 int ret;
363
364 v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
365
366 ret = venc_set_dac(sd, output);
367 if (!ret)
368 venc->output = output;
369
370 return ret;
371}
372
373static long venc_ioctl(struct v4l2_subdev *sd,
374 unsigned int cmd,
375 void *arg)
376{
377 u32 val;
378
379 switch (cmd) {
380 case VENC_GET_FLD:
381 val = venc_read(sd, VENC_VSTAT);
382 *((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
383 VENC_VSTAT_FIDST);
384 break;
385 default:
386 v4l2_err(sd, "Wrong IOCTL cmd\n");
387 break;
388 }
389
390 return 0;
391}
392
393static const struct v4l2_subdev_core_ops venc_core_ops = {
394 .ioctl = venc_ioctl,
395};
396
397static const struct v4l2_subdev_video_ops venc_video_ops = {
398 .s_routing = venc_s_routing,
399 .s_std_output = venc_s_std_output,
400 .s_dv_preset = venc_s_dv_preset,
401};
402
403static const struct v4l2_subdev_ops venc_ops = {
404 .core = &venc_core_ops,
405 .video = &venc_video_ops,
406};
407
408static int venc_initialize(struct v4l2_subdev *sd)
409{
410 struct venc_state *venc = to_state(sd);
411 int ret;
412
413 /* Set default to output to composite and std to NTSC */
414 venc->output = 0;
415 venc->std = V4L2_STD_525_60;
416
417 ret = venc_s_routing(sd, 0, venc->output, 0);
418 if (ret < 0) {
419 v4l2_err(sd, "Error setting output during init\n");
420 return -EINVAL;
421 }
422
423 ret = venc_s_std_output(sd, venc->std);
424 if (ret < 0) {
425 v4l2_err(sd, "Error setting std during init\n");
426 return -EINVAL;
427 }
428
429 return ret;
430}
431
432static int venc_device_get(struct device *dev, void *data)
433{
434 struct platform_device *pdev = to_platform_device(dev);
435 struct venc_state **venc = data;
436
437 if (strcmp(MODULE_NAME, pdev->name) == 0)
438 *venc = platform_get_drvdata(pdev);
439
440 return 0;
441}
442
443struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
444 const char *venc_name)
445{
446 struct venc_state *venc;
447 int err;
448
449 err = bus_for_each_dev(&platform_bus_type, NULL, &venc,
450 venc_device_get);
451 if (venc == NULL)
452 return NULL;
453
454 v4l2_subdev_init(&venc->sd, &venc_ops);
455
456 strcpy(venc->sd.name, venc_name);
457 if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
458 v4l2_err(v4l2_dev,
459 "vpbe unable to register venc sub device\n");
460 return NULL;
461 }
462 if (venc_initialize(&venc->sd)) {
463 v4l2_err(v4l2_dev,
464 "vpbe venc initialization failed\n");
465 return NULL;
466 }
467
468 return &venc->sd;
469}
470EXPORT_SYMBOL(venc_sub_dev_init);
471
472static int venc_probe(struct platform_device *pdev)
473{
474 struct venc_state *venc;
475 struct resource *res;
476 int ret;
477
478 venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL);
479 if (venc == NULL)
480 return -ENOMEM;
481
482 venc->pdev = &pdev->dev;
483 venc->pdata = pdev->dev.platform_data;
484 if (NULL == venc->pdata) {
485 dev_err(venc->pdev, "Unable to get platform data for"
486 " VENC sub device");
487 ret = -ENOENT;
488 goto free_mem;
489 }
490 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
491 if (!res) {
492 dev_err(venc->pdev,
493 "Unable to get VENC register address map\n");
494 ret = -ENODEV;
495 goto free_mem;
496 }
497
498 if (!request_mem_region(res->start, resource_size(res), "venc")) {
499 dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n");
500 ret = -ENODEV;
501 goto free_mem;
502 }
503
504 venc->venc_base = ioremap_nocache(res->start, resource_size(res));
505 if (!venc->venc_base) {
506 dev_err(venc->pdev, "Unable to map VENC IO space\n");
507 ret = -ENODEV;
508 goto release_venc_mem_region;
509 }
510
511 spin_lock_init(&venc->lock);
512 platform_set_drvdata(pdev, venc);
513 dev_notice(venc->pdev, "VENC sub device probe success\n");
514 return 0;
515
516release_venc_mem_region:
517 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
518 release_mem_region(res->start, resource_size(res));
519free_mem:
520 kfree(venc);
521 return ret;
522}
523
524static int venc_remove(struct platform_device *pdev)
525{
526 struct venc_state *venc = platform_get_drvdata(pdev);
527 struct resource *res;
528
529 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
530 iounmap((void *)venc->venc_base);
531 release_mem_region(res->start, resource_size(res));
532 kfree(venc);
533
534 return 0;
535}
536
537static struct platform_driver venc_driver = {
538 .probe = venc_probe,
539 .remove = venc_remove,
540 .driver = {
541 .name = MODULE_NAME,
542 .owner = THIS_MODULE,
543 },
544};
545
546static int venc_init(void)
547{
548 if (platform_driver_register(&venc_driver)) {
549 printk(KERN_ERR "Unable to register venc driver\n");
550 return -ENODEV;
551 }
552 return 0;
553}
554
555static void venc_exit(void)
556{
557 platform_driver_unregister(&venc_driver);
558 return;
559}
560
561module_init(venc_init);
562module_exit(venc_exit);
563
564MODULE_LICENSE("GPL");
565MODULE_DESCRIPTION("VPBE VENC Driver");
566MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/media/video/davinci/vpbe_venc_regs.h b/drivers/media/video/davinci/vpbe_venc_regs.h
new file mode 100644
index 00000000000..947cb151077
--- /dev/null
+++ b/drivers/media/video/davinci/vpbe_venc_regs.h
@@ -0,0 +1,177 @@
1/*
2 * Copyright (C) 2006-2010 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation version 2..
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17#ifndef _VPBE_VENC_REGS_H
18#define _VPBE_VENC_REGS_H
19
20/* VPBE Video Encoder / Digital LCD Subsystem Registers (VENC) */
21#define VENC_VMOD 0x00
22#define VENC_VIDCTL 0x04
23#define VENC_VDPRO 0x08
24#define VENC_SYNCCTL 0x0C
25#define VENC_HSPLS 0x10
26#define VENC_VSPLS 0x14
27#define VENC_HINT 0x18
28#define VENC_HSTART 0x1C
29#define VENC_HVALID 0x20
30#define VENC_VINT 0x24
31#define VENC_VSTART 0x28
32#define VENC_VVALID 0x2C
33#define VENC_HSDLY 0x30
34#define VENC_VSDLY 0x34
35#define VENC_YCCCTL 0x38
36#define VENC_RGBCTL 0x3C
37#define VENC_RGBCLP 0x40
38#define VENC_LINECTL 0x44
39#define VENC_CULLLINE 0x48
40#define VENC_LCDOUT 0x4C
41#define VENC_BRTS 0x50
42#define VENC_BRTW 0x54
43#define VENC_ACCTL 0x58
44#define VENC_PWMP 0x5C
45#define VENC_PWMW 0x60
46#define VENC_DCLKCTL 0x64
47#define VENC_DCLKPTN0 0x68
48#define VENC_DCLKPTN1 0x6C
49#define VENC_DCLKPTN2 0x70
50#define VENC_DCLKPTN3 0x74
51#define VENC_DCLKPTN0A 0x78
52#define VENC_DCLKPTN1A 0x7C
53#define VENC_DCLKPTN2A 0x80
54#define VENC_DCLKPTN3A 0x84
55#define VENC_DCLKHS 0x88
56#define VENC_DCLKHSA 0x8C
57#define VENC_DCLKHR 0x90
58#define VENC_DCLKVS 0x94
59#define VENC_DCLKVR 0x98
60#define VENC_CAPCTL 0x9C
61#define VENC_CAPDO 0xA0
62#define VENC_CAPDE 0xA4
63#define VENC_ATR0 0xA8
64#define VENC_ATR1 0xAC
65#define VENC_ATR2 0xB0
66#define VENC_VSTAT 0xB8
67#define VENC_RAMADR 0xBC
68#define VENC_RAMPORT 0xC0
69#define VENC_DACTST 0xC4
70#define VENC_YCOLVL 0xC8
71#define VENC_SCPROG 0xCC
72#define VENC_CVBS 0xDC
73#define VENC_CMPNT 0xE0
74#define VENC_ETMG0 0xE4
75#define VENC_ETMG1 0xE8
76#define VENC_ETMG2 0xEC
77#define VENC_ETMG3 0xF0
78#define VENC_DACSEL 0xF4
79#define VENC_ARGBX0 0x100
80#define VENC_ARGBX1 0x104
81#define VENC_ARGBX2 0x108
82#define VENC_ARGBX3 0x10C
83#define VENC_ARGBX4 0x110
84#define VENC_DRGBX0 0x114
85#define VENC_DRGBX1 0x118
86#define VENC_DRGBX2 0x11C
87#define VENC_DRGBX3 0x120
88#define VENC_DRGBX4 0x124
89#define VENC_VSTARTA 0x128
90#define VENC_OSDCLK0 0x12C
91#define VENC_OSDCLK1 0x130
92#define VENC_HVLDCL0 0x134
93#define VENC_HVLDCL1 0x138
94#define VENC_OSDHADV 0x13C
95#define VENC_CLKCTL 0x140
96#define VENC_GAMCTL 0x144
97#define VENC_XHINTVL 0x174
98
99/* bit definitions */
100#define VPBE_PCR_VENC_DIV (1 << 1)
101#define VPBE_PCR_CLK_OFF (1 << 0)
102
103#define VENC_VMOD_VDMD_SHIFT 12
104#define VENC_VMOD_VDMD_YCBCR16 0
105#define VENC_VMOD_VDMD_YCBCR8 1
106#define VENC_VMOD_VDMD_RGB666 2
107#define VENC_VMOD_VDMD_RGB8 3
108#define VENC_VMOD_VDMD_EPSON 4
109#define VENC_VMOD_VDMD_CASIO 5
110#define VENC_VMOD_VDMD_UDISPQVGA 6
111#define VENC_VMOD_VDMD_STNLCD 7
112#define VENC_VMOD_VIE_SHIFT 1
113#define VENC_VMOD_VDMD (7 << 12)
114#define VENC_VMOD_ITLCL (1 << 11)
115#define VENC_VMOD_ITLC (1 << 10)
116#define VENC_VMOD_NSIT (1 << 9)
117#define VENC_VMOD_HDMD (1 << 8)
118#define VENC_VMOD_TVTYP_SHIFT 6
119#define VENC_VMOD_TVTYP (3 << 6)
120#define VENC_VMOD_SLAVE (1 << 5)
121#define VENC_VMOD_VMD (1 << 4)
122#define VENC_VMOD_BLNK (1 << 3)
123#define VENC_VMOD_VIE (1 << 1)
124#define VENC_VMOD_VENC (1 << 0)
125
126/* VMOD TVTYP options for HDMD=0 */
127#define SDTV_NTSC 0
128#define SDTV_PAL 1
129/* VMOD TVTYP options for HDMD=1 */
130#define HDTV_525P 0
131#define HDTV_625P 1
132#define HDTV_1080I 2
133#define HDTV_720P 3
134
135#define VENC_VIDCTL_VCLKP (1 << 14)
136#define VENC_VIDCTL_VCLKE_SHIFT 13
137#define VENC_VIDCTL_VCLKE (1 << 13)
138#define VENC_VIDCTL_VCLKZ_SHIFT 12
139#define VENC_VIDCTL_VCLKZ (1 << 12)
140#define VENC_VIDCTL_SYDIR_SHIFT 8
141#define VENC_VIDCTL_SYDIR (1 << 8)
142#define VENC_VIDCTL_DOMD_SHIFT 4
143#define VENC_VIDCTL_DOMD (3 << 4)
144#define VENC_VIDCTL_YCDIR_SHIFT 0
145#define VENC_VIDCTL_YCDIR (1 << 0)
146
147#define VENC_VDPRO_ATYCC_SHIFT 5
148#define VENC_VDPRO_ATYCC (1 << 5)
149#define VENC_VDPRO_ATCOM_SHIFT 4
150#define VENC_VDPRO_ATCOM (1 << 4)
151#define VENC_VDPRO_DAFRQ (1 << 3)
152#define VENC_VDPRO_DAUPS (1 << 2)
153#define VENC_VDPRO_CUPS (1 << 1)
154#define VENC_VDPRO_YUPS (1 << 0)
155
156#define VENC_SYNCCTL_VPL_SHIFT 3
157#define VENC_SYNCCTL_VPL (1 << 3)
158#define VENC_SYNCCTL_HPL_SHIFT 2
159#define VENC_SYNCCTL_HPL (1 << 2)
160#define VENC_SYNCCTL_SYEV_SHIFT 1
161#define VENC_SYNCCTL_SYEV (1 << 1)
162#define VENC_SYNCCTL_SYEH_SHIFT 0
163#define VENC_SYNCCTL_SYEH (1 << 0)
164#define VENC_SYNCCTL_OVD_SHIFT 14
165#define VENC_SYNCCTL_OVD (1 << 14)
166
167#define VENC_DCLKCTL_DCKEC_SHIFT 11
168#define VENC_DCLKCTL_DCKEC (1 << 11)
169#define VENC_DCLKCTL_DCKPW_SHIFT 0
170#define VENC_DCLKCTL_DCKPW (0x3f << 0)
171
172#define VENC_VSTAT_FIDST (1 << 4)
173
174#define VENC_CMPNT_MRGB_SHIFT 14
175#define VENC_CMPNT_MRGB (1 << 14)
176
177#endif /* _VPBE_VENC_REGS_H */
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c
new file mode 100644
index 00000000000..5b38fc93ff2
--- /dev/null
+++ b/drivers/media/video/davinci/vpfe_capture.c
@@ -0,0 +1,2095 @@
1/*
2 * Copyright (C) 2008-2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Driver name : VPFE Capture driver
19 * VPFE Capture driver allows applications to capture and stream video
20 * frames on DaVinci SoCs (DM6446, DM355 etc) from a YUV source such as
21 * TVP5146 or Raw Bayer RGB image data from an image sensor
22 * such as Microns' MT9T001, MT9T031 etc.
23 *
24 * These SoCs have, in common, a Video Processing Subsystem (VPSS) that
25 * consists of a Video Processing Front End (VPFE) for capturing
26 * video/raw image data and Video Processing Back End (VPBE) for displaying
27 * YUV data through an in-built analog encoder or Digital LCD port. This
28 * driver is for capture through VPFE. A typical EVM using these SoCs have
29 * following high level configuration.
30 *
31 *
32 * decoder(TVP5146/ YUV/
33 * MT9T001) --> Raw Bayer RGB ---> MUX -> VPFE (CCDC/ISIF)
34 * data input | |
35 * V |
36 * SDRAM |
37 * V
38 * Image Processor
39 * |
40 * V
41 * SDRAM
42 * The data flow happens from a decoder connected to the VPFE over a
43 * YUV embedded (BT.656/BT.1120) or separate sync or raw bayer rgb interface
44 * and to the input of VPFE through an optional MUX (if more inputs are
45 * to be interfaced on the EVM). The input data is first passed through
46 * CCDC (CCD Controller, a.k.a Image Sensor Interface, ISIF). The CCDC
47 * does very little or no processing on YUV data and does pre-process Raw
48 * Bayer RGB data through modules such as Defect Pixel Correction (DFC)
49 * Color Space Conversion (CSC), data gain/offset etc. After this, data
50 * can be written to SDRAM or can be connected to the image processing
51 * block such as IPIPE (on DM355 only).
52 *
53 * Features supported
54 * - MMAP IO
55 * - Capture using TVP5146 over BT.656
56 * - support for interfacing decoders using sub device model
57 * - Work with DM355 or DM6446 CCDC to do Raw Bayer RGB/YUV
58 * data capture to SDRAM.
59 * TODO list
60 * - Support multiple REQBUF after open
61 * - Support for de-allocating buffers through REQBUF
62 * - Support for Raw Bayer RGB capture
63 * - Support for chaining Image Processor
64 * - Support for static allocation of buffers
65 * - Support for USERPTR IO
66 * - Support for STREAMON before QBUF
67 * - Support for control ioctls
68 */
69#include <linux/module.h>
70#include <linux/slab.h>
71#include <linux/init.h>
72#include <linux/platform_device.h>
73#include <linux/interrupt.h>
74#include <media/v4l2-common.h>
75#include <linux/io.h>
76#include <media/davinci/vpfe_capture.h>
77#include "ccdc_hw_device.h"
78
79static int debug;
80static u32 numbuffers = 3;
81static u32 bufsize = (720 * 576 * 2);
82
83module_param(numbuffers, uint, S_IRUGO);
84module_param(bufsize, uint, S_IRUGO);
85module_param(debug, int, 0644);
86
87MODULE_PARM_DESC(numbuffers, "buffer count (default:3)");
88MODULE_PARM_DESC(bufsize, "buffer size in bytes (default:720 x 576 x 2)");
89MODULE_PARM_DESC(debug, "Debug level 0-1");
90
91MODULE_DESCRIPTION("VPFE Video for Linux Capture Driver");
92MODULE_LICENSE("GPL");
93MODULE_AUTHOR("Texas Instruments");
94
95/* standard information */
96struct vpfe_standard {
97 v4l2_std_id std_id;
98 unsigned int width;
99 unsigned int height;
100 struct v4l2_fract pixelaspect;
101 /* 0 - progressive, 1 - interlaced */
102 int frame_format;
103};
104
105/* ccdc configuration */
106struct ccdc_config {
107 /* This make sure vpfe is probed and ready to go */
108 int vpfe_probed;
109 /* name of ccdc device */
110 char name[32];
111};
112
113/* data structures */
114static struct vpfe_config_params config_params = {
115 .min_numbuffers = 3,
116 .numbuffers = 3,
117 .min_bufsize = 720 * 480 * 2,
118 .device_bufsize = 720 * 576 * 2,
119};
120
121/* ccdc device registered */
122static struct ccdc_hw_device *ccdc_dev;
123/* lock for accessing ccdc information */
124static DEFINE_MUTEX(ccdc_lock);
125/* ccdc configuration */
126static struct ccdc_config *ccdc_cfg;
127
128const struct vpfe_standard vpfe_standards[] = {
129 {V4L2_STD_525_60, 720, 480, {11, 10}, 1},
130 {V4L2_STD_625_50, 720, 576, {54, 59}, 1},
131};
132
133/* Used when raw Bayer image from ccdc is directly captured to SDRAM */
134static const struct vpfe_pixel_format vpfe_pix_fmts[] = {
135 {
136 .fmtdesc = {
137 .index = 0,
138 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
139 .description = "Bayer GrRBGb 8bit A-Law compr.",
140 .pixelformat = V4L2_PIX_FMT_SBGGR8,
141 },
142 .bpp = 1,
143 },
144 {
145 .fmtdesc = {
146 .index = 1,
147 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
148 .description = "Bayer GrRBGb - 16bit",
149 .pixelformat = V4L2_PIX_FMT_SBGGR16,
150 },
151 .bpp = 2,
152 },
153 {
154 .fmtdesc = {
155 .index = 2,
156 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
157 .description = "Bayer GrRBGb 8bit DPCM compr.",
158 .pixelformat = V4L2_PIX_FMT_SGRBG10DPCM8,
159 },
160 .bpp = 1,
161 },
162 {
163 .fmtdesc = {
164 .index = 3,
165 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
166 .description = "YCbCr 4:2:2 Interleaved UYVY",
167 .pixelformat = V4L2_PIX_FMT_UYVY,
168 },
169 .bpp = 2,
170 },
171 {
172 .fmtdesc = {
173 .index = 4,
174 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
175 .description = "YCbCr 4:2:2 Interleaved YUYV",
176 .pixelformat = V4L2_PIX_FMT_YUYV,
177 },
178 .bpp = 2,
179 },
180 {
181 .fmtdesc = {
182 .index = 5,
183 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
184 .description = "Y/CbCr 4:2:0 - Semi planar",
185 .pixelformat = V4L2_PIX_FMT_NV12,
186 },
187 .bpp = 1,
188 },
189};
190
191/*
192 * vpfe_lookup_pix_format()
193 * lookup an entry in the vpfe pix format table based on pix_format
194 */
195static const struct vpfe_pixel_format *vpfe_lookup_pix_format(u32 pix_format)
196{
197 int i;
198
199 for (i = 0; i < ARRAY_SIZE(vpfe_pix_fmts); i++) {
200 if (pix_format == vpfe_pix_fmts[i].fmtdesc.pixelformat)
201 return &vpfe_pix_fmts[i];
202 }
203 return NULL;
204}
205
206/*
207 * vpfe_register_ccdc_device. CCDC module calls this to
208 * register with vpfe capture
209 */
210int vpfe_register_ccdc_device(struct ccdc_hw_device *dev)
211{
212 int ret = 0;
213 printk(KERN_NOTICE "vpfe_register_ccdc_device: %s\n", dev->name);
214
215 BUG_ON(!dev->hw_ops.open);
216 BUG_ON(!dev->hw_ops.enable);
217 BUG_ON(!dev->hw_ops.set_hw_if_params);
218 BUG_ON(!dev->hw_ops.configure);
219 BUG_ON(!dev->hw_ops.set_buftype);
220 BUG_ON(!dev->hw_ops.get_buftype);
221 BUG_ON(!dev->hw_ops.enum_pix);
222 BUG_ON(!dev->hw_ops.set_frame_format);
223 BUG_ON(!dev->hw_ops.get_frame_format);
224 BUG_ON(!dev->hw_ops.get_pixel_format);
225 BUG_ON(!dev->hw_ops.set_pixel_format);
226 BUG_ON(!dev->hw_ops.set_image_window);
227 BUG_ON(!dev->hw_ops.get_image_window);
228 BUG_ON(!dev->hw_ops.get_line_length);
229 BUG_ON(!dev->hw_ops.getfid);
230
231 mutex_lock(&ccdc_lock);
232 if (NULL == ccdc_cfg) {
233 /*
234 * TODO. Will this ever happen? if so, we need to fix it.
235 * Proabably we need to add the request to a linked list and
236 * walk through it during vpfe probe
237 */
238 printk(KERN_ERR "vpfe capture not initialized\n");
239 ret = -EFAULT;
240 goto unlock;
241 }
242
243 if (strcmp(dev->name, ccdc_cfg->name)) {
244 /* ignore this ccdc */
245 ret = -EINVAL;
246 goto unlock;
247 }
248
249 if (ccdc_dev) {
250 printk(KERN_ERR "ccdc already registered\n");
251 ret = -EINVAL;
252 goto unlock;
253 }
254
255 ccdc_dev = dev;
256unlock:
257 mutex_unlock(&ccdc_lock);
258 return ret;
259}
260EXPORT_SYMBOL(vpfe_register_ccdc_device);
261
262/*
263 * vpfe_unregister_ccdc_device. CCDC module calls this to
264 * unregister with vpfe capture
265 */
266void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev)
267{
268 if (NULL == dev) {
269 printk(KERN_ERR "invalid ccdc device ptr\n");
270 return;
271 }
272
273 printk(KERN_NOTICE "vpfe_unregister_ccdc_device, dev->name = %s\n",
274 dev->name);
275
276 if (strcmp(dev->name, ccdc_cfg->name)) {
277 /* ignore this ccdc */
278 return;
279 }
280
281 mutex_lock(&ccdc_lock);
282 ccdc_dev = NULL;
283 mutex_unlock(&ccdc_lock);
284 return;
285}
286EXPORT_SYMBOL(vpfe_unregister_ccdc_device);
287
288/*
289 * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings
290 */
291static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev,
292 struct v4l2_format *f)
293{
294 struct v4l2_rect image_win;
295 enum ccdc_buftype buf_type;
296 enum ccdc_frmfmt frm_fmt;
297
298 memset(f, 0, sizeof(*f));
299 f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
300 ccdc_dev->hw_ops.get_image_window(&image_win);
301 f->fmt.pix.width = image_win.width;
302 f->fmt.pix.height = image_win.height;
303 f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length();
304 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
305 f->fmt.pix.height;
306 buf_type = ccdc_dev->hw_ops.get_buftype();
307 f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format();
308 frm_fmt = ccdc_dev->hw_ops.get_frame_format();
309 if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
310 f->fmt.pix.field = V4L2_FIELD_NONE;
311 else if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
312 if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
313 f->fmt.pix.field = V4L2_FIELD_INTERLACED;
314 else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED)
315 f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
316 else {
317 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n");
318 return -EINVAL;
319 }
320 } else {
321 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n");
322 return -EINVAL;
323 }
324 return 0;
325}
326
327/*
328 * vpfe_config_ccdc_image_format()
329 * For a pix format, configure ccdc to setup the capture
330 */
331static int vpfe_config_ccdc_image_format(struct vpfe_device *vpfe_dev)
332{
333 enum ccdc_frmfmt frm_fmt = CCDC_FRMFMT_INTERLACED;
334 int ret = 0;
335
336 if (ccdc_dev->hw_ops.set_pixel_format(
337 vpfe_dev->fmt.fmt.pix.pixelformat) < 0) {
338 v4l2_err(&vpfe_dev->v4l2_dev,
339 "couldn't set pix format in ccdc\n");
340 return -EINVAL;
341 }
342 /* configure the image window */
343 ccdc_dev->hw_ops.set_image_window(&vpfe_dev->crop);
344
345 switch (vpfe_dev->fmt.fmt.pix.field) {
346 case V4L2_FIELD_INTERLACED:
347 /* do nothing, since it is default */
348 ret = ccdc_dev->hw_ops.set_buftype(
349 CCDC_BUFTYPE_FLD_INTERLEAVED);
350 break;
351 case V4L2_FIELD_NONE:
352 frm_fmt = CCDC_FRMFMT_PROGRESSIVE;
353 /* buffer type only applicable for interlaced scan */
354 break;
355 case V4L2_FIELD_SEQ_TB:
356 ret = ccdc_dev->hw_ops.set_buftype(
357 CCDC_BUFTYPE_FLD_SEPARATED);
358 break;
359 default:
360 return -EINVAL;
361 }
362
363 /* set the frame format */
364 if (!ret)
365 ret = ccdc_dev->hw_ops.set_frame_format(frm_fmt);
366 return ret;
367}
368/*
369 * vpfe_config_image_format()
370 * For a given standard, this functions sets up the default
371 * pix format & crop values in the vpfe device and ccdc. It first
372 * starts with defaults based values from the standard table.
373 * It then checks if sub device support g_mbus_fmt and then override the
374 * values based on that.Sets crop values to match with scan resolution
375 * starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
376 * values in ccdc
377 */
378static int vpfe_config_image_format(struct vpfe_device *vpfe_dev,
379 const v4l2_std_id *std_id)
380{
381 struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev;
382 struct v4l2_mbus_framefmt mbus_fmt;
383 struct v4l2_pix_format *pix = &vpfe_dev->fmt.fmt.pix;
384 int i, ret = 0;
385
386 for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
387 if (vpfe_standards[i].std_id & *std_id) {
388 vpfe_dev->std_info.active_pixels =
389 vpfe_standards[i].width;
390 vpfe_dev->std_info.active_lines =
391 vpfe_standards[i].height;
392 vpfe_dev->std_info.frame_format =
393 vpfe_standards[i].frame_format;
394 vpfe_dev->std_index = i;
395 break;
396 }
397 }
398
399 if (i == ARRAY_SIZE(vpfe_standards)) {
400 v4l2_err(&vpfe_dev->v4l2_dev, "standard not supported\n");
401 return -EINVAL;
402 }
403
404 vpfe_dev->crop.top = 0;
405 vpfe_dev->crop.left = 0;
406 vpfe_dev->crop.width = vpfe_dev->std_info.active_pixels;
407 vpfe_dev->crop.height = vpfe_dev->std_info.active_lines;
408 pix->width = vpfe_dev->crop.width;
409 pix->height = vpfe_dev->crop.height;
410
411 /* first field and frame format based on standard frame format */
412 if (vpfe_dev->std_info.frame_format) {
413 pix->field = V4L2_FIELD_INTERLACED;
414 /* assume V4L2_PIX_FMT_UYVY as default */
415 pix->pixelformat = V4L2_PIX_FMT_UYVY;
416 v4l2_fill_mbus_format(&mbus_fmt, pix,
417 V4L2_MBUS_FMT_YUYV10_2X10);
418 } else {
419 pix->field = V4L2_FIELD_NONE;
420 /* assume V4L2_PIX_FMT_SBGGR8 */
421 pix->pixelformat = V4L2_PIX_FMT_SBGGR8;
422 v4l2_fill_mbus_format(&mbus_fmt, pix,
423 V4L2_MBUS_FMT_SBGGR8_1X8);
424 }
425
426 /* if sub device supports g_mbus_fmt, override the defaults */
427 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
428 sdinfo->grp_id, video, g_mbus_fmt, &mbus_fmt);
429
430 if (ret && ret != -ENOIOCTLCMD) {
431 v4l2_err(&vpfe_dev->v4l2_dev,
432 "error in getting g_mbus_fmt from sub device\n");
433 return ret;
434 }
435 v4l2_fill_pix_format(pix, &mbus_fmt);
436 pix->bytesperline = pix->width * 2;
437 pix->sizeimage = pix->bytesperline * pix->height;
438
439 /* Sets the values in CCDC */
440 ret = vpfe_config_ccdc_image_format(vpfe_dev);
441 if (ret)
442 return ret;
443
444 /* Update the values of sizeimage and bytesperline */
445 if (!ret) {
446 pix->bytesperline = ccdc_dev->hw_ops.get_line_length();
447 pix->sizeimage = pix->bytesperline * pix->height;
448 }
449 return ret;
450}
451
452static int vpfe_initialize_device(struct vpfe_device *vpfe_dev)
453{
454 int ret = 0;
455
456 /* set first input of current subdevice as the current input */
457 vpfe_dev->current_input = 0;
458
459 /* set default standard */
460 vpfe_dev->std_index = 0;
461
462 /* Configure the default format information */
463 ret = vpfe_config_image_format(vpfe_dev,
464 &vpfe_standards[vpfe_dev->std_index].std_id);
465 if (ret)
466 return ret;
467
468 /* now open the ccdc device to initialize it */
469 mutex_lock(&ccdc_lock);
470 if (NULL == ccdc_dev) {
471 v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n");
472 ret = -ENODEV;
473 goto unlock;
474 }
475
476 if (!try_module_get(ccdc_dev->owner)) {
477 v4l2_err(&vpfe_dev->v4l2_dev, "Couldn't lock ccdc module\n");
478 ret = -ENODEV;
479 goto unlock;
480 }
481 ret = ccdc_dev->hw_ops.open(vpfe_dev->pdev);
482 if (!ret)
483 vpfe_dev->initialized = 1;
484
485 /* Clear all VPFE/CCDC interrupts */
486 if (vpfe_dev->cfg->clr_intr)
487 vpfe_dev->cfg->clr_intr(-1);
488
489unlock:
490 mutex_unlock(&ccdc_lock);
491 return ret;
492}
493
494/*
495 * vpfe_open : It creates object of file handle structure and
496 * stores it in private_data member of filepointer
497 */
498static int vpfe_open(struct file *file)
499{
500 struct vpfe_device *vpfe_dev = video_drvdata(file);
501 struct vpfe_fh *fh;
502
503 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_open\n");
504
505 if (!vpfe_dev->cfg->num_subdevs) {
506 v4l2_err(&vpfe_dev->v4l2_dev, "No decoder registered\n");
507 return -ENODEV;
508 }
509
510 /* Allocate memory for the file handle object */
511 fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
512 if (NULL == fh) {
513 v4l2_err(&vpfe_dev->v4l2_dev,
514 "unable to allocate memory for file handle object\n");
515 return -ENOMEM;
516 }
517 /* store pointer to fh in private_data member of file */
518 file->private_data = fh;
519 fh->vpfe_dev = vpfe_dev;
520 mutex_lock(&vpfe_dev->lock);
521 /* If decoder is not initialized. initialize it */
522 if (!vpfe_dev->initialized) {
523 if (vpfe_initialize_device(vpfe_dev)) {
524 mutex_unlock(&vpfe_dev->lock);
525 return -ENODEV;
526 }
527 }
528 /* Increment device usrs counter */
529 vpfe_dev->usrs++;
530 /* Set io_allowed member to false */
531 fh->io_allowed = 0;
532 /* Initialize priority of this instance to default priority */
533 fh->prio = V4L2_PRIORITY_UNSET;
534 v4l2_prio_open(&vpfe_dev->prio, &fh->prio);
535 mutex_unlock(&vpfe_dev->lock);
536 return 0;
537}
538
539static void vpfe_schedule_next_buffer(struct vpfe_device *vpfe_dev)
540{
541 unsigned long addr;
542
543 vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
544 struct videobuf_buffer, queue);
545 list_del(&vpfe_dev->next_frm->queue);
546 vpfe_dev->next_frm->state = VIDEOBUF_ACTIVE;
547 addr = videobuf_to_dma_contig(vpfe_dev->next_frm);
548
549 ccdc_dev->hw_ops.setfbaddr(addr);
550}
551
552static void vpfe_schedule_bottom_field(struct vpfe_device *vpfe_dev)
553{
554 unsigned long addr;
555
556 addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
557 addr += vpfe_dev->field_off;
558 ccdc_dev->hw_ops.setfbaddr(addr);
559}
560
561static void vpfe_process_buffer_complete(struct vpfe_device *vpfe_dev)
562{
563 struct timeval timevalue;
564
565 do_gettimeofday(&timevalue);
566 vpfe_dev->cur_frm->ts = timevalue;
567 vpfe_dev->cur_frm->state = VIDEOBUF_DONE;
568 vpfe_dev->cur_frm->size = vpfe_dev->fmt.fmt.pix.sizeimage;
569 wake_up_interruptible(&vpfe_dev->cur_frm->done);
570 vpfe_dev->cur_frm = vpfe_dev->next_frm;
571}
572
573/* ISR for VINT0*/
574static irqreturn_t vpfe_isr(int irq, void *dev_id)
575{
576 struct vpfe_device *vpfe_dev = dev_id;
577 enum v4l2_field field;
578 int fid;
579
580 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nStarting vpfe_isr...\n");
581 field = vpfe_dev->fmt.fmt.pix.field;
582
583 /* if streaming not started, don't do anything */
584 if (!vpfe_dev->started)
585 goto clear_intr;
586
587 /* only for 6446 this will be applicable */
588 if (NULL != ccdc_dev->hw_ops.reset)
589 ccdc_dev->hw_ops.reset();
590
591 if (field == V4L2_FIELD_NONE) {
592 /* handle progressive frame capture */
593 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
594 "frame format is progressive...\n");
595 if (vpfe_dev->cur_frm != vpfe_dev->next_frm)
596 vpfe_process_buffer_complete(vpfe_dev);
597 goto clear_intr;
598 }
599
600 /* interlaced or TB capture check which field we are in hardware */
601 fid = ccdc_dev->hw_ops.getfid();
602
603 /* switch the software maintained field id */
604 vpfe_dev->field_id ^= 1;
605 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "field id = %x:%x.\n",
606 fid, vpfe_dev->field_id);
607 if (fid == vpfe_dev->field_id) {
608 /* we are in-sync here,continue */
609 if (fid == 0) {
610 /*
611 * One frame is just being captured. If the next frame
612 * is available, release the current frame and move on
613 */
614 if (vpfe_dev->cur_frm != vpfe_dev->next_frm)
615 vpfe_process_buffer_complete(vpfe_dev);
616 /*
617 * based on whether the two fields are stored
618 * interleavely or separately in memory, reconfigure
619 * the CCDC memory address
620 */
621 if (field == V4L2_FIELD_SEQ_TB) {
622 vpfe_schedule_bottom_field(vpfe_dev);
623 }
624 goto clear_intr;
625 }
626 /*
627 * if one field is just being captured configure
628 * the next frame get the next frame from the empty
629 * queue if no frame is available hold on to the
630 * current buffer
631 */
632 spin_lock(&vpfe_dev->dma_queue_lock);
633 if (!list_empty(&vpfe_dev->dma_queue) &&
634 vpfe_dev->cur_frm == vpfe_dev->next_frm)
635 vpfe_schedule_next_buffer(vpfe_dev);
636 spin_unlock(&vpfe_dev->dma_queue_lock);
637 } else if (fid == 0) {
638 /*
639 * out of sync. Recover from any hardware out-of-sync.
640 * May loose one frame
641 */
642 vpfe_dev->field_id = fid;
643 }
644clear_intr:
645 if (vpfe_dev->cfg->clr_intr)
646 vpfe_dev->cfg->clr_intr(irq);
647
648 return IRQ_HANDLED;
649}
650
651/* vdint1_isr - isr handler for VINT1 interrupt */
652static irqreturn_t vdint1_isr(int irq, void *dev_id)
653{
654 struct vpfe_device *vpfe_dev = dev_id;
655
656 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "\nInside vdint1_isr...\n");
657
658 /* if streaming not started, don't do anything */
659 if (!vpfe_dev->started) {
660 if (vpfe_dev->cfg->clr_intr)
661 vpfe_dev->cfg->clr_intr(irq);
662 return IRQ_HANDLED;
663 }
664
665 spin_lock(&vpfe_dev->dma_queue_lock);
666 if ((vpfe_dev->fmt.fmt.pix.field == V4L2_FIELD_NONE) &&
667 !list_empty(&vpfe_dev->dma_queue) &&
668 vpfe_dev->cur_frm == vpfe_dev->next_frm)
669 vpfe_schedule_next_buffer(vpfe_dev);
670 spin_unlock(&vpfe_dev->dma_queue_lock);
671
672 if (vpfe_dev->cfg->clr_intr)
673 vpfe_dev->cfg->clr_intr(irq);
674
675 return IRQ_HANDLED;
676}
677
678static void vpfe_detach_irq(struct vpfe_device *vpfe_dev)
679{
680 enum ccdc_frmfmt frame_format;
681
682 frame_format = ccdc_dev->hw_ops.get_frame_format();
683 if (frame_format == CCDC_FRMFMT_PROGRESSIVE)
684 free_irq(vpfe_dev->ccdc_irq1, vpfe_dev);
685}
686
687static int vpfe_attach_irq(struct vpfe_device *vpfe_dev)
688{
689 enum ccdc_frmfmt frame_format;
690
691 frame_format = ccdc_dev->hw_ops.get_frame_format();
692 if (frame_format == CCDC_FRMFMT_PROGRESSIVE) {
693 return request_irq(vpfe_dev->ccdc_irq1, vdint1_isr,
694 IRQF_DISABLED, "vpfe_capture1",
695 vpfe_dev);
696 }
697 return 0;
698}
699
700/* vpfe_stop_ccdc_capture: stop streaming in ccdc/isif */
701static void vpfe_stop_ccdc_capture(struct vpfe_device *vpfe_dev)
702{
703 vpfe_dev->started = 0;
704 ccdc_dev->hw_ops.enable(0);
705 if (ccdc_dev->hw_ops.enable_out_to_sdram)
706 ccdc_dev->hw_ops.enable_out_to_sdram(0);
707}
708
709/*
710 * vpfe_release : This function deletes buffer queue, frees the
711 * buffers and the vpfe file handle
712 */
713static int vpfe_release(struct file *file)
714{
715 struct vpfe_device *vpfe_dev = video_drvdata(file);
716 struct vpfe_fh *fh = file->private_data;
717 struct vpfe_subdev_info *sdinfo;
718 int ret;
719
720 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
721
722 /* Get the device lock */
723 mutex_lock(&vpfe_dev->lock);
724 /* if this instance is doing IO */
725 if (fh->io_allowed) {
726 if (vpfe_dev->started) {
727 sdinfo = vpfe_dev->current_subdev;
728 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
729 sdinfo->grp_id,
730 video, s_stream, 0);
731 if (ret && (ret != -ENOIOCTLCMD))
732 v4l2_err(&vpfe_dev->v4l2_dev,
733 "stream off failed in subdev\n");
734 vpfe_stop_ccdc_capture(vpfe_dev);
735 vpfe_detach_irq(vpfe_dev);
736 videobuf_streamoff(&vpfe_dev->buffer_queue);
737 }
738 vpfe_dev->io_usrs = 0;
739 vpfe_dev->numbuffers = config_params.numbuffers;
740 }
741
742 /* Decrement device usrs counter */
743 vpfe_dev->usrs--;
744 /* Close the priority */
745 v4l2_prio_close(&vpfe_dev->prio, fh->prio);
746 /* If this is the last file handle */
747 if (!vpfe_dev->usrs) {
748 vpfe_dev->initialized = 0;
749 if (ccdc_dev->hw_ops.close)
750 ccdc_dev->hw_ops.close(vpfe_dev->pdev);
751 module_put(ccdc_dev->owner);
752 }
753 mutex_unlock(&vpfe_dev->lock);
754 file->private_data = NULL;
755 /* Free memory allocated to file handle object */
756 kfree(fh);
757 return 0;
758}
759
760/*
761 * vpfe_mmap : It is used to map kernel space buffers
762 * into user spaces
763 */
764static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
765{
766 /* Get the device object and file handle object */
767 struct vpfe_device *vpfe_dev = video_drvdata(file);
768
769 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
770
771 return videobuf_mmap_mapper(&vpfe_dev->buffer_queue, vma);
772}
773
774/*
775 * vpfe_poll: It is used for select/poll system call
776 */
777static unsigned int vpfe_poll(struct file *file, poll_table *wait)
778{
779 struct vpfe_device *vpfe_dev = video_drvdata(file);
780
781 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
782
783 if (vpfe_dev->started)
784 return videobuf_poll_stream(file,
785 &vpfe_dev->buffer_queue, wait);
786 return 0;
787}
788
789/* vpfe capture driver file operations */
790static const struct v4l2_file_operations vpfe_fops = {
791 .owner = THIS_MODULE,
792 .open = vpfe_open,
793 .release = vpfe_release,
794 .unlocked_ioctl = video_ioctl2,
795 .mmap = vpfe_mmap,
796 .poll = vpfe_poll
797};
798
799/*
800 * vpfe_check_format()
801 * This function adjust the input pixel format as per hardware
802 * capabilities and update the same in pixfmt.
803 * Following algorithm used :-
804 *
805 * If given pixformat is not in the vpfe list of pix formats or not
806 * supported by the hardware, current value of pixformat in the device
807 * is used
808 * If given field is not supported, then current field is used. If field
809 * is different from current, then it is matched with that from sub device.
810 * Minimum height is 2 lines for interlaced or tb field and 1 line for
811 * progressive. Maximum height is clamped to active active lines of scan
812 * Minimum width is 32 bytes in memory and width is clamped to active
813 * pixels of scan.
814 * bytesperline is a multiple of 32.
815 */
816static const struct vpfe_pixel_format *
817 vpfe_check_format(struct vpfe_device *vpfe_dev,
818 struct v4l2_pix_format *pixfmt)
819{
820 u32 min_height = 1, min_width = 32, max_width, max_height;
821 const struct vpfe_pixel_format *vpfe_pix_fmt;
822 u32 pix;
823 int temp, found;
824
825 vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
826 if (NULL == vpfe_pix_fmt) {
827 /*
828 * use current pixel format in the vpfe device. We
829 * will find this pix format in the table
830 */
831 pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
832 vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
833 }
834
835 /* check if hw supports it */
836 temp = 0;
837 found = 0;
838 while (ccdc_dev->hw_ops.enum_pix(&pix, temp) >= 0) {
839 if (vpfe_pix_fmt->fmtdesc.pixelformat == pix) {
840 found = 1;
841 break;
842 }
843 temp++;
844 }
845
846 if (!found) {
847 /* use current pixel format */
848 pixfmt->pixelformat = vpfe_dev->fmt.fmt.pix.pixelformat;
849 /*
850 * Since this is currently used in the vpfe device, we
851 * will find this pix format in the table
852 */
853 vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
854 }
855
856 /* check what field format is supported */
857 if (pixfmt->field == V4L2_FIELD_ANY) {
858 /* if field is any, use current value as default */
859 pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
860 }
861
862 /*
863 * if field is not same as current field in the vpfe device
864 * try matching the field with the sub device field
865 */
866 if (vpfe_dev->fmt.fmt.pix.field != pixfmt->field) {
867 /*
868 * If field value is not in the supported fields, use current
869 * field used in the device as default
870 */
871 switch (pixfmt->field) {
872 case V4L2_FIELD_INTERLACED:
873 case V4L2_FIELD_SEQ_TB:
874 /* if sub device is supporting progressive, use that */
875 if (!vpfe_dev->std_info.frame_format)
876 pixfmt->field = V4L2_FIELD_NONE;
877 break;
878 case V4L2_FIELD_NONE:
879 if (vpfe_dev->std_info.frame_format)
880 pixfmt->field = V4L2_FIELD_INTERLACED;
881 break;
882
883 default:
884 /* use current field as default */
885 pixfmt->field = vpfe_dev->fmt.fmt.pix.field;
886 break;
887 }
888 }
889
890 /* Now adjust image resolutions supported */
891 if (pixfmt->field == V4L2_FIELD_INTERLACED ||
892 pixfmt->field == V4L2_FIELD_SEQ_TB)
893 min_height = 2;
894
895 max_width = vpfe_dev->std_info.active_pixels;
896 max_height = vpfe_dev->std_info.active_lines;
897 min_width /= vpfe_pix_fmt->bpp;
898
899 v4l2_info(&vpfe_dev->v4l2_dev, "width = %d, height = %d, bpp = %d\n",
900 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp);
901
902 pixfmt->width = clamp((pixfmt->width), min_width, max_width);
903 pixfmt->height = clamp((pixfmt->height), min_height, max_height);
904
905 /* If interlaced, adjust height to be a multiple of 2 */
906 if (pixfmt->field == V4L2_FIELD_INTERLACED)
907 pixfmt->height &= (~1);
908 /*
909 * recalculate bytesperline and sizeimage since width
910 * and height might have changed
911 */
912 pixfmt->bytesperline = (((pixfmt->width * vpfe_pix_fmt->bpp) + 31)
913 & ~31);
914 if (pixfmt->pixelformat == V4L2_PIX_FMT_NV12)
915 pixfmt->sizeimage =
916 pixfmt->bytesperline * pixfmt->height +
917 ((pixfmt->bytesperline * pixfmt->height) >> 1);
918 else
919 pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
920
921 v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="
922 " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
923 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,
924 pixfmt->bytesperline, pixfmt->sizeimage);
925 return vpfe_pix_fmt;
926}
927
928static int vpfe_querycap(struct file *file, void *priv,
929 struct v4l2_capability *cap)
930{
931 struct vpfe_device *vpfe_dev = video_drvdata(file);
932
933 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
934
935 cap->version = VPFE_CAPTURE_VERSION_CODE;
936 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
937 strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
938 strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
939 strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
940 return 0;
941}
942
943static int vpfe_g_fmt_vid_cap(struct file *file, void *priv,
944 struct v4l2_format *fmt)
945{
946 struct vpfe_device *vpfe_dev = video_drvdata(file);
947 int ret = 0;
948
949 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt_vid_cap\n");
950 /* Fill in the information about format */
951 *fmt = vpfe_dev->fmt;
952 return ret;
953}
954
955static int vpfe_enum_fmt_vid_cap(struct file *file, void *priv,
956 struct v4l2_fmtdesc *fmt)
957{
958 struct vpfe_device *vpfe_dev = video_drvdata(file);
959 const struct vpfe_pixel_format *pix_fmt;
960 int temp_index;
961 u32 pix;
962
963 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt_vid_cap\n");
964
965 if (ccdc_dev->hw_ops.enum_pix(&pix, fmt->index) < 0)
966 return -EINVAL;
967
968 /* Fill in the information about format */
969 pix_fmt = vpfe_lookup_pix_format(pix);
970 if (NULL != pix_fmt) {
971 temp_index = fmt->index;
972 *fmt = pix_fmt->fmtdesc;
973 fmt->index = temp_index;
974 return 0;
975 }
976 return -EINVAL;
977}
978
979static int vpfe_s_fmt_vid_cap(struct file *file, void *priv,
980 struct v4l2_format *fmt)
981{
982 struct vpfe_device *vpfe_dev = video_drvdata(file);
983 const struct vpfe_pixel_format *pix_fmts;
984 int ret = 0;
985
986 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");
987
988 /* If streaming is started, return error */
989 if (vpfe_dev->started) {
990 v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
991 return -EBUSY;
992 }
993
994 /* Check for valid frame format */
995 pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);
996
997 if (NULL == pix_fmts)
998 return -EINVAL;
999
1000 /* store the pixel format in the device object */
1001 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1002 if (ret)
1003 return ret;
1004
1005 /* First detach any IRQ if currently attached */
1006 vpfe_detach_irq(vpfe_dev);
1007 vpfe_dev->fmt = *fmt;
1008 /* set image capture parameters in the ccdc */
1009 ret = vpfe_config_ccdc_image_format(vpfe_dev);
1010 mutex_unlock(&vpfe_dev->lock);
1011 return ret;
1012}
1013
1014static int vpfe_try_fmt_vid_cap(struct file *file, void *priv,
1015 struct v4l2_format *f)
1016{
1017 struct vpfe_device *vpfe_dev = video_drvdata(file);
1018 const struct vpfe_pixel_format *pix_fmts;
1019
1020 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");
1021
1022 pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);
1023 if (NULL == pix_fmts)
1024 return -EINVAL;
1025 return 0;
1026}
1027
1028/*
1029 * vpfe_get_subdev_input_index - Get subdev index and subdev input index for a
1030 * given app input index
1031 */
1032static int vpfe_get_subdev_input_index(struct vpfe_device *vpfe_dev,
1033 int *subdev_index,
1034 int *subdev_input_index,
1035 int app_input_index)
1036{
1037 struct vpfe_config *cfg = vpfe_dev->cfg;
1038 struct vpfe_subdev_info *sdinfo;
1039 int i, j = 0;
1040
1041 for (i = 0; i < cfg->num_subdevs; i++) {
1042 sdinfo = &cfg->sub_devs[i];
1043 if (app_input_index < (j + sdinfo->num_inputs)) {
1044 *subdev_index = i;
1045 *subdev_input_index = app_input_index - j;
1046 return 0;
1047 }
1048 j += sdinfo->num_inputs;
1049 }
1050 return -EINVAL;
1051}
1052
1053/*
1054 * vpfe_get_app_input - Get app input index for a given subdev input index
1055 * driver stores the input index of the current sub device and translate it
1056 * when application request the current input
1057 */
1058static int vpfe_get_app_input_index(struct vpfe_device *vpfe_dev,
1059 int *app_input_index)
1060{
1061 struct vpfe_config *cfg = vpfe_dev->cfg;
1062 struct vpfe_subdev_info *sdinfo;
1063 int i, j = 0;
1064
1065 for (i = 0; i < cfg->num_subdevs; i++) {
1066 sdinfo = &cfg->sub_devs[i];
1067 if (!strcmp(sdinfo->name, vpfe_dev->current_subdev->name)) {
1068 if (vpfe_dev->current_input >= sdinfo->num_inputs)
1069 return -1;
1070 *app_input_index = j + vpfe_dev->current_input;
1071 return 0;
1072 }
1073 j += sdinfo->num_inputs;
1074 }
1075 return -EINVAL;
1076}
1077
1078static int vpfe_enum_input(struct file *file, void *priv,
1079 struct v4l2_input *inp)
1080{
1081 struct vpfe_device *vpfe_dev = video_drvdata(file);
1082 struct vpfe_subdev_info *sdinfo;
1083 int subdev, index ;
1084
1085 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
1086
1087 if (vpfe_get_subdev_input_index(vpfe_dev,
1088 &subdev,
1089 &index,
1090 inp->index) < 0) {
1091 v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"
1092 " for the subdev\n");
1093 return -EINVAL;
1094 }
1095 sdinfo = &vpfe_dev->cfg->sub_devs[subdev];
1096 memcpy(inp, &sdinfo->inputs[index], sizeof(struct v4l2_input));
1097 return 0;
1098}
1099
1100static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
1101{
1102 struct vpfe_device *vpfe_dev = video_drvdata(file);
1103
1104 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
1105
1106 return vpfe_get_app_input_index(vpfe_dev, index);
1107}
1108
1109
1110static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
1111{
1112 struct vpfe_device *vpfe_dev = video_drvdata(file);
1113 struct vpfe_subdev_info *sdinfo;
1114 int subdev_index, inp_index;
1115 struct vpfe_route *route;
1116 u32 input = 0, output = 0;
1117 int ret = -EINVAL;
1118
1119 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
1120
1121 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1122 if (ret)
1123 return ret;
1124
1125 /*
1126 * If streaming is started return device busy
1127 * error
1128 */
1129 if (vpfe_dev->started) {
1130 v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
1131 ret = -EBUSY;
1132 goto unlock_out;
1133 }
1134
1135 if (vpfe_get_subdev_input_index(vpfe_dev,
1136 &subdev_index,
1137 &inp_index,
1138 index) < 0) {
1139 v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");
1140 goto unlock_out;
1141 }
1142
1143 sdinfo = &vpfe_dev->cfg->sub_devs[subdev_index];
1144 route = &sdinfo->routes[inp_index];
1145 if (route && sdinfo->can_route) {
1146 input = route->input;
1147 output = route->output;
1148 }
1149
1150 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1151 video, s_routing, input, output, 0);
1152
1153 if (ret) {
1154 v4l2_err(&vpfe_dev->v4l2_dev,
1155 "vpfe_doioctl:error in setting input in decoder\n");
1156 ret = -EINVAL;
1157 goto unlock_out;
1158 }
1159 vpfe_dev->current_subdev = sdinfo;
1160 vpfe_dev->current_input = index;
1161 vpfe_dev->std_index = 0;
1162
1163 /* set the bus/interface parameter for the sub device in ccdc */
1164 ret = ccdc_dev->hw_ops.set_hw_if_params(&sdinfo->ccdc_if_params);
1165 if (ret)
1166 goto unlock_out;
1167
1168 /* set the default image parameters in the device */
1169 ret = vpfe_config_image_format(vpfe_dev,
1170 &vpfe_standards[vpfe_dev->std_index].std_id);
1171unlock_out:
1172 mutex_unlock(&vpfe_dev->lock);
1173 return ret;
1174}
1175
1176static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
1177{
1178 struct vpfe_device *vpfe_dev = video_drvdata(file);
1179 struct vpfe_subdev_info *sdinfo;
1180 int ret = 0;
1181
1182 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
1183
1184 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1185 sdinfo = vpfe_dev->current_subdev;
1186 if (ret)
1187 return ret;
1188 /* Call querystd function of decoder device */
1189 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1190 video, querystd, std_id);
1191 mutex_unlock(&vpfe_dev->lock);
1192 return ret;
1193}
1194
1195static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
1196{
1197 struct vpfe_device *vpfe_dev = video_drvdata(file);
1198 struct vpfe_subdev_info *sdinfo;
1199 int ret = 0;
1200
1201 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
1202
1203 /* Call decoder driver function to set the standard */
1204 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1205 if (ret)
1206 return ret;
1207
1208 sdinfo = vpfe_dev->current_subdev;
1209 /* If streaming is started, return device busy error */
1210 if (vpfe_dev->started) {
1211 v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
1212 ret = -EBUSY;
1213 goto unlock_out;
1214 }
1215
1216 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1217 core, s_std, *std_id);
1218 if (ret < 0) {
1219 v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
1220 goto unlock_out;
1221 }
1222 ret = vpfe_config_image_format(vpfe_dev, std_id);
1223
1224unlock_out:
1225 mutex_unlock(&vpfe_dev->lock);
1226 return ret;
1227}
1228
1229static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *std_id)
1230{
1231 struct vpfe_device *vpfe_dev = video_drvdata(file);
1232
1233 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
1234
1235 *std_id = vpfe_standards[vpfe_dev->std_index].std_id;
1236 return 0;
1237}
1238/*
1239 * Videobuf operations
1240 */
1241static int vpfe_videobuf_setup(struct videobuf_queue *vq,
1242 unsigned int *count,
1243 unsigned int *size)
1244{
1245 struct vpfe_fh *fh = vq->priv_data;
1246 struct vpfe_device *vpfe_dev = fh->vpfe_dev;
1247
1248 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_setup\n");
1249 *size = vpfe_dev->fmt.fmt.pix.sizeimage;
1250 if (vpfe_dev->memory == V4L2_MEMORY_MMAP &&
1251 vpfe_dev->fmt.fmt.pix.sizeimage > config_params.device_bufsize)
1252 *size = config_params.device_bufsize;
1253
1254 if (*count < config_params.min_numbuffers)
1255 *count = config_params.min_numbuffers;
1256 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1257 "count=%d, size=%d\n", *count, *size);
1258 return 0;
1259}
1260
1261static int vpfe_videobuf_prepare(struct videobuf_queue *vq,
1262 struct videobuf_buffer *vb,
1263 enum v4l2_field field)
1264{
1265 struct vpfe_fh *fh = vq->priv_data;
1266 struct vpfe_device *vpfe_dev = fh->vpfe_dev;
1267 unsigned long addr;
1268 int ret;
1269
1270 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
1271
1272 /* If buffer is not initialized, initialize it */
1273 if (VIDEOBUF_NEEDS_INIT == vb->state) {
1274 vb->width = vpfe_dev->fmt.fmt.pix.width;
1275 vb->height = vpfe_dev->fmt.fmt.pix.height;
1276 vb->size = vpfe_dev->fmt.fmt.pix.sizeimage;
1277 vb->field = field;
1278
1279 ret = videobuf_iolock(vq, vb, NULL);
1280 if (ret < 0)
1281 return ret;
1282
1283 addr = videobuf_to_dma_contig(vb);
1284 /* Make sure user addresses are aligned to 32 bytes */
1285 if (!ALIGN(addr, 32))
1286 return -EINVAL;
1287
1288 vb->state = VIDEOBUF_PREPARED;
1289 }
1290 return 0;
1291}
1292
1293static void vpfe_videobuf_queue(struct videobuf_queue *vq,
1294 struct videobuf_buffer *vb)
1295{
1296 /* Get the file handle object and device object */
1297 struct vpfe_fh *fh = vq->priv_data;
1298 struct vpfe_device *vpfe_dev = fh->vpfe_dev;
1299 unsigned long flags;
1300
1301 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue\n");
1302
1303 /* add the buffer to the DMA queue */
1304 spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
1305 list_add_tail(&vb->queue, &vpfe_dev->dma_queue);
1306 spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
1307
1308 /* Change state of the buffer */
1309 vb->state = VIDEOBUF_QUEUED;
1310}
1311
1312static void vpfe_videobuf_release(struct videobuf_queue *vq,
1313 struct videobuf_buffer *vb)
1314{
1315 struct vpfe_fh *fh = vq->priv_data;
1316 struct vpfe_device *vpfe_dev = fh->vpfe_dev;
1317 unsigned long flags;
1318
1319 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_videobuf_release\n");
1320
1321 /*
1322 * We need to flush the buffer from the dma queue since
1323 * they are de-allocated
1324 */
1325 spin_lock_irqsave(&vpfe_dev->dma_queue_lock, flags);
1326 INIT_LIST_HEAD(&vpfe_dev->dma_queue);
1327 spin_unlock_irqrestore(&vpfe_dev->dma_queue_lock, flags);
1328 videobuf_dma_contig_free(vq, vb);
1329 vb->state = VIDEOBUF_NEEDS_INIT;
1330}
1331
1332static struct videobuf_queue_ops vpfe_videobuf_qops = {
1333 .buf_setup = vpfe_videobuf_setup,
1334 .buf_prepare = vpfe_videobuf_prepare,
1335 .buf_queue = vpfe_videobuf_queue,
1336 .buf_release = vpfe_videobuf_release,
1337};
1338
1339/*
1340 * vpfe_reqbufs. currently support REQBUF only once opening
1341 * the device.
1342 */
1343static int vpfe_reqbufs(struct file *file, void *priv,
1344 struct v4l2_requestbuffers *req_buf)
1345{
1346 struct vpfe_device *vpfe_dev = video_drvdata(file);
1347 struct vpfe_fh *fh = file->private_data;
1348 int ret = 0;
1349
1350 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
1351
1352 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != req_buf->type) {
1353 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
1354 return -EINVAL;
1355 }
1356
1357 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1358 if (ret)
1359 return ret;
1360
1361 if (vpfe_dev->io_usrs != 0) {
1362 v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
1363 ret = -EBUSY;
1364 goto unlock_out;
1365 }
1366
1367 vpfe_dev->memory = req_buf->memory;
1368 videobuf_queue_dma_contig_init(&vpfe_dev->buffer_queue,
1369 &vpfe_videobuf_qops,
1370 vpfe_dev->pdev,
1371 &vpfe_dev->irqlock,
1372 req_buf->type,
1373 vpfe_dev->fmt.fmt.pix.field,
1374 sizeof(struct videobuf_buffer),
1375 fh, NULL);
1376
1377 fh->io_allowed = 1;
1378 vpfe_dev->io_usrs = 1;
1379 INIT_LIST_HEAD(&vpfe_dev->dma_queue);
1380 ret = videobuf_reqbufs(&vpfe_dev->buffer_queue, req_buf);
1381unlock_out:
1382 mutex_unlock(&vpfe_dev->lock);
1383 return ret;
1384}
1385
1386static int vpfe_querybuf(struct file *file, void *priv,
1387 struct v4l2_buffer *buf)
1388{
1389 struct vpfe_device *vpfe_dev = video_drvdata(file);
1390
1391 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
1392
1393 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
1394 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1395 return -EINVAL;
1396 }
1397
1398 if (vpfe_dev->memory != V4L2_MEMORY_MMAP) {
1399 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
1400 return -EINVAL;
1401 }
1402 /* Call videobuf_querybuf to get information */
1403 return videobuf_querybuf(&vpfe_dev->buffer_queue, buf);
1404}
1405
1406static int vpfe_qbuf(struct file *file, void *priv,
1407 struct v4l2_buffer *p)
1408{
1409 struct vpfe_device *vpfe_dev = video_drvdata(file);
1410 struct vpfe_fh *fh = file->private_data;
1411
1412 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
1413
1414 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != p->type) {
1415 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1416 return -EINVAL;
1417 }
1418
1419 /*
1420 * If this file handle is not allowed to do IO,
1421 * return error
1422 */
1423 if (!fh->io_allowed) {
1424 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1425 return -EACCES;
1426 }
1427 return videobuf_qbuf(&vpfe_dev->buffer_queue, p);
1428}
1429
1430static int vpfe_dqbuf(struct file *file, void *priv,
1431 struct v4l2_buffer *buf)
1432{
1433 struct vpfe_device *vpfe_dev = video_drvdata(file);
1434
1435 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
1436
1437 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf->type) {
1438 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1439 return -EINVAL;
1440 }
1441 return videobuf_dqbuf(&vpfe_dev->buffer_queue,
1442 buf, file->f_flags & O_NONBLOCK);
1443}
1444
1445static int vpfe_queryctrl(struct file *file, void *priv,
1446 struct v4l2_queryctrl *qctrl)
1447{
1448 struct vpfe_device *vpfe_dev = video_drvdata(file);
1449 struct vpfe_subdev_info *sdinfo;
1450
1451 sdinfo = vpfe_dev->current_subdev;
1452
1453 return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1454 core, queryctrl, qctrl);
1455
1456}
1457
1458static int vpfe_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
1459{
1460 struct vpfe_device *vpfe_dev = video_drvdata(file);
1461 struct vpfe_subdev_info *sdinfo;
1462
1463 sdinfo = vpfe_dev->current_subdev;
1464
1465 return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1466 core, g_ctrl, ctrl);
1467}
1468
1469static int vpfe_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl)
1470{
1471 struct vpfe_device *vpfe_dev = video_drvdata(file);
1472 struct vpfe_subdev_info *sdinfo;
1473
1474 sdinfo = vpfe_dev->current_subdev;
1475
1476 return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1477 core, s_ctrl, ctrl);
1478}
1479
1480/*
1481 * vpfe_calculate_offsets : This function calculates buffers offset
1482 * for top and bottom field
1483 */
1484static void vpfe_calculate_offsets(struct vpfe_device *vpfe_dev)
1485{
1486 struct v4l2_rect image_win;
1487
1488 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_calculate_offsets\n");
1489
1490 ccdc_dev->hw_ops.get_image_window(&image_win);
1491 vpfe_dev->field_off = image_win.height * image_win.width;
1492}
1493
1494/* vpfe_start_ccdc_capture: start streaming in ccdc/isif */
1495static void vpfe_start_ccdc_capture(struct vpfe_device *vpfe_dev)
1496{
1497 ccdc_dev->hw_ops.enable(1);
1498 if (ccdc_dev->hw_ops.enable_out_to_sdram)
1499 ccdc_dev->hw_ops.enable_out_to_sdram(1);
1500 vpfe_dev->started = 1;
1501}
1502
1503/*
1504 * vpfe_streamon. Assume the DMA queue is not empty.
1505 * application is expected to call QBUF before calling
1506 * this ioctl. If not, driver returns error
1507 */
1508static int vpfe_streamon(struct file *file, void *priv,
1509 enum v4l2_buf_type buf_type)
1510{
1511 struct vpfe_device *vpfe_dev = video_drvdata(file);
1512 struct vpfe_fh *fh = file->private_data;
1513 struct vpfe_subdev_info *sdinfo;
1514 unsigned long addr;
1515 int ret = 0;
1516
1517 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
1518
1519 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
1520 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1521 return -EINVAL;
1522 }
1523
1524 /* If file handle is not allowed IO, return error */
1525 if (!fh->io_allowed) {
1526 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1527 return -EACCES;
1528 }
1529
1530 sdinfo = vpfe_dev->current_subdev;
1531 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1532 video, s_stream, 1);
1533
1534 if (ret && (ret != -ENOIOCTLCMD)) {
1535 v4l2_err(&vpfe_dev->v4l2_dev, "stream on failed in subdev\n");
1536 return -EINVAL;
1537 }
1538
1539 /* If buffer queue is empty, return error */
1540 if (list_empty(&vpfe_dev->buffer_queue.stream)) {
1541 v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
1542 return -EIO;
1543 }
1544
1545 /* Call videobuf_streamon to start streaming * in videobuf */
1546 ret = videobuf_streamon(&vpfe_dev->buffer_queue);
1547 if (ret)
1548 return ret;
1549
1550
1551 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1552 if (ret)
1553 goto streamoff;
1554 /* Get the next frame from the buffer queue */
1555 vpfe_dev->next_frm = list_entry(vpfe_dev->dma_queue.next,
1556 struct videobuf_buffer, queue);
1557 vpfe_dev->cur_frm = vpfe_dev->next_frm;
1558 /* Remove buffer from the buffer queue */
1559 list_del(&vpfe_dev->cur_frm->queue);
1560 /* Mark state of the current frame to active */
1561 vpfe_dev->cur_frm->state = VIDEOBUF_ACTIVE;
1562 /* Initialize field_id and started member */
1563 vpfe_dev->field_id = 0;
1564 addr = videobuf_to_dma_contig(vpfe_dev->cur_frm);
1565
1566 /* Calculate field offset */
1567 vpfe_calculate_offsets(vpfe_dev);
1568
1569 if (vpfe_attach_irq(vpfe_dev) < 0) {
1570 v4l2_err(&vpfe_dev->v4l2_dev,
1571 "Error in attaching interrupt handle\n");
1572 ret = -EFAULT;
1573 goto unlock_out;
1574 }
1575 if (ccdc_dev->hw_ops.configure() < 0) {
1576 v4l2_err(&vpfe_dev->v4l2_dev,
1577 "Error in configuring ccdc\n");
1578 ret = -EINVAL;
1579 goto unlock_out;
1580 }
1581 ccdc_dev->hw_ops.setfbaddr((unsigned long)(addr));
1582 vpfe_start_ccdc_capture(vpfe_dev);
1583 mutex_unlock(&vpfe_dev->lock);
1584 return ret;
1585unlock_out:
1586 mutex_unlock(&vpfe_dev->lock);
1587streamoff:
1588 ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
1589 return ret;
1590}
1591
1592static int vpfe_streamoff(struct file *file, void *priv,
1593 enum v4l2_buf_type buf_type)
1594{
1595 struct vpfe_device *vpfe_dev = video_drvdata(file);
1596 struct vpfe_fh *fh = file->private_data;
1597 struct vpfe_subdev_info *sdinfo;
1598 int ret = 0;
1599
1600 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
1601
1602 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != buf_type) {
1603 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1604 return -EINVAL;
1605 }
1606
1607 /* If io is allowed for this file handle, return error */
1608 if (!fh->io_allowed) {
1609 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1610 return -EACCES;
1611 }
1612
1613 /* If streaming is not started, return error */
1614 if (!vpfe_dev->started) {
1615 v4l2_err(&vpfe_dev->v4l2_dev, "device started\n");
1616 return -EINVAL;
1617 }
1618
1619 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1620 if (ret)
1621 return ret;
1622
1623 vpfe_stop_ccdc_capture(vpfe_dev);
1624 vpfe_detach_irq(vpfe_dev);
1625
1626 sdinfo = vpfe_dev->current_subdev;
1627 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
1628 video, s_stream, 0);
1629
1630 if (ret && (ret != -ENOIOCTLCMD))
1631 v4l2_err(&vpfe_dev->v4l2_dev, "stream off failed in subdev\n");
1632 ret = videobuf_streamoff(&vpfe_dev->buffer_queue);
1633 mutex_unlock(&vpfe_dev->lock);
1634 return ret;
1635}
1636
1637static int vpfe_cropcap(struct file *file, void *priv,
1638 struct v4l2_cropcap *crop)
1639{
1640 struct vpfe_device *vpfe_dev = video_drvdata(file);
1641
1642 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_cropcap\n");
1643
1644 if (vpfe_dev->std_index >= ARRAY_SIZE(vpfe_standards))
1645 return -EINVAL;
1646
1647 memset(crop, 0, sizeof(struct v4l2_cropcap));
1648 crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1649 crop->bounds.width = crop->defrect.width =
1650 vpfe_standards[vpfe_dev->std_index].width;
1651 crop->bounds.height = crop->defrect.height =
1652 vpfe_standards[vpfe_dev->std_index].height;
1653 crop->pixelaspect = vpfe_standards[vpfe_dev->std_index].pixelaspect;
1654 return 0;
1655}
1656
1657static int vpfe_g_crop(struct file *file, void *priv,
1658 struct v4l2_crop *crop)
1659{
1660 struct vpfe_device *vpfe_dev = video_drvdata(file);
1661
1662 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_crop\n");
1663
1664 crop->c = vpfe_dev->crop;
1665 return 0;
1666}
1667
1668static int vpfe_s_crop(struct file *file, void *priv,
1669 struct v4l2_crop *crop)
1670{
1671 struct vpfe_device *vpfe_dev = video_drvdata(file);
1672 int ret = 0;
1673
1674 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
1675
1676 if (vpfe_dev->started) {
1677 /* make sure streaming is not started */
1678 v4l2_err(&vpfe_dev->v4l2_dev,
1679 "Cannot change crop when streaming is ON\n");
1680 return -EBUSY;
1681 }
1682
1683 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1684 if (ret)
1685 return ret;
1686
1687 if (crop->c.top < 0 || crop->c.left < 0) {
1688 v4l2_err(&vpfe_dev->v4l2_dev,
1689 "doesn't support negative values for top & left\n");
1690 ret = -EINVAL;
1691 goto unlock_out;
1692 }
1693
1694 /* adjust the width to 16 pixel boundary */
1695 crop->c.width = ((crop->c.width + 15) & ~0xf);
1696
1697 /* make sure parameters are valid */
1698 if ((crop->c.left + crop->c.width >
1699 vpfe_dev->std_info.active_pixels) ||
1700 (crop->c.top + crop->c.height >
1701 vpfe_dev->std_info.active_lines)) {
1702 v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
1703 ret = -EINVAL;
1704 goto unlock_out;
1705 }
1706 ccdc_dev->hw_ops.set_image_window(&crop->c);
1707 vpfe_dev->fmt.fmt.pix.width = crop->c.width;
1708 vpfe_dev->fmt.fmt.pix.height = crop->c.height;
1709 vpfe_dev->fmt.fmt.pix.bytesperline =
1710 ccdc_dev->hw_ops.get_line_length();
1711 vpfe_dev->fmt.fmt.pix.sizeimage =
1712 vpfe_dev->fmt.fmt.pix.bytesperline *
1713 vpfe_dev->fmt.fmt.pix.height;
1714 vpfe_dev->crop = crop->c;
1715unlock_out:
1716 mutex_unlock(&vpfe_dev->lock);
1717 return ret;
1718}
1719
1720
1721static long vpfe_param_handler(struct file *file, void *priv,
1722 bool valid_prio, int cmd, void *param)
1723{
1724 struct vpfe_device *vpfe_dev = video_drvdata(file);
1725 int ret = 0;
1726
1727 v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
1728
1729 if (vpfe_dev->started) {
1730 /* only allowed if streaming is not started */
1731 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1732 "device already started\n");
1733 return -EBUSY;
1734 }
1735
1736 ret = mutex_lock_interruptible(&vpfe_dev->lock);
1737 if (ret)
1738 return ret;
1739
1740 switch (cmd) {
1741 case VPFE_CMD_S_CCDC_RAW_PARAMS:
1742 v4l2_warn(&vpfe_dev->v4l2_dev,
1743 "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n");
1744 if (ccdc_dev->hw_ops.set_params) {
1745 ret = ccdc_dev->hw_ops.set_params(param);
1746 if (ret) {
1747 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1748 "Error setting parameters in CCDC\n");
1749 goto unlock_out;
1750 }
1751 if (vpfe_get_ccdc_image_format(vpfe_dev,
1752 &vpfe_dev->fmt) < 0) {
1753 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1754 "Invalid image format at CCDC\n");
1755 goto unlock_out;
1756 }
1757 } else {
1758 ret = -EINVAL;
1759 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1760 "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n");
1761 }
1762 break;
1763 default:
1764 ret = -EINVAL;
1765 }
1766unlock_out:
1767 mutex_unlock(&vpfe_dev->lock);
1768 return ret;
1769}
1770
1771
1772/* vpfe capture ioctl operations */
1773static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
1774 .vidioc_querycap = vpfe_querycap,
1775 .vidioc_g_fmt_vid_cap = vpfe_g_fmt_vid_cap,
1776 .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt_vid_cap,
1777 .vidioc_s_fmt_vid_cap = vpfe_s_fmt_vid_cap,
1778 .vidioc_try_fmt_vid_cap = vpfe_try_fmt_vid_cap,
1779 .vidioc_enum_input = vpfe_enum_input,
1780 .vidioc_g_input = vpfe_g_input,
1781 .vidioc_s_input = vpfe_s_input,
1782 .vidioc_querystd = vpfe_querystd,
1783 .vidioc_s_std = vpfe_s_std,
1784 .vidioc_g_std = vpfe_g_std,
1785 .vidioc_queryctrl = vpfe_queryctrl,
1786 .vidioc_g_ctrl = vpfe_g_ctrl,
1787 .vidioc_s_ctrl = vpfe_s_ctrl,
1788 .vidioc_reqbufs = vpfe_reqbufs,
1789 .vidioc_querybuf = vpfe_querybuf,
1790 .vidioc_qbuf = vpfe_qbuf,
1791 .vidioc_dqbuf = vpfe_dqbuf,
1792 .vidioc_streamon = vpfe_streamon,
1793 .vidioc_streamoff = vpfe_streamoff,
1794 .vidioc_cropcap = vpfe_cropcap,
1795 .vidioc_g_crop = vpfe_g_crop,
1796 .vidioc_s_crop = vpfe_s_crop,
1797 .vidioc_default = vpfe_param_handler,
1798};
1799
1800static struct vpfe_device *vpfe_initialize(void)
1801{
1802 struct vpfe_device *vpfe_dev;
1803
1804 /* Default number of buffers should be 3 */
1805 if ((numbuffers > 0) &&
1806 (numbuffers < config_params.min_numbuffers))
1807 numbuffers = config_params.min_numbuffers;
1808
1809 /*
1810 * Set buffer size to min buffers size if invalid buffer size is
1811 * given
1812 */
1813 if (bufsize < config_params.min_bufsize)
1814 bufsize = config_params.min_bufsize;
1815
1816 config_params.numbuffers = numbuffers;
1817
1818 if (numbuffers)
1819 config_params.device_bufsize = bufsize;
1820
1821 /* Allocate memory for device objects */
1822 vpfe_dev = kzalloc(sizeof(*vpfe_dev), GFP_KERNEL);
1823
1824 return vpfe_dev;
1825}
1826
1827/*
1828 * vpfe_probe : This function creates device entries by register
1829 * itself to the V4L2 driver and initializes fields of each
1830 * device objects
1831 */
1832static __init int vpfe_probe(struct platform_device *pdev)
1833{
1834 struct vpfe_subdev_info *sdinfo;
1835 struct vpfe_config *vpfe_cfg;
1836 struct resource *res1;
1837 struct vpfe_device *vpfe_dev;
1838 struct i2c_adapter *i2c_adap;
1839 struct video_device *vfd;
1840 int ret = -ENOMEM, i, j;
1841 int num_subdevs = 0;
1842
1843 /* Get the pointer to the device object */
1844 vpfe_dev = vpfe_initialize();
1845
1846 if (!vpfe_dev) {
1847 v4l2_err(pdev->dev.driver,
1848 "Failed to allocate memory for vpfe_dev\n");
1849 return ret;
1850 }
1851
1852 vpfe_dev->pdev = &pdev->dev;
1853
1854 if (NULL == pdev->dev.platform_data) {
1855 v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
1856 ret = -ENODEV;
1857 goto probe_free_dev_mem;
1858 }
1859
1860 vpfe_cfg = pdev->dev.platform_data;
1861 vpfe_dev->cfg = vpfe_cfg;
1862 if (NULL == vpfe_cfg->ccdc ||
1863 NULL == vpfe_cfg->card_name ||
1864 NULL == vpfe_cfg->sub_devs) {
1865 v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
1866 ret = -ENOENT;
1867 goto probe_free_dev_mem;
1868 }
1869
1870 /* Allocate memory for ccdc configuration */
1871 ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);
1872 if (NULL == ccdc_cfg) {
1873 v4l2_err(pdev->dev.driver,
1874 "Memory allocation failed for ccdc_cfg\n");
1875 goto probe_free_lock;
1876 }
1877
1878 mutex_lock(&ccdc_lock);
1879
1880 strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32);
1881 /* Get VINT0 irq resource */
1882 res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1883 if (!res1) {
1884 v4l2_err(pdev->dev.driver,
1885 "Unable to get interrupt for VINT0\n");
1886 ret = -ENODEV;
1887 goto probe_free_ccdc_cfg_mem;
1888 }
1889 vpfe_dev->ccdc_irq0 = res1->start;
1890
1891 /* Get VINT1 irq resource */
1892 res1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
1893 if (!res1) {
1894 v4l2_err(pdev->dev.driver,
1895 "Unable to get interrupt for VINT1\n");
1896 ret = -ENODEV;
1897 goto probe_free_ccdc_cfg_mem;
1898 }
1899 vpfe_dev->ccdc_irq1 = res1->start;
1900
1901 ret = request_irq(vpfe_dev->ccdc_irq0, vpfe_isr, IRQF_DISABLED,
1902 "vpfe_capture0", vpfe_dev);
1903
1904 if (0 != ret) {
1905 v4l2_err(pdev->dev.driver, "Unable to request interrupt\n");
1906 goto probe_free_ccdc_cfg_mem;
1907 }
1908
1909 /* Allocate memory for video device */
1910 vfd = video_device_alloc();
1911 if (NULL == vfd) {
1912 ret = -ENOMEM;
1913 v4l2_err(pdev->dev.driver, "Unable to alloc video device\n");
1914 goto probe_out_release_irq;
1915 }
1916
1917 /* Initialize field of video device */
1918 vfd->release = video_device_release;
1919 vfd->fops = &vpfe_fops;
1920 vfd->ioctl_ops = &vpfe_ioctl_ops;
1921 vfd->tvnorms = 0;
1922 vfd->current_norm = V4L2_STD_PAL;
1923 vfd->v4l2_dev = &vpfe_dev->v4l2_dev;
1924 snprintf(vfd->name, sizeof(vfd->name),
1925 "%s_V%d.%d.%d",
1926 CAPTURE_DRV_NAME,
1927 (VPFE_CAPTURE_VERSION_CODE >> 16) & 0xff,
1928 (VPFE_CAPTURE_VERSION_CODE >> 8) & 0xff,
1929 (VPFE_CAPTURE_VERSION_CODE) & 0xff);
1930 /* Set video_dev to the video device */
1931 vpfe_dev->video_dev = vfd;
1932
1933 ret = v4l2_device_register(&pdev->dev, &vpfe_dev->v4l2_dev);
1934 if (ret) {
1935 v4l2_err(pdev->dev.driver,
1936 "Unable to register v4l2 device.\n");
1937 goto probe_out_video_release;
1938 }
1939 v4l2_info(&vpfe_dev->v4l2_dev, "v4l2 device registered\n");
1940 spin_lock_init(&vpfe_dev->irqlock);
1941 spin_lock_init(&vpfe_dev->dma_queue_lock);
1942 mutex_init(&vpfe_dev->lock);
1943
1944 /* Initialize field of the device objects */
1945 vpfe_dev->numbuffers = config_params.numbuffers;
1946
1947 /* Initialize prio member of device object */
1948 v4l2_prio_init(&vpfe_dev->prio);
1949 /* register video device */
1950 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1951 "trying to register vpfe device.\n");
1952 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1953 "video_dev=%x\n", (int)&vpfe_dev->video_dev);
1954 vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1955 ret = video_register_device(vpfe_dev->video_dev,
1956 VFL_TYPE_GRABBER, -1);
1957
1958 if (ret) {
1959 v4l2_err(pdev->dev.driver,
1960 "Unable to register video device.\n");
1961 goto probe_out_v4l2_unregister;
1962 }
1963
1964 v4l2_info(&vpfe_dev->v4l2_dev, "video device registered\n");
1965 /* set the driver data in platform device */
1966 platform_set_drvdata(pdev, vpfe_dev);
1967 /* set driver private data */
1968 video_set_drvdata(vpfe_dev->video_dev, vpfe_dev);
1969 i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id);
1970 num_subdevs = vpfe_cfg->num_subdevs;
1971 vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
1972 GFP_KERNEL);
1973 if (NULL == vpfe_dev->sd) {
1974 v4l2_err(&vpfe_dev->v4l2_dev,
1975 "unable to allocate memory for subdevice pointers\n");
1976 ret = -ENOMEM;
1977 goto probe_out_video_unregister;
1978 }
1979
1980 for (i = 0; i < num_subdevs; i++) {
1981 struct v4l2_input *inps;
1982
1983 sdinfo = &vpfe_cfg->sub_devs[i];
1984
1985 /* Load up the subdevice */
1986 vpfe_dev->sd[i] =
1987 v4l2_i2c_new_subdev_board(&vpfe_dev->v4l2_dev,
1988 i2c_adap,
1989 &sdinfo->board_info,
1990 NULL);
1991 if (vpfe_dev->sd[i]) {
1992 v4l2_info(&vpfe_dev->v4l2_dev,
1993 "v4l2 sub device %s registered\n",
1994 sdinfo->name);
1995 vpfe_dev->sd[i]->grp_id = sdinfo->grp_id;
1996 /* update tvnorms from the sub devices */
1997 for (j = 0; j < sdinfo->num_inputs; j++) {
1998 inps = &sdinfo->inputs[j];
1999 vfd->tvnorms |= inps->std;
2000 }
2001 } else {
2002 v4l2_info(&vpfe_dev->v4l2_dev,
2003 "v4l2 sub device %s register fails\n",
2004 sdinfo->name);
2005 goto probe_sd_out;
2006 }
2007 }
2008
2009 /* set first sub device as current one */
2010 vpfe_dev->current_subdev = &vpfe_cfg->sub_devs[0];
2011
2012 /* We have at least one sub device to work with */
2013 mutex_unlock(&ccdc_lock);
2014 return 0;
2015
2016probe_sd_out:
2017 kfree(vpfe_dev->sd);
2018probe_out_video_unregister:
2019 video_unregister_device(vpfe_dev->video_dev);
2020probe_out_v4l2_unregister:
2021 v4l2_device_unregister(&vpfe_dev->v4l2_dev);
2022probe_out_video_release:
2023 if (!video_is_registered(vpfe_dev->video_dev))
2024 video_device_release(vpfe_dev->video_dev);
2025probe_out_release_irq:
2026 free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
2027probe_free_ccdc_cfg_mem:
2028 kfree(ccdc_cfg);
2029probe_free_lock:
2030 mutex_unlock(&ccdc_lock);
2031probe_free_dev_mem:
2032 kfree(vpfe_dev);
2033 return ret;
2034}
2035
2036/*
2037 * vpfe_remove : It un-register device from V4L2 driver
2038 */
2039static int __devexit vpfe_remove(struct platform_device *pdev)
2040{
2041 struct vpfe_device *vpfe_dev = platform_get_drvdata(pdev);
2042
2043 v4l2_info(pdev->dev.driver, "vpfe_remove\n");
2044
2045 free_irq(vpfe_dev->ccdc_irq0, vpfe_dev);
2046 kfree(vpfe_dev->sd);
2047 v4l2_device_unregister(&vpfe_dev->v4l2_dev);
2048 video_unregister_device(vpfe_dev->video_dev);
2049 kfree(vpfe_dev);
2050 kfree(ccdc_cfg);
2051 return 0;
2052}
2053
2054static int vpfe_suspend(struct device *dev)
2055{
2056 return 0;
2057}
2058
2059static int vpfe_resume(struct device *dev)
2060{
2061 return 0;
2062}
2063
2064static const struct dev_pm_ops vpfe_dev_pm_ops = {
2065 .suspend = vpfe_suspend,
2066 .resume = vpfe_resume,
2067};
2068
2069static struct platform_driver vpfe_driver = {
2070 .driver = {
2071 .name = CAPTURE_DRV_NAME,
2072 .owner = THIS_MODULE,
2073 .pm = &vpfe_dev_pm_ops,
2074 },
2075 .probe = vpfe_probe,
2076 .remove = __devexit_p(vpfe_remove),
2077};
2078
2079static __init int vpfe_init(void)
2080{
2081 printk(KERN_NOTICE "vpfe_init\n");
2082 /* Register driver to the kernel */
2083 return platform_driver_register(&vpfe_driver);
2084}
2085
2086/*
2087 * vpfe_cleanup : This function un-registers device driver
2088 */
2089static void vpfe_cleanup(void)
2090{
2091 platform_driver_unregister(&vpfe_driver);
2092}
2093
2094module_init(vpfe_init);
2095module_exit(vpfe_cleanup);
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c
new file mode 100644
index 00000000000..af9680273ff
--- /dev/null
+++ b/drivers/media/video/davinci/vpif.c
@@ -0,0 +1,473 @@
1/*
2 * vpif - DM646x Video Port Interface driver
3 * VPIF is a receiver and transmitter for video data. It has two channels(0, 1)
4 * that receiveing video byte stream and two channels(2, 3) for video output.
5 * The hardware supports SDTV, HDTV formats, raw data capture.
6 * Currently, the driver supports NTSC and PAL standards.
7 *
8 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation version 2.
13 *
14 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
15 * kind, whether express or implied; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/init.h>
21#include <linux/module.h>
22#include <linux/platform_device.h>
23#include <linux/spinlock.h>
24#include <linux/kernel.h>
25#include <linux/io.h>
26#include <mach/hardware.h>
27
28#include "vpif.h"
29
30MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver");
31MODULE_LICENSE("GPL");
32
33#define VPIF_CH0_MAX_MODES (22)
34#define VPIF_CH1_MAX_MODES (02)
35#define VPIF_CH2_MAX_MODES (15)
36#define VPIF_CH3_MAX_MODES (02)
37
38static resource_size_t res_len;
39static struct resource *res;
40spinlock_t vpif_lock;
41
42void __iomem *vpif_base;
43
44/**
45 * ch_params: video standard configuration parameters for vpif
46 * The table must include all presets from supported subdevices.
47 */
48const struct vpif_channel_config_params ch_params[] = {
49 /* HDTV formats */
50 {
51 .name = "480p59_94",
52 .width = 720,
53 .height = 480,
54 .frm_fmt = 1,
55 .ycmux_mode = 0,
56 .eav2sav = 138-8,
57 .sav2eav = 720,
58 .l1 = 1,
59 .l3 = 43,
60 .l5 = 523,
61 .vsize = 525,
62 .capture_format = 0,
63 .vbi_supported = 0,
64 .hd_sd = 1,
65 .dv_preset = V4L2_DV_480P59_94,
66 },
67 {
68 .name = "576p50",
69 .width = 720,
70 .height = 576,
71 .frm_fmt = 1,
72 .ycmux_mode = 0,
73 .eav2sav = 144-8,
74 .sav2eav = 720,
75 .l1 = 1,
76 .l3 = 45,
77 .l5 = 621,
78 .vsize = 625,
79 .capture_format = 0,
80 .vbi_supported = 0,
81 .hd_sd = 1,
82 .dv_preset = V4L2_DV_576P50,
83 },
84 {
85 .name = "720p50",
86 .width = 1280,
87 .height = 720,
88 .frm_fmt = 1,
89 .ycmux_mode = 0,
90 .eav2sav = 700-8,
91 .sav2eav = 1280,
92 .l1 = 1,
93 .l3 = 26,
94 .l5 = 746,
95 .vsize = 750,
96 .capture_format = 0,
97 .vbi_supported = 0,
98 .hd_sd = 1,
99 .dv_preset = V4L2_DV_720P50,
100 },
101 {
102 .name = "720p60",
103 .width = 1280,
104 .height = 720,
105 .frm_fmt = 1,
106 .ycmux_mode = 0,
107 .eav2sav = 370 - 8,
108 .sav2eav = 1280,
109 .l1 = 1,
110 .l3 = 26,
111 .l5 = 746,
112 .vsize = 750,
113 .capture_format = 0,
114 .vbi_supported = 0,
115 .hd_sd = 1,
116 .dv_preset = V4L2_DV_720P60,
117 },
118 {
119 .name = "1080I50",
120 .width = 1920,
121 .height = 1080,
122 .frm_fmt = 0,
123 .ycmux_mode = 0,
124 .eav2sav = 720 - 8,
125 .sav2eav = 1920,
126 .l1 = 1,
127 .l3 = 21,
128 .l5 = 561,
129 .l7 = 563,
130 .l9 = 584,
131 .l11 = 1124,
132 .vsize = 1125,
133 .capture_format = 0,
134 .vbi_supported = 0,
135 .hd_sd = 1,
136 .dv_preset = V4L2_DV_1080I50,
137 },
138 {
139 .name = "1080I60",
140 .width = 1920,
141 .height = 1080,
142 .frm_fmt = 0,
143 .ycmux_mode = 0,
144 .eav2sav = 280 - 8,
145 .sav2eav = 1920,
146 .l1 = 1,
147 .l3 = 21,
148 .l5 = 561,
149 .l7 = 563,
150 .l9 = 584,
151 .l11 = 1124,
152 .vsize = 1125,
153 .capture_format = 0,
154 .vbi_supported = 0,
155 .hd_sd = 1,
156 .dv_preset = V4L2_DV_1080I60,
157 },
158 {
159 .name = "1080p60",
160 .width = 1920,
161 .height = 1080,
162 .frm_fmt = 1,
163 .ycmux_mode = 0,
164 .eav2sav = 280 - 8,
165 .sav2eav = 1920,
166 .l1 = 1,
167 .l3 = 42,
168 .l5 = 1122,
169 .vsize = 1125,
170 .capture_format = 0,
171 .vbi_supported = 0,
172 .hd_sd = 1,
173 .dv_preset = V4L2_DV_1080P60,
174 },
175
176 /* SDTV formats */
177 {
178 .name = "NTSC_M",
179 .width = 720,
180 .height = 480,
181 .frm_fmt = 0,
182 .ycmux_mode = 1,
183 .eav2sav = 268,
184 .sav2eav = 1440,
185 .l1 = 1,
186 .l3 = 23,
187 .l5 = 263,
188 .l7 = 266,
189 .l9 = 286,
190 .l11 = 525,
191 .vsize = 525,
192 .capture_format = 0,
193 .vbi_supported = 1,
194 .hd_sd = 0,
195 .stdid = V4L2_STD_525_60,
196 },
197 {
198 .name = "PAL_BDGHIK",
199 .width = 720,
200 .height = 576,
201 .frm_fmt = 0,
202 .ycmux_mode = 1,
203 .eav2sav = 280,
204 .sav2eav = 1440,
205 .l1 = 1,
206 .l3 = 23,
207 .l5 = 311,
208 .l7 = 313,
209 .l9 = 336,
210 .l11 = 624,
211 .vsize = 625,
212 .capture_format = 0,
213 .vbi_supported = 1,
214 .hd_sd = 0,
215 .stdid = V4L2_STD_625_50,
216 },
217};
218
219const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);
220
221static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
222{
223 if (val)
224 vpif_set_bit(reg, bit);
225 else
226 vpif_clr_bit(reg, bit);
227}
228
229/* This structure is used to keep track of VPIF size register's offsets */
230struct vpif_registers {
231 u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl;
232 u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt;
233 u32 vanc1_size, width_mask, len_mask;
234 u8 max_modes;
235};
236
237static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = {
238 /* Channel0 */
239 {
240 VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01,
241 VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL,
242 VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
243 VPIF_CH0_MAX_MODES,
244 },
245 /* Channel1 */
246 {
247 VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01,
248 VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL,
249 VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
250 VPIF_CH1_MAX_MODES,
251 },
252 /* Channel2 */
253 {
254 VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01,
255 VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL,
256 VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE,
257 VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF,
258 VPIF_CH2_MAX_MODES
259 },
260 /* Channel3 */
261 {
262 VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01,
263 VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL,
264 VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE,
265 VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF,
266 VPIF_CH3_MAX_MODES
267 },
268};
269
270/* vpif_set_mode_info:
271 * This function is used to set horizontal and vertical config parameters
272 * As per the standard in the channel, configure the values of L1, L3,
273 * L5, L7 L9, L11 in VPIF Register , also write width and height
274 */
275static void vpif_set_mode_info(const struct vpif_channel_config_params *config,
276 u8 channel_id, u8 config_channel_id)
277{
278 u32 value;
279
280 value = (config->eav2sav & vpifregs[config_channel_id].width_mask);
281 value <<= VPIF_CH_LEN_SHIFT;
282 value |= (config->sav2eav & vpifregs[config_channel_id].width_mask);
283 regw(value, vpifregs[channel_id].h_cfg);
284
285 value = (config->l1 & vpifregs[config_channel_id].len_mask);
286 value <<= VPIF_CH_LEN_SHIFT;
287 value |= (config->l3 & vpifregs[config_channel_id].len_mask);
288 regw(value, vpifregs[channel_id].v_cfg_00);
289
290 value = (config->l5 & vpifregs[config_channel_id].len_mask);
291 value <<= VPIF_CH_LEN_SHIFT;
292 value |= (config->l7 & vpifregs[config_channel_id].len_mask);
293 regw(value, vpifregs[channel_id].v_cfg_01);
294
295 value = (config->l9 & vpifregs[config_channel_id].len_mask);
296 value <<= VPIF_CH_LEN_SHIFT;
297 value |= (config->l11 & vpifregs[config_channel_id].len_mask);
298 regw(value, vpifregs[channel_id].v_cfg_02);
299
300 value = (config->vsize & vpifregs[config_channel_id].len_mask);
301 regw(value, vpifregs[channel_id].v_cfg);
302}
303
304/* config_vpif_params
305 * Function to set the parameters of a channel
306 * Mainly modifies the channel ciontrol register
307 * It sets frame format, yc mux mode
308 */
309static void config_vpif_params(struct vpif_params *vpifparams,
310 u8 channel_id, u8 found)
311{
312 const struct vpif_channel_config_params *config = &vpifparams->std_info;
313 u32 value, ch_nip, reg;
314 u8 start, end;
315 int i;
316
317 start = channel_id;
318 end = channel_id + found;
319
320 for (i = start; i < end; i++) {
321 reg = vpifregs[i].ch_ctrl;
322 if (channel_id < 2)
323 ch_nip = VPIF_CAPTURE_CH_NIP;
324 else
325 ch_nip = VPIF_DISPLAY_CH_NIP;
326
327 vpif_wr_bit(reg, ch_nip, config->frm_fmt);
328 vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode);
329 vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT,
330 vpifparams->video_params.storage_mode);
331
332 /* Set raster scanning SDR Format */
333 vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT);
334 vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format);
335
336 if (channel_id > 1) /* Set the Pixel enable bit */
337 vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT);
338 else if (config->capture_format) {
339 /* Set the polarity of various pins */
340 vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT,
341 vpifparams->iface.fid_pol);
342 vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT,
343 vpifparams->iface.vd_pol);
344 vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT,
345 vpifparams->iface.hd_pol);
346
347 value = regr(reg);
348 /* Set data width */
349 value &= ((~(unsigned int)(0x3)) <<
350 VPIF_CH_DATA_WIDTH_BIT);
351 value |= ((vpifparams->params.data_sz) <<
352 VPIF_CH_DATA_WIDTH_BIT);
353 regw(value, reg);
354 }
355
356 /* Write the pitch in the driver */
357 regw((vpifparams->video_params.hpitch),
358 vpifregs[i].line_offset);
359 }
360}
361
362/* vpif_set_video_params
363 * This function is used to set video parameters in VPIF register
364 */
365int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id)
366{
367 const struct vpif_channel_config_params *config = &vpifparams->std_info;
368 int found = 1;
369
370 vpif_set_mode_info(config, channel_id, channel_id);
371 if (!config->ycmux_mode) {
372 /* YC are on separate channels (HDTV formats) */
373 vpif_set_mode_info(config, channel_id + 1, channel_id);
374 found = 2;
375 }
376
377 config_vpif_params(vpifparams, channel_id, found);
378
379 regw(0x80, VPIF_REQ_SIZE);
380 regw(0x01, VPIF_EMULATION_CTRL);
381
382 return found;
383}
384EXPORT_SYMBOL(vpif_set_video_params);
385
386void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,
387 u8 channel_id)
388{
389 u32 value;
390
391 value = 0x3F8 & (vbiparams->hstart0);
392 value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16);
393 regw(value, vpifregs[channel_id].vanc0_strt);
394
395 value = 0x3F8 & (vbiparams->hstart1);
396 value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16);
397 regw(value, vpifregs[channel_id].vanc1_strt);
398
399 value = 0x3F8 & (vbiparams->hsize0);
400 value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16);
401 regw(value, vpifregs[channel_id].vanc0_size);
402
403 value = 0x3F8 & (vbiparams->hsize1);
404 value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16);
405 regw(value, vpifregs[channel_id].vanc1_size);
406
407}
408EXPORT_SYMBOL(vpif_set_vbi_display_params);
409
410int vpif_channel_getfid(u8 channel_id)
411{
412 return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK)
413 >> VPIF_CH_FID_SHIFT;
414}
415EXPORT_SYMBOL(vpif_channel_getfid);
416
417static int __init vpif_probe(struct platform_device *pdev)
418{
419 int status = 0;
420
421 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
422 if (!res)
423 return -ENOENT;
424
425 res_len = resource_size(res);
426
427 res = request_mem_region(res->start, res_len, res->name);
428 if (!res)
429 return -EBUSY;
430
431 vpif_base = ioremap(res->start, res_len);
432 if (!vpif_base) {
433 status = -EBUSY;
434 goto fail;
435 }
436
437 spin_lock_init(&vpif_lock);
438 dev_info(&pdev->dev, "vpif probe success\n");
439 return 0;
440
441fail:
442 release_mem_region(res->start, res_len);
443 return status;
444}
445
446static int __devexit vpif_remove(struct platform_device *pdev)
447{
448 iounmap(vpif_base);
449 release_mem_region(res->start, res_len);
450 return 0;
451}
452
453static struct platform_driver vpif_driver = {
454 .driver = {
455 .name = "vpif",
456 .owner = THIS_MODULE,
457 },
458 .remove = __devexit_p(vpif_remove),
459 .probe = vpif_probe,
460};
461
462static void vpif_exit(void)
463{
464 platform_driver_unregister(&vpif_driver);
465}
466
467static int __init vpif_init(void)
468{
469 return platform_driver_register(&vpif_driver);
470}
471subsys_initcall(vpif_init);
472module_exit(vpif_exit);
473
diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h
new file mode 100644
index 00000000000..10550bd93b0
--- /dev/null
+++ b/drivers/media/video/davinci/vpif.h
@@ -0,0 +1,644 @@
1/*
2 * VPIF header file
3 *
4 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef VPIF_H
17#define VPIF_H
18
19#include <linux/io.h>
20#include <linux/videodev2.h>
21#include <mach/hardware.h>
22#include <mach/dm646x.h>
23
24/* Maximum channel allowed */
25#define VPIF_NUM_CHANNELS (4)
26#define VPIF_CAPTURE_NUM_CHANNELS (2)
27#define VPIF_DISPLAY_NUM_CHANNELS (2)
28
29/* Macros to read/write registers */
30extern void __iomem *vpif_base;
31extern spinlock_t vpif_lock;
32
33#define regr(reg) readl((reg) + vpif_base)
34#define regw(value, reg) writel(value, (reg + vpif_base))
35
36/* Register Address Offsets */
37#define VPIF_PID (0x0000)
38#define VPIF_CH0_CTRL (0x0004)
39#define VPIF_CH1_CTRL (0x0008)
40#define VPIF_CH2_CTRL (0x000C)
41#define VPIF_CH3_CTRL (0x0010)
42
43#define VPIF_INTEN (0x0020)
44#define VPIF_INTEN_SET (0x0024)
45#define VPIF_INTEN_CLR (0x0028)
46#define VPIF_STATUS (0x002C)
47#define VPIF_STATUS_CLR (0x0030)
48#define VPIF_EMULATION_CTRL (0x0034)
49#define VPIF_REQ_SIZE (0x0038)
50
51#define VPIF_CH0_TOP_STRT_ADD_LUMA (0x0040)
52#define VPIF_CH0_BTM_STRT_ADD_LUMA (0x0044)
53#define VPIF_CH0_TOP_STRT_ADD_CHROMA (0x0048)
54#define VPIF_CH0_BTM_STRT_ADD_CHROMA (0x004c)
55#define VPIF_CH0_TOP_STRT_ADD_HANC (0x0050)
56#define VPIF_CH0_BTM_STRT_ADD_HANC (0x0054)
57#define VPIF_CH0_TOP_STRT_ADD_VANC (0x0058)
58#define VPIF_CH0_BTM_STRT_ADD_VANC (0x005c)
59#define VPIF_CH0_SP_CFG (0x0060)
60#define VPIF_CH0_IMG_ADD_OFST (0x0064)
61#define VPIF_CH0_HANC_ADD_OFST (0x0068)
62#define VPIF_CH0_H_CFG (0x006c)
63#define VPIF_CH0_V_CFG_00 (0x0070)
64#define VPIF_CH0_V_CFG_01 (0x0074)
65#define VPIF_CH0_V_CFG_02 (0x0078)
66#define VPIF_CH0_V_CFG_03 (0x007c)
67
68#define VPIF_CH1_TOP_STRT_ADD_LUMA (0x0080)
69#define VPIF_CH1_BTM_STRT_ADD_LUMA (0x0084)
70#define VPIF_CH1_TOP_STRT_ADD_CHROMA (0x0088)
71#define VPIF_CH1_BTM_STRT_ADD_CHROMA (0x008c)
72#define VPIF_CH1_TOP_STRT_ADD_HANC (0x0090)
73#define VPIF_CH1_BTM_STRT_ADD_HANC (0x0094)
74#define VPIF_CH1_TOP_STRT_ADD_VANC (0x0098)
75#define VPIF_CH1_BTM_STRT_ADD_VANC (0x009c)
76#define VPIF_CH1_SP_CFG (0x00a0)
77#define VPIF_CH1_IMG_ADD_OFST (0x00a4)
78#define VPIF_CH1_HANC_ADD_OFST (0x00a8)
79#define VPIF_CH1_H_CFG (0x00ac)
80#define VPIF_CH1_V_CFG_00 (0x00b0)
81#define VPIF_CH1_V_CFG_01 (0x00b4)
82#define VPIF_CH1_V_CFG_02 (0x00b8)
83#define VPIF_CH1_V_CFG_03 (0x00bc)
84
85#define VPIF_CH2_TOP_STRT_ADD_LUMA (0x00c0)
86#define VPIF_CH2_BTM_STRT_ADD_LUMA (0x00c4)
87#define VPIF_CH2_TOP_STRT_ADD_CHROMA (0x00c8)
88#define VPIF_CH2_BTM_STRT_ADD_CHROMA (0x00cc)
89#define VPIF_CH2_TOP_STRT_ADD_HANC (0x00d0)
90#define VPIF_CH2_BTM_STRT_ADD_HANC (0x00d4)
91#define VPIF_CH2_TOP_STRT_ADD_VANC (0x00d8)
92#define VPIF_CH2_BTM_STRT_ADD_VANC (0x00dc)
93#define VPIF_CH2_SP_CFG (0x00e0)
94#define VPIF_CH2_IMG_ADD_OFST (0x00e4)
95#define VPIF_CH2_HANC_ADD_OFST (0x00e8)
96#define VPIF_CH2_H_CFG (0x00ec)
97#define VPIF_CH2_V_CFG_00 (0x00f0)
98#define VPIF_CH2_V_CFG_01 (0x00f4)
99#define VPIF_CH2_V_CFG_02 (0x00f8)
100#define VPIF_CH2_V_CFG_03 (0x00fc)
101#define VPIF_CH2_HANC0_STRT (0x0100)
102#define VPIF_CH2_HANC0_SIZE (0x0104)
103#define VPIF_CH2_HANC1_STRT (0x0108)
104#define VPIF_CH2_HANC1_SIZE (0x010c)
105#define VPIF_CH2_VANC0_STRT (0x0110)
106#define VPIF_CH2_VANC0_SIZE (0x0114)
107#define VPIF_CH2_VANC1_STRT (0x0118)
108#define VPIF_CH2_VANC1_SIZE (0x011c)
109
110#define VPIF_CH3_TOP_STRT_ADD_LUMA (0x0140)
111#define VPIF_CH3_BTM_STRT_ADD_LUMA (0x0144)
112#define VPIF_CH3_TOP_STRT_ADD_CHROMA (0x0148)
113#define VPIF_CH3_BTM_STRT_ADD_CHROMA (0x014c)
114#define VPIF_CH3_TOP_STRT_ADD_HANC (0x0150)
115#define VPIF_CH3_BTM_STRT_ADD_HANC (0x0154)
116#define VPIF_CH3_TOP_STRT_ADD_VANC (0x0158)
117#define VPIF_CH3_BTM_STRT_ADD_VANC (0x015c)
118#define VPIF_CH3_SP_CFG (0x0160)
119#define VPIF_CH3_IMG_ADD_OFST (0x0164)
120#define VPIF_CH3_HANC_ADD_OFST (0x0168)
121#define VPIF_CH3_H_CFG (0x016c)
122#define VPIF_CH3_V_CFG_00 (0x0170)
123#define VPIF_CH3_V_CFG_01 (0x0174)
124#define VPIF_CH3_V_CFG_02 (0x0178)
125#define VPIF_CH3_V_CFG_03 (0x017c)
126#define VPIF_CH3_HANC0_STRT (0x0180)
127#define VPIF_CH3_HANC0_SIZE (0x0184)
128#define VPIF_CH3_HANC1_STRT (0x0188)
129#define VPIF_CH3_HANC1_SIZE (0x018c)
130#define VPIF_CH3_VANC0_STRT (0x0190)
131#define VPIF_CH3_VANC0_SIZE (0x0194)
132#define VPIF_CH3_VANC1_STRT (0x0198)
133#define VPIF_CH3_VANC1_SIZE (0x019c)
134
135#define VPIF_IODFT_CTRL (0x01c0)
136
137/* Functions for bit Manipulation */
138static inline void vpif_set_bit(u32 reg, u32 bit)
139{
140 regw((regr(reg)) | (0x01 << bit), reg);
141}
142
143static inline void vpif_clr_bit(u32 reg, u32 bit)
144{
145 regw(((regr(reg)) & ~(0x01 << bit)), reg);
146}
147
148/* Macro for Generating mask */
149#ifdef GENERATE_MASK
150#undef GENERATE_MASK
151#endif
152
153#define GENERATE_MASK(bits, pos) \
154 ((((0xFFFFFFFF) << (32 - bits)) >> (32 - bits)) << pos)
155
156/* Bit positions in the channel control registers */
157#define VPIF_CH_DATA_MODE_BIT (2)
158#define VPIF_CH_YC_MUX_BIT (3)
159#define VPIF_CH_SDR_FMT_BIT (4)
160#define VPIF_CH_HANC_EN_BIT (8)
161#define VPIF_CH_VANC_EN_BIT (9)
162
163#define VPIF_CAPTURE_CH_NIP (10)
164#define VPIF_DISPLAY_CH_NIP (11)
165
166#define VPIF_DISPLAY_PIX_EN_BIT (10)
167
168#define VPIF_CH_INPUT_FIELD_FRAME_BIT (12)
169
170#define VPIF_CH_FID_POLARITY_BIT (15)
171#define VPIF_CH_V_VALID_POLARITY_BIT (14)
172#define VPIF_CH_H_VALID_POLARITY_BIT (13)
173#define VPIF_CH_DATA_WIDTH_BIT (28)
174
175#define VPIF_CH_CLK_EDGE_CTRL_BIT (31)
176
177/* Mask various length */
178#define VPIF_CH_EAVSAV_MASK GENERATE_MASK(13, 0)
179#define VPIF_CH_LEN_MASK GENERATE_MASK(12, 0)
180#define VPIF_CH_WIDTH_MASK GENERATE_MASK(13, 0)
181#define VPIF_CH_LEN_SHIFT (16)
182
183/* VPIF masks for registers */
184#define VPIF_REQ_SIZE_MASK (0x1ff)
185
186/* bit posotion of interrupt vpif_ch_intr register */
187#define VPIF_INTEN_FRAME_CH0 (0x00000001)
188#define VPIF_INTEN_FRAME_CH1 (0x00000002)
189#define VPIF_INTEN_FRAME_CH2 (0x00000004)
190#define VPIF_INTEN_FRAME_CH3 (0x00000008)
191
192/* bit position of clock and channel enable in vpif_chn_ctrl register */
193
194#define VPIF_CH0_CLK_EN (0x00000002)
195#define VPIF_CH0_EN (0x00000001)
196#define VPIF_CH1_CLK_EN (0x00000002)
197#define VPIF_CH1_EN (0x00000001)
198#define VPIF_CH2_CLK_EN (0x00000002)
199#define VPIF_CH2_EN (0x00000001)
200#define VPIF_CH3_CLK_EN (0x00000002)
201#define VPIF_CH3_EN (0x00000001)
202#define VPIF_CH_CLK_EN (0x00000002)
203#define VPIF_CH_EN (0x00000001)
204
205#define VPIF_INT_TOP (0x00)
206#define VPIF_INT_BOTTOM (0x01)
207#define VPIF_INT_BOTH (0x02)
208
209#define VPIF_CH0_INT_CTRL_SHIFT (6)
210#define VPIF_CH1_INT_CTRL_SHIFT (6)
211#define VPIF_CH2_INT_CTRL_SHIFT (6)
212#define VPIF_CH3_INT_CTRL_SHIFT (6)
213#define VPIF_CH_INT_CTRL_SHIFT (6)
214
215/* enabled interrupt on both the fields on vpid_ch0_ctrl register */
216#define channel0_intr_assert() (regw((regr(VPIF_CH0_CTRL)|\
217 (VPIF_INT_BOTH << VPIF_CH0_INT_CTRL_SHIFT)), VPIF_CH0_CTRL))
218
219/* enabled interrupt on both the fields on vpid_ch1_ctrl register */
220#define channel1_intr_assert() (regw((regr(VPIF_CH1_CTRL)|\
221 (VPIF_INT_BOTH << VPIF_CH1_INT_CTRL_SHIFT)), VPIF_CH1_CTRL))
222
223/* enabled interrupt on both the fields on vpid_ch0_ctrl register */
224#define channel2_intr_assert() (regw((regr(VPIF_CH2_CTRL)|\
225 (VPIF_INT_BOTH << VPIF_CH2_INT_CTRL_SHIFT)), VPIF_CH2_CTRL))
226
227/* enabled interrupt on both the fields on vpid_ch1_ctrl register */
228#define channel3_intr_assert() (regw((regr(VPIF_CH3_CTRL)|\
229 (VPIF_INT_BOTH << VPIF_CH3_INT_CTRL_SHIFT)), VPIF_CH3_CTRL))
230
231#define VPIF_CH_FID_MASK (0x20)
232#define VPIF_CH_FID_SHIFT (5)
233
234#define VPIF_NTSC_VBI_START_FIELD0 (1)
235#define VPIF_NTSC_VBI_START_FIELD1 (263)
236#define VPIF_PAL_VBI_START_FIELD0 (624)
237#define VPIF_PAL_VBI_START_FIELD1 (311)
238
239#define VPIF_NTSC_HBI_START_FIELD0 (1)
240#define VPIF_NTSC_HBI_START_FIELD1 (263)
241#define VPIF_PAL_HBI_START_FIELD0 (624)
242#define VPIF_PAL_HBI_START_FIELD1 (311)
243
244#define VPIF_NTSC_VBI_COUNT_FIELD0 (20)
245#define VPIF_NTSC_VBI_COUNT_FIELD1 (19)
246#define VPIF_PAL_VBI_COUNT_FIELD0 (24)
247#define VPIF_PAL_VBI_COUNT_FIELD1 (25)
248
249#define VPIF_NTSC_HBI_COUNT_FIELD0 (263)
250#define VPIF_NTSC_HBI_COUNT_FIELD1 (262)
251#define VPIF_PAL_HBI_COUNT_FIELD0 (312)
252#define VPIF_PAL_HBI_COUNT_FIELD1 (313)
253
254#define VPIF_NTSC_VBI_SAMPLES_PER_LINE (720)
255#define VPIF_PAL_VBI_SAMPLES_PER_LINE (720)
256#define VPIF_NTSC_HBI_SAMPLES_PER_LINE (268)
257#define VPIF_PAL_HBI_SAMPLES_PER_LINE (280)
258
259#define VPIF_CH_VANC_EN (0x20)
260#define VPIF_DMA_REQ_SIZE (0x080)
261#define VPIF_EMULATION_DISABLE (0x01)
262
263extern u8 irq_vpif_capture_channel[VPIF_NUM_CHANNELS];
264
265/* inline function to enable/disable channel0 */
266static inline void enable_channel0(int enable)
267{
268 if (enable)
269 regw((regr(VPIF_CH0_CTRL) | (VPIF_CH0_EN)), VPIF_CH0_CTRL);
270 else
271 regw((regr(VPIF_CH0_CTRL) & (~VPIF_CH0_EN)), VPIF_CH0_CTRL);
272}
273
274/* inline function to enable/disable channel1 */
275static inline void enable_channel1(int enable)
276{
277 if (enable)
278 regw((regr(VPIF_CH1_CTRL) | (VPIF_CH1_EN)), VPIF_CH1_CTRL);
279 else
280 regw((regr(VPIF_CH1_CTRL) & (~VPIF_CH1_EN)), VPIF_CH1_CTRL);
281}
282
283/* inline function to enable interrupt for channel0 */
284static inline void channel0_intr_enable(int enable)
285{
286 unsigned long flags;
287
288 spin_lock_irqsave(&vpif_lock, flags);
289
290 if (enable) {
291 regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
292 regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
293
294 regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH0), VPIF_INTEN);
295 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0),
296 VPIF_INTEN_SET);
297 } else {
298 regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH0)), VPIF_INTEN);
299 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH0),
300 VPIF_INTEN_SET);
301 }
302 spin_unlock_irqrestore(&vpif_lock, flags);
303}
304
305/* inline function to enable interrupt for channel1 */
306static inline void channel1_intr_enable(int enable)
307{
308 unsigned long flags;
309
310 spin_lock_irqsave(&vpif_lock, flags);
311
312 if (enable) {
313 regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
314 regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
315
316 regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH1), VPIF_INTEN);
317 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1),
318 VPIF_INTEN_SET);
319 } else {
320 regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH1)), VPIF_INTEN);
321 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH1),
322 VPIF_INTEN_SET);
323 }
324 spin_unlock_irqrestore(&vpif_lock, flags);
325}
326
327/* inline function to set buffer addresses in case of Y/C non mux mode */
328static inline void ch0_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma,
329 unsigned long btm_strt_luma,
330 unsigned long top_strt_chroma,
331 unsigned long btm_strt_chroma)
332{
333 regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA);
334 regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA);
335 regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA);
336 regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA);
337}
338
339/* inline function to set buffer addresses in VPIF registers for video data */
340static inline void ch0_set_videobuf_addr(unsigned long top_strt_luma,
341 unsigned long btm_strt_luma,
342 unsigned long top_strt_chroma,
343 unsigned long btm_strt_chroma)
344{
345 regw(top_strt_luma, VPIF_CH0_TOP_STRT_ADD_LUMA);
346 regw(btm_strt_luma, VPIF_CH0_BTM_STRT_ADD_LUMA);
347 regw(top_strt_chroma, VPIF_CH0_TOP_STRT_ADD_CHROMA);
348 regw(btm_strt_chroma, VPIF_CH0_BTM_STRT_ADD_CHROMA);
349}
350
351static inline void ch1_set_videobuf_addr(unsigned long top_strt_luma,
352 unsigned long btm_strt_luma,
353 unsigned long top_strt_chroma,
354 unsigned long btm_strt_chroma)
355{
356
357 regw(top_strt_luma, VPIF_CH1_TOP_STRT_ADD_LUMA);
358 regw(btm_strt_luma, VPIF_CH1_BTM_STRT_ADD_LUMA);
359 regw(top_strt_chroma, VPIF_CH1_TOP_STRT_ADD_CHROMA);
360 regw(btm_strt_chroma, VPIF_CH1_BTM_STRT_ADD_CHROMA);
361}
362
363static inline void ch0_set_vbi_addr(unsigned long top_vbi,
364 unsigned long btm_vbi, unsigned long a, unsigned long b)
365{
366 regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_VANC);
367 regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_VANC);
368}
369
370static inline void ch0_set_hbi_addr(unsigned long top_vbi,
371 unsigned long btm_vbi, unsigned long a, unsigned long b)
372{
373 regw(top_vbi, VPIF_CH0_TOP_STRT_ADD_HANC);
374 regw(btm_vbi, VPIF_CH0_BTM_STRT_ADD_HANC);
375}
376
377static inline void ch1_set_vbi_addr(unsigned long top_vbi,
378 unsigned long btm_vbi, unsigned long a, unsigned long b)
379{
380 regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_VANC);
381 regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_VANC);
382}
383
384static inline void ch1_set_hbi_addr(unsigned long top_vbi,
385 unsigned long btm_vbi, unsigned long a, unsigned long b)
386{
387 regw(top_vbi, VPIF_CH1_TOP_STRT_ADD_HANC);
388 regw(btm_vbi, VPIF_CH1_BTM_STRT_ADD_HANC);
389}
390
391/* Inline function to enable raw vbi in the given channel */
392static inline void disable_raw_feature(u8 channel_id, u8 index)
393{
394 u32 ctrl_reg;
395 if (0 == channel_id)
396 ctrl_reg = VPIF_CH0_CTRL;
397 else
398 ctrl_reg = VPIF_CH1_CTRL;
399
400 if (1 == index)
401 vpif_clr_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT);
402 else
403 vpif_clr_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT);
404}
405
406static inline void enable_raw_feature(u8 channel_id, u8 index)
407{
408 u32 ctrl_reg;
409 if (0 == channel_id)
410 ctrl_reg = VPIF_CH0_CTRL;
411 else
412 ctrl_reg = VPIF_CH1_CTRL;
413
414 if (1 == index)
415 vpif_set_bit(ctrl_reg, VPIF_CH_VANC_EN_BIT);
416 else
417 vpif_set_bit(ctrl_reg, VPIF_CH_HANC_EN_BIT);
418}
419
420/* inline function to enable/disable channel2 */
421static inline void enable_channel2(int enable)
422{
423 if (enable) {
424 regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL);
425 regw((regr(VPIF_CH2_CTRL) | (VPIF_CH2_EN)), VPIF_CH2_CTRL);
426 } else {
427 regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_CLK_EN)), VPIF_CH2_CTRL);
428 regw((regr(VPIF_CH2_CTRL) & (~VPIF_CH2_EN)), VPIF_CH2_CTRL);
429 }
430}
431
432/* inline function to enable/disable channel3 */
433static inline void enable_channel3(int enable)
434{
435 if (enable) {
436 regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL);
437 regw((regr(VPIF_CH3_CTRL) | (VPIF_CH3_EN)), VPIF_CH3_CTRL);
438 } else {
439 regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_CLK_EN)), VPIF_CH3_CTRL);
440 regw((regr(VPIF_CH3_CTRL) & (~VPIF_CH3_EN)), VPIF_CH3_CTRL);
441 }
442}
443
444/* inline function to enable interrupt for channel2 */
445static inline void channel2_intr_enable(int enable)
446{
447 unsigned long flags;
448
449 spin_lock_irqsave(&vpif_lock, flags);
450
451 if (enable) {
452 regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
453 regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
454 regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH2), VPIF_INTEN);
455 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2),
456 VPIF_INTEN_SET);
457 } else {
458 regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH2)), VPIF_INTEN);
459 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH2),
460 VPIF_INTEN_SET);
461 }
462 spin_unlock_irqrestore(&vpif_lock, flags);
463}
464
465/* inline function to enable interrupt for channel3 */
466static inline void channel3_intr_enable(int enable)
467{
468 unsigned long flags;
469
470 spin_lock_irqsave(&vpif_lock, flags);
471
472 if (enable) {
473 regw((regr(VPIF_INTEN) | 0x10), VPIF_INTEN);
474 regw((regr(VPIF_INTEN_SET) | 0x10), VPIF_INTEN_SET);
475
476 regw((regr(VPIF_INTEN) | VPIF_INTEN_FRAME_CH3), VPIF_INTEN);
477 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3),
478 VPIF_INTEN_SET);
479 } else {
480 regw((regr(VPIF_INTEN) & (~VPIF_INTEN_FRAME_CH3)), VPIF_INTEN);
481 regw((regr(VPIF_INTEN_SET) | VPIF_INTEN_FRAME_CH3),
482 VPIF_INTEN_SET);
483 }
484 spin_unlock_irqrestore(&vpif_lock, flags);
485}
486
487/* inline function to enable raw vbi data for channel2 */
488static inline void channel2_raw_enable(int enable, u8 index)
489{
490 u32 mask;
491
492 if (1 == index)
493 mask = VPIF_CH_VANC_EN_BIT;
494 else
495 mask = VPIF_CH_HANC_EN_BIT;
496
497 if (enable)
498 vpif_set_bit(VPIF_CH2_CTRL, mask);
499 else
500 vpif_clr_bit(VPIF_CH2_CTRL, mask);
501}
502
503/* inline function to enable raw vbi data for channel3*/
504static inline void channel3_raw_enable(int enable, u8 index)
505{
506 u32 mask;
507
508 if (1 == index)
509 mask = VPIF_CH_VANC_EN_BIT;
510 else
511 mask = VPIF_CH_HANC_EN_BIT;
512
513 if (enable)
514 vpif_set_bit(VPIF_CH3_CTRL, mask);
515 else
516 vpif_clr_bit(VPIF_CH3_CTRL, mask);
517}
518
519/* inline function to set buffer addresses in case of Y/C non mux mode */
520static inline void ch2_set_videobuf_addr_yc_nmux(unsigned long top_strt_luma,
521 unsigned long btm_strt_luma,
522 unsigned long top_strt_chroma,
523 unsigned long btm_strt_chroma)
524{
525 regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA);
526 regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA);
527 regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA);
528 regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA);
529}
530
531/* inline function to set buffer addresses in VPIF registers for video data */
532static inline void ch2_set_videobuf_addr(unsigned long top_strt_luma,
533 unsigned long btm_strt_luma,
534 unsigned long top_strt_chroma,
535 unsigned long btm_strt_chroma)
536{
537 regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_LUMA);
538 regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_LUMA);
539 regw(top_strt_chroma, VPIF_CH2_TOP_STRT_ADD_CHROMA);
540 regw(btm_strt_chroma, VPIF_CH2_BTM_STRT_ADD_CHROMA);
541}
542
543static inline void ch3_set_videobuf_addr(unsigned long top_strt_luma,
544 unsigned long btm_strt_luma,
545 unsigned long top_strt_chroma,
546 unsigned long btm_strt_chroma)
547{
548 regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_LUMA);
549 regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_LUMA);
550 regw(top_strt_chroma, VPIF_CH3_TOP_STRT_ADD_CHROMA);
551 regw(btm_strt_chroma, VPIF_CH3_BTM_STRT_ADD_CHROMA);
552}
553
554/* inline function to set buffer addresses in VPIF registers for vbi data */
555static inline void ch2_set_vbi_addr(unsigned long top_strt_luma,
556 unsigned long btm_strt_luma,
557 unsigned long top_strt_chroma,
558 unsigned long btm_strt_chroma)
559{
560 regw(top_strt_luma, VPIF_CH2_TOP_STRT_ADD_VANC);
561 regw(btm_strt_luma, VPIF_CH2_BTM_STRT_ADD_VANC);
562}
563
564static inline void ch3_set_vbi_addr(unsigned long top_strt_luma,
565 unsigned long btm_strt_luma,
566 unsigned long top_strt_chroma,
567 unsigned long btm_strt_chroma)
568{
569 regw(top_strt_luma, VPIF_CH3_TOP_STRT_ADD_VANC);
570 regw(btm_strt_luma, VPIF_CH3_BTM_STRT_ADD_VANC);
571}
572
573#define VPIF_MAX_NAME (30)
574
575/* This structure will store size parameters as per the mode selected by user */
576struct vpif_channel_config_params {
577 char name[VPIF_MAX_NAME]; /* Name of the mode */
578 u16 width; /* Indicates width of the image */
579 u16 height; /* Indicates height of the image */
580 u8 frm_fmt; /* Interlaced (0) or progressive (1) */
581 u8 ycmux_mode; /* This mode requires one (0) or two (1)
582 channels */
583 u16 eav2sav; /* length of eav 2 sav */
584 u16 sav2eav; /* length of sav 2 eav */
585 u16 l1, l3, l5, l7, l9, l11; /* Other parameter configurations */
586 u16 vsize; /* Vertical size of the image */
587 u8 capture_format; /* Indicates whether capture format
588 * is in BT or in CCD/CMOS */
589 u8 vbi_supported; /* Indicates whether this mode
590 * supports capturing vbi or not */
591 u8 hd_sd; /* HDTV (1) or SDTV (0) format */
592 v4l2_std_id stdid; /* SDTV format */
593 u32 dv_preset; /* HDTV format */
594};
595
596extern const unsigned int vpif_ch_params_count;
597extern const struct vpif_channel_config_params ch_params[];
598
599struct vpif_video_params;
600struct vpif_params;
601struct vpif_vbi_params;
602
603int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id);
604void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,
605 u8 channel_id);
606int vpif_channel_getfid(u8 channel_id);
607
608enum data_size {
609 _8BITS = 0,
610 _10BITS,
611 _12BITS,
612};
613
614/* Structure for vpif parameters for raw vbi data */
615struct vpif_vbi_params {
616 __u32 hstart0; /* Horizontal start of raw vbi data for first field */
617 __u32 vstart0; /* Vertical start of raw vbi data for first field */
618 __u32 hsize0; /* Horizontal size of raw vbi data for first field */
619 __u32 vsize0; /* Vertical size of raw vbi data for first field */
620 __u32 hstart1; /* Horizontal start of raw vbi data for second field */
621 __u32 vstart1; /* Vertical start of raw vbi data for second field */
622 __u32 hsize1; /* Horizontal size of raw vbi data for second field */
623 __u32 vsize1; /* Vertical size of raw vbi data for second field */
624};
625
626/* structure for vpif parameters */
627struct vpif_video_params {
628 __u8 storage_mode; /* Indicates field or frame mode */
629 unsigned long hpitch;
630 v4l2_std_id stdid;
631};
632
633struct vpif_params {
634 struct vpif_interface iface;
635 struct vpif_video_params video_params;
636 struct vpif_channel_config_params std_info;
637 union param {
638 struct vpif_vbi_params vbi_params;
639 enum data_size data_sz;
640 } params;
641};
642
643#endif /* End of #ifndef VPIF_H */
644
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
new file mode 100644
index 00000000000..49e4deb5004
--- /dev/null
+++ b/drivers/media/video/davinci/vpif_capture.c
@@ -0,0 +1,2412 @@
1/*
2 * Copyright (C) 2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * TODO : add support for VBI & HBI data service
19 * add static buffer allocation
20 */
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/fs.h>
26#include <linux/mm.h>
27#include <linux/interrupt.h>
28#include <linux/workqueue.h>
29#include <linux/string.h>
30#include <linux/videodev2.h>
31#include <linux/wait.h>
32#include <linux/time.h>
33#include <linux/i2c.h>
34#include <linux/platform_device.h>
35#include <linux/io.h>
36#include <linux/slab.h>
37#include <media/v4l2-device.h>
38#include <media/v4l2-ioctl.h>
39#include <media/v4l2-chip-ident.h>
40
41#include "vpif_capture.h"
42#include "vpif.h"
43
44MODULE_DESCRIPTION("TI DaVinci VPIF Capture driver");
45MODULE_LICENSE("GPL");
46MODULE_VERSION(VPIF_CAPTURE_VERSION);
47
48#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg)
49#define vpif_dbg(level, debug, fmt, arg...) \
50 v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
51
52static int debug = 1;
53static u32 ch0_numbuffers = 3;
54static u32 ch1_numbuffers = 3;
55static u32 ch0_bufsize = 1920 * 1080 * 2;
56static u32 ch1_bufsize = 720 * 576 * 2;
57
58module_param(debug, int, 0644);
59module_param(ch0_numbuffers, uint, S_IRUGO);
60module_param(ch1_numbuffers, uint, S_IRUGO);
61module_param(ch0_bufsize, uint, S_IRUGO);
62module_param(ch1_bufsize, uint, S_IRUGO);
63
64MODULE_PARM_DESC(debug, "Debug level 0-1");
65MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)");
66MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)");
67MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)");
68MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)");
69
70static struct vpif_config_params config_params = {
71 .min_numbuffers = 3,
72 .numbuffers[0] = 3,
73 .numbuffers[1] = 3,
74 .min_bufsize[0] = 720 * 480 * 2,
75 .min_bufsize[1] = 720 * 480 * 2,
76 .channel_bufsize[0] = 1920 * 1080 * 2,
77 .channel_bufsize[1] = 720 * 576 * 2,
78};
79
80/* global variables */
81static struct vpif_device vpif_obj = { {NULL} };
82static struct device *vpif_dev;
83
84/**
85 * vpif_uservirt_to_phys : translate user/virtual address to phy address
86 * @virtp: user/virtual address
87 *
88 * This inline function is used to convert user space virtual address to
89 * physical address.
90 */
91static inline u32 vpif_uservirt_to_phys(u32 virtp)
92{
93 unsigned long physp = 0;
94 struct mm_struct *mm = current->mm;
95 struct vm_area_struct *vma;
96
97 vma = find_vma(mm, virtp);
98
99 /* For kernel direct-mapped memory, take the easy way */
100 if (virtp >= PAGE_OFFSET)
101 physp = virt_to_phys((void *)virtp);
102 else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff))
103 /**
104 * this will catch, kernel-allocated, mmaped-to-usermode
105 * addresses
106 */
107 physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
108 else {
109 /* otherwise, use get_user_pages() for general userland pages */
110 int res, nr_pages = 1;
111 struct page *pages;
112
113 down_read(&current->mm->mmap_sem);
114
115 res = get_user_pages(current, current->mm,
116 virtp, nr_pages, 1, 0, &pages, NULL);
117 up_read(&current->mm->mmap_sem);
118
119 if (res == nr_pages)
120 physp = __pa(page_address(&pages[0]) +
121 (virtp & ~PAGE_MASK));
122 else {
123 vpif_err("get_user_pages failed\n");
124 return 0;
125 }
126 }
127 return physp;
128}
129
130/**
131 * buffer_prepare : callback function for buffer prepare
132 * @q : buffer queue ptr
133 * @vb: ptr to video buffer
134 * @field: field info
135 *
136 * This is the callback function for buffer prepare when videobuf_qbuf()
137 * function is called. The buffer is prepared and user space virtual address
138 * or user address is converted into physical address
139 */
140static int vpif_buffer_prepare(struct videobuf_queue *q,
141 struct videobuf_buffer *vb,
142 enum v4l2_field field)
143{
144 /* Get the file handle object and channel object */
145 struct vpif_fh *fh = q->priv_data;
146 struct channel_obj *ch = fh->channel;
147 struct common_obj *common;
148 unsigned long addr;
149
150
151 vpif_dbg(2, debug, "vpif_buffer_prepare\n");
152
153 common = &ch->common[VPIF_VIDEO_INDEX];
154
155 /* If buffer is not initialized, initialize it */
156 if (VIDEOBUF_NEEDS_INIT == vb->state) {
157 vb->width = common->width;
158 vb->height = common->height;
159 vb->size = vb->width * vb->height;
160 vb->field = field;
161 }
162 vb->state = VIDEOBUF_PREPARED;
163 /**
164 * if user pointer memory mechanism is used, get the physical
165 * address of the buffer
166 */
167 if (V4L2_MEMORY_USERPTR == common->memory) {
168 if (0 == vb->baddr) {
169 vpif_dbg(1, debug, "buffer address is 0\n");
170 return -EINVAL;
171
172 }
173 vb->boff = vpif_uservirt_to_phys(vb->baddr);
174 if (!IS_ALIGNED(vb->boff, 8))
175 goto exit;
176 }
177
178 addr = vb->boff;
179 if (q->streaming) {
180 if (!IS_ALIGNED((addr + common->ytop_off), 8) ||
181 !IS_ALIGNED((addr + common->ybtm_off), 8) ||
182 !IS_ALIGNED((addr + common->ctop_off), 8) ||
183 !IS_ALIGNED((addr + common->cbtm_off), 8))
184 goto exit;
185 }
186 return 0;
187exit:
188 vpif_dbg(1, debug, "buffer_prepare:offset is not aligned to 8 bytes\n");
189 return -EINVAL;
190}
191
192/**
193 * vpif_buffer_setup : Callback function for buffer setup.
194 * @q: buffer queue ptr
195 * @count: number of buffers
196 * @size: size of the buffer
197 *
198 * This callback function is called when reqbuf() is called to adjust
199 * the buffer count and buffer size
200 */
201static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count,
202 unsigned int *size)
203{
204 /* Get the file handle object and channel object */
205 struct vpif_fh *fh = q->priv_data;
206 struct channel_obj *ch = fh->channel;
207 struct common_obj *common;
208
209 common = &ch->common[VPIF_VIDEO_INDEX];
210
211 vpif_dbg(2, debug, "vpif_buffer_setup\n");
212
213 /* If memory type is not mmap, return */
214 if (V4L2_MEMORY_MMAP != common->memory)
215 return 0;
216
217 /* Calculate the size of the buffer */
218 *size = config_params.channel_bufsize[ch->channel_id];
219
220 if (*count < config_params.min_numbuffers)
221 *count = config_params.min_numbuffers;
222 return 0;
223}
224
225/**
226 * vpif_buffer_queue : Callback function to add buffer to DMA queue
227 * @q: ptr to videobuf_queue
228 * @vb: ptr to videobuf_buffer
229 */
230static void vpif_buffer_queue(struct videobuf_queue *q,
231 struct videobuf_buffer *vb)
232{
233 /* Get the file handle object and channel object */
234 struct vpif_fh *fh = q->priv_data;
235 struct channel_obj *ch = fh->channel;
236 struct common_obj *common;
237
238 common = &ch->common[VPIF_VIDEO_INDEX];
239
240 vpif_dbg(2, debug, "vpif_buffer_queue\n");
241
242 /* add the buffer to the DMA queue */
243 list_add_tail(&vb->queue, &common->dma_queue);
244 /* Change state of the buffer */
245 vb->state = VIDEOBUF_QUEUED;
246}
247
248/**
249 * vpif_buffer_release : Callback function to free buffer
250 * @q: buffer queue ptr
251 * @vb: ptr to video buffer
252 *
253 * This function is called from the videobuf layer to free memory
254 * allocated to the buffers
255 */
256static void vpif_buffer_release(struct videobuf_queue *q,
257 struct videobuf_buffer *vb)
258{
259 /* Get the file handle object and channel object */
260 struct vpif_fh *fh = q->priv_data;
261 struct channel_obj *ch = fh->channel;
262 struct common_obj *common;
263
264 common = &ch->common[VPIF_VIDEO_INDEX];
265
266 videobuf_dma_contig_free(q, vb);
267 vb->state = VIDEOBUF_NEEDS_INIT;
268}
269
270static struct videobuf_queue_ops video_qops = {
271 .buf_setup = vpif_buffer_setup,
272 .buf_prepare = vpif_buffer_prepare,
273 .buf_queue = vpif_buffer_queue,
274 .buf_release = vpif_buffer_release,
275};
276
277static u8 channel_first_int[VPIF_NUMBER_OF_OBJECTS][2] =
278 { {1, 1} };
279
280/**
281 * vpif_process_buffer_complete: process a completed buffer
282 * @common: ptr to common channel object
283 *
284 * This function time stamp the buffer and mark it as DONE. It also
285 * wake up any process waiting on the QUEUE and set the next buffer
286 * as current
287 */
288static void vpif_process_buffer_complete(struct common_obj *common)
289{
290 do_gettimeofday(&common->cur_frm->ts);
291 common->cur_frm->state = VIDEOBUF_DONE;
292 wake_up_interruptible(&common->cur_frm->done);
293 /* Make curFrm pointing to nextFrm */
294 common->cur_frm = common->next_frm;
295}
296
297/**
298 * vpif_schedule_next_buffer: set next buffer address for capture
299 * @common : ptr to common channel object
300 *
301 * This function will get next buffer from the dma queue and
302 * set the buffer address in the vpif register for capture.
303 * the buffer is marked active
304 */
305static void vpif_schedule_next_buffer(struct common_obj *common)
306{
307 unsigned long addr = 0;
308
309 common->next_frm = list_entry(common->dma_queue.next,
310 struct videobuf_buffer, queue);
311 /* Remove that buffer from the buffer queue */
312 list_del(&common->next_frm->queue);
313 common->next_frm->state = VIDEOBUF_ACTIVE;
314 if (V4L2_MEMORY_USERPTR == common->memory)
315 addr = common->next_frm->boff;
316 else
317 addr = videobuf_to_dma_contig(common->next_frm);
318
319 /* Set top and bottom field addresses in VPIF registers */
320 common->set_addr(addr + common->ytop_off,
321 addr + common->ybtm_off,
322 addr + common->ctop_off,
323 addr + common->cbtm_off);
324}
325
326/**
327 * vpif_channel_isr : ISR handler for vpif capture
328 * @irq: irq number
329 * @dev_id: dev_id ptr
330 *
331 * It changes status of the captured buffer, takes next buffer from the queue
332 * and sets its address in VPIF registers
333 */
334static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
335{
336 struct vpif_device *dev = &vpif_obj;
337 struct common_obj *common;
338 struct channel_obj *ch;
339 enum v4l2_field field;
340 int channel_id = 0;
341 int fid = -1, i;
342
343 channel_id = *(int *)(dev_id);
344 ch = dev->dev[channel_id];
345
346 field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field;
347
348 for (i = 0; i < VPIF_NUMBER_OF_OBJECTS; i++) {
349 common = &ch->common[i];
350 /* skip If streaming is not started in this channel */
351 if (0 == common->started)
352 continue;
353
354 /* Check the field format */
355 if (1 == ch->vpifparams.std_info.frm_fmt) {
356 /* Progressive mode */
357 if (list_empty(&common->dma_queue))
358 continue;
359
360 if (!channel_first_int[i][channel_id])
361 vpif_process_buffer_complete(common);
362
363 channel_first_int[i][channel_id] = 0;
364
365 vpif_schedule_next_buffer(common);
366
367
368 channel_first_int[i][channel_id] = 0;
369 } else {
370 /**
371 * Interlaced mode. If it is first interrupt, ignore
372 * it
373 */
374 if (channel_first_int[i][channel_id]) {
375 channel_first_int[i][channel_id] = 0;
376 continue;
377 }
378 if (0 == i) {
379 ch->field_id ^= 1;
380 /* Get field id from VPIF registers */
381 fid = vpif_channel_getfid(ch->channel_id);
382 if (fid != ch->field_id) {
383 /**
384 * If field id does not match stored
385 * field id, make them in sync
386 */
387 if (0 == fid)
388 ch->field_id = fid;
389 return IRQ_HANDLED;
390 }
391 }
392 /* device field id and local field id are in sync */
393 if (0 == fid) {
394 /* this is even field */
395 if (common->cur_frm == common->next_frm)
396 continue;
397
398 /* mark the current buffer as done */
399 vpif_process_buffer_complete(common);
400 } else if (1 == fid) {
401 /* odd field */
402 if (list_empty(&common->dma_queue) ||
403 (common->cur_frm != common->next_frm))
404 continue;
405
406 vpif_schedule_next_buffer(common);
407 }
408 }
409 }
410 return IRQ_HANDLED;
411}
412
413/**
414 * vpif_update_std_info() - update standard related info
415 * @ch: ptr to channel object
416 *
417 * For a given standard selected by application, update values
418 * in the device data structures
419 */
420static int vpif_update_std_info(struct channel_obj *ch)
421{
422 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
423 struct vpif_params *vpifparams = &ch->vpifparams;
424 const struct vpif_channel_config_params *config;
425 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
426 struct video_obj *vid_ch = &ch->video;
427 int index;
428
429 vpif_dbg(2, debug, "vpif_update_std_info\n");
430
431 for (index = 0; index < vpif_ch_params_count; index++) {
432 config = &ch_params[index];
433 if (config->hd_sd == 0) {
434 vpif_dbg(2, debug, "SD format\n");
435 if (config->stdid & vid_ch->stdid) {
436 memcpy(std_info, config, sizeof(*config));
437 break;
438 }
439 } else {
440 vpif_dbg(2, debug, "HD format\n");
441 if (config->dv_preset == vid_ch->dv_preset) {
442 memcpy(std_info, config, sizeof(*config));
443 break;
444 }
445 }
446 }
447
448 /* standard not found */
449 if (index == vpif_ch_params_count)
450 return -EINVAL;
451
452 common->fmt.fmt.pix.width = std_info->width;
453 common->width = std_info->width;
454 common->fmt.fmt.pix.height = std_info->height;
455 common->height = std_info->height;
456 common->fmt.fmt.pix.bytesperline = std_info->width;
457 vpifparams->video_params.hpitch = std_info->width;
458 vpifparams->video_params.storage_mode = std_info->frm_fmt;
459
460 return 0;
461}
462
463/**
464 * vpif_calculate_offsets : This function calculates buffers offsets
465 * @ch : ptr to channel object
466 *
467 * This function calculates buffer offsets for Y and C in the top and
468 * bottom field
469 */
470static void vpif_calculate_offsets(struct channel_obj *ch)
471{
472 unsigned int hpitch, vpitch, sizeimage;
473 struct video_obj *vid_ch = &(ch->video);
474 struct vpif_params *vpifparams = &ch->vpifparams;
475 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
476 enum v4l2_field field = common->fmt.fmt.pix.field;
477
478 vpif_dbg(2, debug, "vpif_calculate_offsets\n");
479
480 if (V4L2_FIELD_ANY == field) {
481 if (vpifparams->std_info.frm_fmt)
482 vid_ch->buf_field = V4L2_FIELD_NONE;
483 else
484 vid_ch->buf_field = V4L2_FIELD_INTERLACED;
485 } else
486 vid_ch->buf_field = common->fmt.fmt.pix.field;
487
488 if (V4L2_MEMORY_USERPTR == common->memory)
489 sizeimage = common->fmt.fmt.pix.sizeimage;
490 else
491 sizeimage = config_params.channel_bufsize[ch->channel_id];
492
493 hpitch = common->fmt.fmt.pix.bytesperline;
494 vpitch = sizeimage / (hpitch * 2);
495
496 if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||
497 (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) {
498 /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */
499 common->ytop_off = 0;
500 common->ybtm_off = hpitch;
501 common->ctop_off = sizeimage / 2;
502 common->cbtm_off = sizeimage / 2 + hpitch;
503 } else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) {
504 /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */
505 common->ytop_off = 0;
506 common->ybtm_off = sizeimage / 4;
507 common->ctop_off = sizeimage / 2;
508 common->cbtm_off = common->ctop_off + sizeimage / 4;
509 } else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) {
510 /* Calculate offsets for Y top, Y Bottom, C top and C Bottom */
511 common->ybtm_off = 0;
512 common->ytop_off = sizeimage / 4;
513 common->cbtm_off = sizeimage / 2;
514 common->ctop_off = common->cbtm_off + sizeimage / 4;
515 }
516 if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||
517 (V4L2_FIELD_INTERLACED == vid_ch->buf_field))
518 vpifparams->video_params.storage_mode = 1;
519 else
520 vpifparams->video_params.storage_mode = 0;
521
522 if (1 == vpifparams->std_info.frm_fmt)
523 vpifparams->video_params.hpitch =
524 common->fmt.fmt.pix.bytesperline;
525 else {
526 if ((field == V4L2_FIELD_ANY)
527 || (field == V4L2_FIELD_INTERLACED))
528 vpifparams->video_params.hpitch =
529 common->fmt.fmt.pix.bytesperline * 2;
530 else
531 vpifparams->video_params.hpitch =
532 common->fmt.fmt.pix.bytesperline;
533 }
534
535 ch->vpifparams.video_params.stdid = vpifparams->std_info.stdid;
536}
537
538/**
539 * vpif_config_format: configure default frame format in the device
540 * ch : ptr to channel object
541 */
542static void vpif_config_format(struct channel_obj *ch)
543{
544 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
545
546 vpif_dbg(2, debug, "vpif_config_format\n");
547
548 common->fmt.fmt.pix.field = V4L2_FIELD_ANY;
549 if (config_params.numbuffers[ch->channel_id] == 0)
550 common->memory = V4L2_MEMORY_USERPTR;
551 else
552 common->memory = V4L2_MEMORY_MMAP;
553
554 common->fmt.fmt.pix.sizeimage
555 = config_params.channel_bufsize[ch->channel_id];
556
557 if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
558 common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
559 else
560 common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
561 common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
562}
563
564/**
565 * vpif_get_default_field() - Get default field type based on interface
566 * @vpif_params - ptr to vpif params
567 */
568static inline enum v4l2_field vpif_get_default_field(
569 struct vpif_interface *iface)
570{
571 return (iface->if_type == VPIF_IF_RAW_BAYER) ? V4L2_FIELD_NONE :
572 V4L2_FIELD_INTERLACED;
573}
574
575/**
576 * vpif_check_format() - check given pixel format for compatibility
577 * @ch - channel ptr
578 * @pixfmt - Given pixel format
579 * @update - update the values as per hardware requirement
580 *
581 * Check the application pixel format for S_FMT and update the input
582 * values as per hardware limits for TRY_FMT. The default pixel and
583 * field format is selected based on interface type.
584 */
585static int vpif_check_format(struct channel_obj *ch,
586 struct v4l2_pix_format *pixfmt,
587 int update)
588{
589 struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
590 struct vpif_params *vpif_params = &ch->vpifparams;
591 enum v4l2_field field = pixfmt->field;
592 u32 sizeimage, hpitch, vpitch;
593 int ret = -EINVAL;
594
595 vpif_dbg(2, debug, "vpif_check_format\n");
596 /**
597 * first check for the pixel format. If if_type is Raw bayer,
598 * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only
599 * V4L2_PIX_FMT_YUV422P is supported
600 */
601 if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
602 if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) {
603 if (!update) {
604 vpif_dbg(2, debug, "invalid pix format\n");
605 goto exit;
606 }
607 pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
608 }
609 } else {
610 if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) {
611 if (!update) {
612 vpif_dbg(2, debug, "invalid pixel format\n");
613 goto exit;
614 }
615 pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
616 }
617 }
618
619 if (!(VPIF_VALID_FIELD(field))) {
620 if (!update) {
621 vpif_dbg(2, debug, "invalid field format\n");
622 goto exit;
623 }
624 /**
625 * By default use FIELD_NONE for RAW Bayer capture
626 * and FIELD_INTERLACED for other interfaces
627 */
628 field = vpif_get_default_field(&vpif_params->iface);
629 } else if (field == V4L2_FIELD_ANY)
630 /* unsupported field. Use default */
631 field = vpif_get_default_field(&vpif_params->iface);
632
633 /* validate the hpitch */
634 hpitch = pixfmt->bytesperline;
635 if (hpitch < vpif_params->std_info.width) {
636 if (!update) {
637 vpif_dbg(2, debug, "invalid hpitch\n");
638 goto exit;
639 }
640 hpitch = vpif_params->std_info.width;
641 }
642
643 if (V4L2_MEMORY_USERPTR == common->memory)
644 sizeimage = pixfmt->sizeimage;
645 else
646 sizeimage = config_params.channel_bufsize[ch->channel_id];
647
648 vpitch = sizeimage / (hpitch * 2);
649
650 /* validate the vpitch */
651 if (vpitch < vpif_params->std_info.height) {
652 if (!update) {
653 vpif_dbg(2, debug, "Invalid vpitch\n");
654 goto exit;
655 }
656 vpitch = vpif_params->std_info.height;
657 }
658
659 /* Check for 8 byte alignment */
660 if (!ALIGN(hpitch, 8)) {
661 if (!update) {
662 vpif_dbg(2, debug, "invalid pitch alignment\n");
663 goto exit;
664 }
665 /* adjust to next 8 byte boundary */
666 hpitch = (((hpitch + 7) / 8) * 8);
667 }
668 /* if update is set, modify the bytesperline and sizeimage */
669 if (update) {
670 pixfmt->bytesperline = hpitch;
671 pixfmt->sizeimage = hpitch * vpitch * 2;
672 }
673 /**
674 * Image width and height is always based on current standard width and
675 * height
676 */
677 pixfmt->width = common->fmt.fmt.pix.width;
678 pixfmt->height = common->fmt.fmt.pix.height;
679 return 0;
680exit:
681 return ret;
682}
683
684/**
685 * vpif_config_addr() - function to configure buffer address in vpif
686 * @ch - channel ptr
687 * @muxmode - channel mux mode
688 */
689static void vpif_config_addr(struct channel_obj *ch, int muxmode)
690{
691 struct common_obj *common;
692
693 vpif_dbg(2, debug, "vpif_config_addr\n");
694
695 common = &(ch->common[VPIF_VIDEO_INDEX]);
696
697 if (VPIF_CHANNEL1_VIDEO == ch->channel_id)
698 common->set_addr = ch1_set_videobuf_addr;
699 else if (2 == muxmode)
700 common->set_addr = ch0_set_videobuf_addr_yc_nmux;
701 else
702 common->set_addr = ch0_set_videobuf_addr;
703}
704
705/**
706 * vpfe_mmap : It is used to map kernel space buffers into user spaces
707 * @filep: file pointer
708 * @vma: ptr to vm_area_struct
709 */
710static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
711{
712 /* Get the channel object and file handle object */
713 struct vpif_fh *fh = filep->private_data;
714 struct channel_obj *ch = fh->channel;
715 struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
716
717 vpif_dbg(2, debug, "vpif_mmap\n");
718
719 return videobuf_mmap_mapper(&common->buffer_queue, vma);
720}
721
722/**
723 * vpif_poll: It is used for select/poll system call
724 * @filep: file pointer
725 * @wait: poll table to wait
726 */
727static unsigned int vpif_poll(struct file *filep, poll_table * wait)
728{
729 struct vpif_fh *fh = filep->private_data;
730 struct channel_obj *channel = fh->channel;
731 struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]);
732
733 vpif_dbg(2, debug, "vpif_poll\n");
734
735 if (common->started)
736 return videobuf_poll_stream(filep, &common->buffer_queue, wait);
737 return 0;
738}
739
740/**
741 * vpif_open : vpif open handler
742 * @filep: file ptr
743 *
744 * It creates object of file handle structure and stores it in private_data
745 * member of filepointer
746 */
747static int vpif_open(struct file *filep)
748{
749 struct vpif_capture_config *config = vpif_dev->platform_data;
750 struct video_device *vdev = video_devdata(filep);
751 struct common_obj *common;
752 struct video_obj *vid_ch;
753 struct channel_obj *ch;
754 struct vpif_fh *fh;
755 int i;
756
757 vpif_dbg(2, debug, "vpif_open\n");
758
759 ch = video_get_drvdata(vdev);
760
761 vid_ch = &ch->video;
762 common = &ch->common[VPIF_VIDEO_INDEX];
763
764 if (NULL == ch->curr_subdev_info) {
765 /**
766 * search through the sub device to see a registered
767 * sub device and make it as current sub device
768 */
769 for (i = 0; i < config->subdev_count; i++) {
770 if (vpif_obj.sd[i]) {
771 /* the sub device is registered */
772 ch->curr_subdev_info = &config->subdev_info[i];
773 /* make first input as the current input */
774 vid_ch->input_idx = 0;
775 break;
776 }
777 }
778 if (i == config->subdev_count) {
779 vpif_err("No sub device registered\n");
780 return -ENOENT;
781 }
782 }
783
784 /* Allocate memory for the file handle object */
785 fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
786 if (NULL == fh) {
787 vpif_err("unable to allocate memory for file handle object\n");
788 return -ENOMEM;
789 }
790
791 /* store pointer to fh in private_data member of filep */
792 filep->private_data = fh;
793 fh->channel = ch;
794 fh->initialized = 0;
795 /* If decoder is not initialized. initialize it */
796 if (!ch->initialized) {
797 fh->initialized = 1;
798 ch->initialized = 1;
799 memset(&(ch->vpifparams), 0, sizeof(struct vpif_params));
800 }
801 /* Increment channel usrs counter */
802 ch->usrs++;
803 /* Set io_allowed member to false */
804 fh->io_allowed[VPIF_VIDEO_INDEX] = 0;
805 /* Initialize priority of this instance to default priority */
806 fh->prio = V4L2_PRIORITY_UNSET;
807 v4l2_prio_open(&ch->prio, &fh->prio);
808 return 0;
809}
810
811/**
812 * vpif_release : function to clean up file close
813 * @filep: file pointer
814 *
815 * This function deletes buffer queue, frees the buffers and the vpfe file
816 * handle
817 */
818static int vpif_release(struct file *filep)
819{
820 struct vpif_fh *fh = filep->private_data;
821 struct channel_obj *ch = fh->channel;
822 struct common_obj *common;
823
824 vpif_dbg(2, debug, "vpif_release\n");
825
826 common = &ch->common[VPIF_VIDEO_INDEX];
827
828 /* if this instance is doing IO */
829 if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
830 /* Reset io_usrs member of channel object */
831 common->io_usrs = 0;
832 /* Disable channel as per its device type and channel id */
833 if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
834 enable_channel0(0);
835 channel0_intr_enable(0);
836 }
837 if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
838 (2 == common->started)) {
839 enable_channel1(0);
840 channel1_intr_enable(0);
841 }
842 common->started = 0;
843 /* Free buffers allocated */
844 videobuf_queue_cancel(&common->buffer_queue);
845 videobuf_mmap_free(&common->buffer_queue);
846 }
847
848 /* Decrement channel usrs counter */
849 ch->usrs--;
850
851 /* Close the priority */
852 v4l2_prio_close(&ch->prio, fh->prio);
853
854 if (fh->initialized)
855 ch->initialized = 0;
856
857 filep->private_data = NULL;
858 kfree(fh);
859 return 0;
860}
861
862/**
863 * vpif_reqbufs() - request buffer handler
864 * @file: file ptr
865 * @priv: file handle
866 * @reqbuf: request buffer structure ptr
867 */
868static int vpif_reqbufs(struct file *file, void *priv,
869 struct v4l2_requestbuffers *reqbuf)
870{
871 struct vpif_fh *fh = priv;
872 struct channel_obj *ch = fh->channel;
873 struct common_obj *common;
874 u8 index = 0;
875
876 vpif_dbg(2, debug, "vpif_reqbufs\n");
877
878 /**
879 * This file handle has not initialized the channel,
880 * It is not allowed to do settings
881 */
882 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)
883 || (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
884 if (!fh->initialized) {
885 vpif_dbg(1, debug, "Channel Busy\n");
886 return -EBUSY;
887 }
888 }
889
890 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != reqbuf->type)
891 return -EINVAL;
892
893 index = VPIF_VIDEO_INDEX;
894
895 common = &ch->common[index];
896
897 if (0 != common->io_usrs)
898 return -EBUSY;
899
900 /* Initialize videobuf queue as per the buffer type */
901 videobuf_queue_dma_contig_init(&common->buffer_queue,
902 &video_qops, NULL,
903 &common->irqlock,
904 reqbuf->type,
905 common->fmt.fmt.pix.field,
906 sizeof(struct videobuf_buffer), fh,
907 &common->lock);
908
909 /* Set io allowed member of file handle to TRUE */
910 fh->io_allowed[index] = 1;
911 /* Increment io usrs member of channel object to 1 */
912 common->io_usrs = 1;
913 /* Store type of memory requested in channel object */
914 common->memory = reqbuf->memory;
915 INIT_LIST_HEAD(&common->dma_queue);
916
917 /* Allocate buffers */
918 return videobuf_reqbufs(&common->buffer_queue, reqbuf);
919}
920
921/**
922 * vpif_querybuf() - query buffer handler
923 * @file: file ptr
924 * @priv: file handle
925 * @buf: v4l2 buffer structure ptr
926 */
927static int vpif_querybuf(struct file *file, void *priv,
928 struct v4l2_buffer *buf)
929{
930 struct vpif_fh *fh = priv;
931 struct channel_obj *ch = fh->channel;
932 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
933
934 vpif_dbg(2, debug, "vpif_querybuf\n");
935
936 if (common->fmt.type != buf->type)
937 return -EINVAL;
938
939 if (common->memory != V4L2_MEMORY_MMAP) {
940 vpif_dbg(1, debug, "Invalid memory\n");
941 return -EINVAL;
942 }
943
944 return videobuf_querybuf(&common->buffer_queue, buf);
945}
946
947/**
948 * vpif_qbuf() - query buffer handler
949 * @file: file ptr
950 * @priv: file handle
951 * @buf: v4l2 buffer structure ptr
952 */
953static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
954{
955
956 struct vpif_fh *fh = priv;
957 struct channel_obj *ch = fh->channel;
958 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
959 struct v4l2_buffer tbuf = *buf;
960 struct videobuf_buffer *buf1;
961 unsigned long addr = 0;
962 unsigned long flags;
963 int ret = 0;
964
965 vpif_dbg(2, debug, "vpif_qbuf\n");
966
967 if (common->fmt.type != tbuf.type) {
968 vpif_err("invalid buffer type\n");
969 return -EINVAL;
970 }
971
972 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
973 vpif_err("fh io not allowed \n");
974 return -EACCES;
975 }
976
977 if (!(list_empty(&common->dma_queue)) ||
978 (common->cur_frm != common->next_frm) ||
979 !common->started ||
980 (common->started && (0 == ch->field_id)))
981 return videobuf_qbuf(&common->buffer_queue, buf);
982
983 /* bufferqueue is empty store buffer address in VPIF registers */
984 mutex_lock(&common->buffer_queue.vb_lock);
985 buf1 = common->buffer_queue.bufs[tbuf.index];
986
987 if ((buf1->state == VIDEOBUF_QUEUED) ||
988 (buf1->state == VIDEOBUF_ACTIVE)) {
989 vpif_err("invalid state\n");
990 goto qbuf_exit;
991 }
992
993 switch (buf1->memory) {
994 case V4L2_MEMORY_MMAP:
995 if (buf1->baddr == 0)
996 goto qbuf_exit;
997 break;
998
999 case V4L2_MEMORY_USERPTR:
1000 if (tbuf.length < buf1->bsize)
1001 goto qbuf_exit;
1002
1003 if ((VIDEOBUF_NEEDS_INIT != buf1->state)
1004 && (buf1->baddr != tbuf.m.userptr)) {
1005 vpif_buffer_release(&common->buffer_queue, buf1);
1006 buf1->baddr = tbuf.m.userptr;
1007 }
1008 break;
1009
1010 default:
1011 goto qbuf_exit;
1012 }
1013
1014 local_irq_save(flags);
1015 ret = vpif_buffer_prepare(&common->buffer_queue, buf1,
1016 common->buffer_queue.field);
1017 if (ret < 0) {
1018 local_irq_restore(flags);
1019 goto qbuf_exit;
1020 }
1021
1022 buf1->state = VIDEOBUF_ACTIVE;
1023
1024 if (V4L2_MEMORY_USERPTR == common->memory)
1025 addr = buf1->boff;
1026 else
1027 addr = videobuf_to_dma_contig(buf1);
1028
1029 common->next_frm = buf1;
1030 common->set_addr(addr + common->ytop_off,
1031 addr + common->ybtm_off,
1032 addr + common->ctop_off,
1033 addr + common->cbtm_off);
1034
1035 local_irq_restore(flags);
1036 list_add_tail(&buf1->stream, &common->buffer_queue.stream);
1037 mutex_unlock(&common->buffer_queue.vb_lock);
1038 return 0;
1039
1040qbuf_exit:
1041 mutex_unlock(&common->buffer_queue.vb_lock);
1042 return -EINVAL;
1043}
1044
1045/**
1046 * vpif_dqbuf() - query buffer handler
1047 * @file: file ptr
1048 * @priv: file handle
1049 * @buf: v4l2 buffer structure ptr
1050 */
1051static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
1052{
1053 struct vpif_fh *fh = priv;
1054 struct channel_obj *ch = fh->channel;
1055 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1056
1057 vpif_dbg(2, debug, "vpif_dqbuf\n");
1058
1059 return videobuf_dqbuf(&common->buffer_queue, buf,
1060 file->f_flags & O_NONBLOCK);
1061}
1062
1063/**
1064 * vpif_streamon() - streamon handler
1065 * @file: file ptr
1066 * @priv: file handle
1067 * @buftype: v4l2 buffer type
1068 */
1069static int vpif_streamon(struct file *file, void *priv,
1070 enum v4l2_buf_type buftype)
1071{
1072
1073 struct vpif_capture_config *config = vpif_dev->platform_data;
1074 struct vpif_fh *fh = priv;
1075 struct channel_obj *ch = fh->channel;
1076 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1077 struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
1078 struct vpif_params *vpif;
1079 unsigned long addr = 0;
1080 int ret = 0;
1081
1082 vpif_dbg(2, debug, "vpif_streamon\n");
1083
1084 vpif = &ch->vpifparams;
1085
1086 if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1087 vpif_dbg(1, debug, "buffer type not supported\n");
1088 return -EINVAL;
1089 }
1090
1091 /* If file handle is not allowed IO, return error */
1092 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
1093 vpif_dbg(1, debug, "io not allowed\n");
1094 return -EACCES;
1095 }
1096
1097 /* If Streaming is already started, return error */
1098 if (common->started) {
1099 vpif_dbg(1, debug, "channel->started\n");
1100 return -EBUSY;
1101 }
1102
1103 if ((ch->channel_id == VPIF_CHANNEL0_VIDEO &&
1104 oth_ch->common[VPIF_VIDEO_INDEX].started &&
1105 vpif->std_info.ycmux_mode == 0) ||
1106 ((ch->channel_id == VPIF_CHANNEL1_VIDEO) &&
1107 (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) {
1108 vpif_dbg(1, debug, "other channel is being used\n");
1109 return -EBUSY;
1110 }
1111
1112 ret = vpif_check_format(ch, &common->fmt.fmt.pix, 0);
1113 if (ret)
1114 return ret;
1115
1116 /* Enable streamon on the sub device */
1117 ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
1118 s_stream, 1);
1119
1120 if (ret && (ret != -ENOIOCTLCMD)) {
1121 vpif_dbg(1, debug, "stream on failed in subdev\n");
1122 return ret;
1123 }
1124
1125 /* Call videobuf_streamon to start streaming in videobuf */
1126 ret = videobuf_streamon(&common->buffer_queue);
1127 if (ret) {
1128 vpif_dbg(1, debug, "videobuf_streamon\n");
1129 return ret;
1130 }
1131
1132 /* If buffer queue is empty, return error */
1133 if (list_empty(&common->dma_queue)) {
1134 vpif_dbg(1, debug, "buffer queue is empty\n");
1135 ret = -EIO;
1136 goto exit;
1137 }
1138
1139 /* Get the next frame from the buffer queue */
1140 common->cur_frm = list_entry(common->dma_queue.next,
1141 struct videobuf_buffer, queue);
1142 common->next_frm = common->cur_frm;
1143
1144 /* Remove buffer from the buffer queue */
1145 list_del(&common->cur_frm->queue);
1146 /* Mark state of the current frame to active */
1147 common->cur_frm->state = VIDEOBUF_ACTIVE;
1148 /* Initialize field_id and started member */
1149 ch->field_id = 0;
1150 common->started = 1;
1151
1152 if (V4L2_MEMORY_USERPTR == common->memory)
1153 addr = common->cur_frm->boff;
1154 else
1155 addr = videobuf_to_dma_contig(common->cur_frm);
1156
1157 /* Calculate the offset for Y and C data in the buffer */
1158 vpif_calculate_offsets(ch);
1159
1160 if ((vpif->std_info.frm_fmt &&
1161 ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE) &&
1162 (common->fmt.fmt.pix.field != V4L2_FIELD_ANY))) ||
1163 (!vpif->std_info.frm_fmt &&
1164 (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
1165 vpif_dbg(1, debug, "conflict in field format and std format\n");
1166 ret = -EINVAL;
1167 goto exit;
1168 }
1169
1170 /* configure 1 or 2 channel mode */
1171 ret = config->setup_input_channel_mode(vpif->std_info.ycmux_mode);
1172
1173 if (ret < 0) {
1174 vpif_dbg(1, debug, "can't set vpif channel mode\n");
1175 goto exit;
1176 }
1177
1178 /* Call vpif_set_params function to set the parameters and addresses */
1179 ret = vpif_set_video_params(vpif, ch->channel_id);
1180
1181 if (ret < 0) {
1182 vpif_dbg(1, debug, "can't set video params\n");
1183 goto exit;
1184 }
1185
1186 common->started = ret;
1187 vpif_config_addr(ch, ret);
1188
1189 common->set_addr(addr + common->ytop_off,
1190 addr + common->ybtm_off,
1191 addr + common->ctop_off,
1192 addr + common->cbtm_off);
1193
1194 /**
1195 * Set interrupt for both the fields in VPIF Register enable channel in
1196 * VPIF register
1197 */
1198 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) {
1199 channel0_intr_assert();
1200 channel0_intr_enable(1);
1201 enable_channel0(1);
1202 }
1203 if ((VPIF_CHANNEL1_VIDEO == ch->channel_id) ||
1204 (common->started == 2)) {
1205 channel1_intr_assert();
1206 channel1_intr_enable(1);
1207 enable_channel1(1);
1208 }
1209 channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
1210 return ret;
1211
1212exit:
1213 videobuf_streamoff(&common->buffer_queue);
1214 return ret;
1215}
1216
1217/**
1218 * vpif_streamoff() - streamoff handler
1219 * @file: file ptr
1220 * @priv: file handle
1221 * @buftype: v4l2 buffer type
1222 */
1223static int vpif_streamoff(struct file *file, void *priv,
1224 enum v4l2_buf_type buftype)
1225{
1226
1227 struct vpif_fh *fh = priv;
1228 struct channel_obj *ch = fh->channel;
1229 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1230 int ret;
1231
1232 vpif_dbg(2, debug, "vpif_streamoff\n");
1233
1234 if (buftype != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1235 vpif_dbg(1, debug, "buffer type not supported\n");
1236 return -EINVAL;
1237 }
1238
1239 /* If io is allowed for this file handle, return error */
1240 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
1241 vpif_dbg(1, debug, "io not allowed\n");
1242 return -EACCES;
1243 }
1244
1245 /* If streaming is not started, return error */
1246 if (!common->started) {
1247 vpif_dbg(1, debug, "channel->started\n");
1248 return -EINVAL;
1249 }
1250
1251 /* disable channel */
1252 if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
1253 enable_channel0(0);
1254 channel0_intr_enable(0);
1255 } else {
1256 enable_channel1(0);
1257 channel1_intr_enable(0);
1258 }
1259
1260 common->started = 0;
1261
1262 ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
1263 s_stream, 0);
1264
1265 if (ret && (ret != -ENOIOCTLCMD))
1266 vpif_dbg(1, debug, "stream off failed in subdev\n");
1267
1268 return videobuf_streamoff(&common->buffer_queue);
1269}
1270
1271/**
1272 * vpif_map_sub_device_to_input() - Maps sub device to input
1273 * @ch - ptr to channel
1274 * @config - ptr to capture configuration
1275 * @input_index - Given input index from application
1276 * @sub_device_index - index into sd table
1277 *
1278 * lookup the sub device information for a given input index.
1279 * we report all the inputs to application. inputs table also
1280 * has sub device name for the each input
1281 */
1282static struct vpif_subdev_info *vpif_map_sub_device_to_input(
1283 struct channel_obj *ch,
1284 struct vpif_capture_config *vpif_cfg,
1285 int input_index,
1286 int *sub_device_index)
1287{
1288 struct vpif_capture_chan_config *chan_cfg;
1289 struct vpif_subdev_info *subdev_info = NULL;
1290 const char *subdev_name = NULL;
1291 int i;
1292
1293 vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n");
1294
1295 chan_cfg = &vpif_cfg->chan_config[ch->channel_id];
1296
1297 /**
1298 * search through the inputs to find the sub device supporting
1299 * the input
1300 */
1301 for (i = 0; i < chan_cfg->input_count; i++) {
1302 /* For each sub device, loop through input */
1303 if (i == input_index) {
1304 subdev_name = chan_cfg->inputs[i].subdev_name;
1305 break;
1306 }
1307 }
1308
1309 /* if reached maximum. return null */
1310 if (i == chan_cfg->input_count || (NULL == subdev_name))
1311 return subdev_info;
1312
1313 /* loop through the sub device list to get the sub device info */
1314 for (i = 0; i < vpif_cfg->subdev_count; i++) {
1315 subdev_info = &vpif_cfg->subdev_info[i];
1316 if (!strcmp(subdev_info->name, subdev_name))
1317 break;
1318 }
1319
1320 if (i == vpif_cfg->subdev_count)
1321 return subdev_info;
1322
1323 /* check if the sub device is registered */
1324 if (NULL == vpif_obj.sd[i])
1325 return NULL;
1326
1327 *sub_device_index = i;
1328 return subdev_info;
1329}
1330
1331/**
1332 * vpif_querystd() - querystd handler
1333 * @file: file ptr
1334 * @priv: file handle
1335 * @std_id: ptr to std id
1336 *
1337 * This function is called to detect standard at the selected input
1338 */
1339static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
1340{
1341 struct vpif_fh *fh = priv;
1342 struct channel_obj *ch = fh->channel;
1343 int ret = 0;
1344
1345 vpif_dbg(2, debug, "vpif_querystd\n");
1346
1347 /* Call querystd function of decoder device */
1348 ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
1349 querystd, std_id);
1350 if (ret < 0)
1351 vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
1352
1353 return ret;
1354}
1355
1356/**
1357 * vpif_g_std() - get STD handler
1358 * @file: file ptr
1359 * @priv: file handle
1360 * @std_id: ptr to std id
1361 */
1362static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)
1363{
1364 struct vpif_fh *fh = priv;
1365 struct channel_obj *ch = fh->channel;
1366
1367 vpif_dbg(2, debug, "vpif_g_std\n");
1368
1369 *std = ch->video.stdid;
1370 return 0;
1371}
1372
1373/**
1374 * vpif_s_std() - set STD handler
1375 * @file: file ptr
1376 * @priv: file handle
1377 * @std_id: ptr to std id
1378 */
1379static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
1380{
1381 struct vpif_fh *fh = priv;
1382 struct channel_obj *ch = fh->channel;
1383 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1384 int ret = 0;
1385
1386 vpif_dbg(2, debug, "vpif_s_std\n");
1387
1388 if (common->started) {
1389 vpif_err("streaming in progress\n");
1390 return -EBUSY;
1391 }
1392
1393 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1394 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1395 if (!fh->initialized) {
1396 vpif_dbg(1, debug, "Channel Busy\n");
1397 return -EBUSY;
1398 }
1399 }
1400
1401 ret = v4l2_prio_check(&ch->prio, fh->prio);
1402 if (0 != ret)
1403 return ret;
1404
1405 fh->initialized = 1;
1406
1407 /* Call encoder subdevice function to set the standard */
1408 ch->video.stdid = *std_id;
1409 ch->video.dv_preset = V4L2_DV_INVALID;
1410 memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
1411
1412 /* Get the information about the standard */
1413 if (vpif_update_std_info(ch)) {
1414 vpif_err("Error getting the standard info\n");
1415 return -EINVAL;
1416 }
1417
1418 /* Configure the default format information */
1419 vpif_config_format(ch);
1420
1421 /* set standard in the sub device */
1422 ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
1423 s_std, *std_id);
1424 if (ret < 0)
1425 vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
1426 return ret;
1427}
1428
1429/**
1430 * vpif_enum_input() - ENUMINPUT handler
1431 * @file: file ptr
1432 * @priv: file handle
1433 * @input: ptr to input structure
1434 */
1435static int vpif_enum_input(struct file *file, void *priv,
1436 struct v4l2_input *input)
1437{
1438
1439 struct vpif_capture_config *config = vpif_dev->platform_data;
1440 struct vpif_capture_chan_config *chan_cfg;
1441 struct vpif_fh *fh = priv;
1442 struct channel_obj *ch = fh->channel;
1443
1444 chan_cfg = &config->chan_config[ch->channel_id];
1445
1446 if (input->index >= chan_cfg->input_count) {
1447 vpif_dbg(1, debug, "Invalid input index\n");
1448 return -EINVAL;
1449 }
1450
1451 memcpy(input, &chan_cfg->inputs[input->index].input,
1452 sizeof(*input));
1453 return 0;
1454}
1455
1456/**
1457 * vpif_g_input() - Get INPUT handler
1458 * @file: file ptr
1459 * @priv: file handle
1460 * @index: ptr to input index
1461 */
1462static int vpif_g_input(struct file *file, void *priv, unsigned int *index)
1463{
1464 struct vpif_fh *fh = priv;
1465 struct channel_obj *ch = fh->channel;
1466 struct video_obj *vid_ch = &ch->video;
1467
1468 *index = vid_ch->input_idx;
1469
1470 return 0;
1471}
1472
1473/**
1474 * vpif_s_input() - Set INPUT handler
1475 * @file: file ptr
1476 * @priv: file handle
1477 * @index: input index
1478 */
1479static int vpif_s_input(struct file *file, void *priv, unsigned int index)
1480{
1481 struct vpif_capture_config *config = vpif_dev->platform_data;
1482 struct vpif_capture_chan_config *chan_cfg;
1483 struct vpif_fh *fh = priv;
1484 struct channel_obj *ch = fh->channel;
1485 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1486 struct video_obj *vid_ch = &ch->video;
1487 struct vpif_subdev_info *subdev_info;
1488 int ret = 0, sd_index = 0;
1489 u32 input = 0, output = 0;
1490
1491 chan_cfg = &config->chan_config[ch->channel_id];
1492
1493 if (common->started) {
1494 vpif_err("Streaming in progress\n");
1495 return -EBUSY;
1496 }
1497
1498 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1499 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1500 if (!fh->initialized) {
1501 vpif_dbg(1, debug, "Channel Busy\n");
1502 return -EBUSY;
1503 }
1504 }
1505
1506 ret = v4l2_prio_check(&ch->prio, fh->prio);
1507 if (0 != ret)
1508 return ret;
1509
1510 fh->initialized = 1;
1511 subdev_info = vpif_map_sub_device_to_input(ch, config, index,
1512 &sd_index);
1513 if (NULL == subdev_info) {
1514 vpif_dbg(1, debug,
1515 "couldn't lookup sub device for the input index\n");
1516 return -EINVAL;
1517 }
1518
1519 /* first setup input path from sub device to vpif */
1520 if (config->setup_input_path) {
1521 ret = config->setup_input_path(ch->channel_id,
1522 subdev_info->name);
1523 if (ret < 0) {
1524 vpif_dbg(1, debug, "couldn't setup input path for the"
1525 " sub device %s, for input index %d\n",
1526 subdev_info->name, index);
1527 return ret;
1528 }
1529 }
1530
1531 if (subdev_info->can_route) {
1532 input = subdev_info->input;
1533 output = subdev_info->output;
1534 ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing,
1535 input, output, 0);
1536 if (ret < 0) {
1537 vpif_dbg(1, debug, "Failed to set input\n");
1538 return ret;
1539 }
1540 }
1541 vid_ch->input_idx = index;
1542 ch->curr_subdev_info = subdev_info;
1543 ch->curr_sd_index = sd_index;
1544 /* copy interface parameters to vpif */
1545 ch->vpifparams.iface = subdev_info->vpif_if;
1546
1547 /* update tvnorms from the sub device input info */
1548 ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
1549 return ret;
1550}
1551
1552/**
1553 * vpif_enum_fmt_vid_cap() - ENUM_FMT handler
1554 * @file: file ptr
1555 * @priv: file handle
1556 * @index: input index
1557 */
1558static int vpif_enum_fmt_vid_cap(struct file *file, void *priv,
1559 struct v4l2_fmtdesc *fmt)
1560{
1561 struct vpif_fh *fh = priv;
1562 struct channel_obj *ch = fh->channel;
1563
1564 if (fmt->index != 0) {
1565 vpif_dbg(1, debug, "Invalid format index\n");
1566 return -EINVAL;
1567 }
1568
1569 /* Fill in the information about format */
1570 if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) {
1571 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1572 strcpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb");
1573 fmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
1574 } else {
1575 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1576 strcpy(fmt->description, "YCbCr4:2:2 YC Planar");
1577 fmt->pixelformat = V4L2_PIX_FMT_YUV422P;
1578 }
1579 return 0;
1580}
1581
1582/**
1583 * vpif_try_fmt_vid_cap() - TRY_FMT handler
1584 * @file: file ptr
1585 * @priv: file handle
1586 * @fmt: ptr to v4l2 format structure
1587 */
1588static int vpif_try_fmt_vid_cap(struct file *file, void *priv,
1589 struct v4l2_format *fmt)
1590{
1591 struct vpif_fh *fh = priv;
1592 struct channel_obj *ch = fh->channel;
1593 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
1594
1595 return vpif_check_format(ch, pixfmt, 1);
1596}
1597
1598
1599/**
1600 * vpif_g_fmt_vid_cap() - Set INPUT handler
1601 * @file: file ptr
1602 * @priv: file handle
1603 * @fmt: ptr to v4l2 format structure
1604 */
1605static int vpif_g_fmt_vid_cap(struct file *file, void *priv,
1606 struct v4l2_format *fmt)
1607{
1608 struct vpif_fh *fh = priv;
1609 struct channel_obj *ch = fh->channel;
1610 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1611
1612 /* Check the validity of the buffer type */
1613 if (common->fmt.type != fmt->type)
1614 return -EINVAL;
1615
1616 /* Fill in the information about format */
1617 *fmt = common->fmt;
1618 return 0;
1619}
1620
1621/**
1622 * vpif_s_fmt_vid_cap() - Set FMT handler
1623 * @file: file ptr
1624 * @priv: file handle
1625 * @fmt: ptr to v4l2 format structure
1626 */
1627static int vpif_s_fmt_vid_cap(struct file *file, void *priv,
1628 struct v4l2_format *fmt)
1629{
1630 struct vpif_fh *fh = priv;
1631 struct channel_obj *ch = fh->channel;
1632 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1633 struct v4l2_pix_format *pixfmt;
1634 int ret = 0;
1635
1636 vpif_dbg(2, debug, "%s\n", __func__);
1637
1638 /* If streaming is started, return error */
1639 if (common->started) {
1640 vpif_dbg(1, debug, "Streaming is started\n");
1641 return -EBUSY;
1642 }
1643
1644 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1645 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1646 if (!fh->initialized) {
1647 vpif_dbg(1, debug, "Channel Busy\n");
1648 return -EBUSY;
1649 }
1650 }
1651
1652 ret = v4l2_prio_check(&ch->prio, fh->prio);
1653 if (0 != ret)
1654 return ret;
1655
1656 fh->initialized = 1;
1657
1658 pixfmt = &fmt->fmt.pix;
1659 /* Check for valid field format */
1660 ret = vpif_check_format(ch, pixfmt, 0);
1661
1662 if (ret)
1663 return ret;
1664 /* store the format in the channel object */
1665 common->fmt = *fmt;
1666 return 0;
1667}
1668
1669/**
1670 * vpif_querycap() - QUERYCAP handler
1671 * @file: file ptr
1672 * @priv: file handle
1673 * @cap: ptr to v4l2_capability structure
1674 */
1675static int vpif_querycap(struct file *file, void *priv,
1676 struct v4l2_capability *cap)
1677{
1678 struct vpif_capture_config *config = vpif_dev->platform_data;
1679
1680 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1681 strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
1682 strlcpy(cap->bus_info, "DM646x Platform", sizeof(cap->bus_info));
1683 strlcpy(cap->card, config->card_name, sizeof(cap->card));
1684
1685 return 0;
1686}
1687
1688/**
1689 * vpif_g_priority() - get priority handler
1690 * @file: file ptr
1691 * @priv: file handle
1692 * @prio: ptr to v4l2_priority structure
1693 */
1694static int vpif_g_priority(struct file *file, void *priv,
1695 enum v4l2_priority *prio)
1696{
1697 struct vpif_fh *fh = priv;
1698 struct channel_obj *ch = fh->channel;
1699
1700 *prio = v4l2_prio_max(&ch->prio);
1701
1702 return 0;
1703}
1704
1705/**
1706 * vpif_s_priority() - set priority handler
1707 * @file: file ptr
1708 * @priv: file handle
1709 * @prio: ptr to v4l2_priority structure
1710 */
1711static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p)
1712{
1713 struct vpif_fh *fh = priv;
1714 struct channel_obj *ch = fh->channel;
1715
1716 return v4l2_prio_change(&ch->prio, &fh->prio, p);
1717}
1718
1719/**
1720 * vpif_cropcap() - cropcap handler
1721 * @file: file ptr
1722 * @priv: file handle
1723 * @crop: ptr to v4l2_cropcap structure
1724 */
1725static int vpif_cropcap(struct file *file, void *priv,
1726 struct v4l2_cropcap *crop)
1727{
1728 struct vpif_fh *fh = priv;
1729 struct channel_obj *ch = fh->channel;
1730 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1731
1732 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != crop->type)
1733 return -EINVAL;
1734
1735 crop->bounds.left = 0;
1736 crop->bounds.top = 0;
1737 crop->bounds.height = common->height;
1738 crop->bounds.width = common->width;
1739 crop->defrect = crop->bounds;
1740 return 0;
1741}
1742
1743/**
1744 * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
1745 * @file: file ptr
1746 * @priv: file handle
1747 * @preset: input preset
1748 */
1749static int vpif_enum_dv_presets(struct file *file, void *priv,
1750 struct v4l2_dv_enum_preset *preset)
1751{
1752 struct vpif_fh *fh = priv;
1753 struct channel_obj *ch = fh->channel;
1754
1755 return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
1756 video, enum_dv_presets, preset);
1757}
1758
1759/**
1760 * vpif_query_dv_presets() - QUERY_DV_PRESET handler
1761 * @file: file ptr
1762 * @priv: file handle
1763 * @preset: input preset
1764 */
1765static int vpif_query_dv_preset(struct file *file, void *priv,
1766 struct v4l2_dv_preset *preset)
1767{
1768 struct vpif_fh *fh = priv;
1769 struct channel_obj *ch = fh->channel;
1770
1771 return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
1772 video, query_dv_preset, preset);
1773}
1774/**
1775 * vpif_s_dv_presets() - S_DV_PRESETS handler
1776 * @file: file ptr
1777 * @priv: file handle
1778 * @preset: input preset
1779 */
1780static int vpif_s_dv_preset(struct file *file, void *priv,
1781 struct v4l2_dv_preset *preset)
1782{
1783 struct vpif_fh *fh = priv;
1784 struct channel_obj *ch = fh->channel;
1785 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1786 int ret = 0;
1787
1788 if (common->started) {
1789 vpif_dbg(1, debug, "streaming in progress\n");
1790 return -EBUSY;
1791 }
1792
1793 if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
1794 (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
1795 if (!fh->initialized) {
1796 vpif_dbg(1, debug, "Channel Busy\n");
1797 return -EBUSY;
1798 }
1799 }
1800
1801 ret = v4l2_prio_check(&ch->prio, fh->prio);
1802 if (ret)
1803 return ret;
1804
1805 fh->initialized = 1;
1806
1807 /* Call encoder subdevice function to set the standard */
1808 if (mutex_lock_interruptible(&common->lock))
1809 return -ERESTARTSYS;
1810
1811 ch->video.dv_preset = preset->preset;
1812 ch->video.stdid = V4L2_STD_UNKNOWN;
1813 memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
1814
1815 /* Get the information about the standard */
1816 if (vpif_update_std_info(ch)) {
1817 vpif_dbg(1, debug, "Error getting the standard info\n");
1818 ret = -EINVAL;
1819 } else {
1820 /* Configure the default format information */
1821 vpif_config_format(ch);
1822
1823 ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
1824 video, s_dv_preset, preset);
1825 }
1826
1827 mutex_unlock(&common->lock);
1828
1829 return ret;
1830}
1831/**
1832 * vpif_g_dv_presets() - G_DV_PRESETS handler
1833 * @file: file ptr
1834 * @priv: file handle
1835 * @preset: input preset
1836 */
1837static int vpif_g_dv_preset(struct file *file, void *priv,
1838 struct v4l2_dv_preset *preset)
1839{
1840 struct vpif_fh *fh = priv;
1841 struct channel_obj *ch = fh->channel;
1842
1843 preset->preset = ch->video.dv_preset;
1844
1845 return 0;
1846}
1847
1848/**
1849 * vpif_s_dv_timings() - S_DV_TIMINGS handler
1850 * @file: file ptr
1851 * @priv: file handle
1852 * @timings: digital video timings
1853 */
1854static int vpif_s_dv_timings(struct file *file, void *priv,
1855 struct v4l2_dv_timings *timings)
1856{
1857 struct vpif_fh *fh = priv;
1858 struct channel_obj *ch = fh->channel;
1859 struct vpif_params *vpifparams = &ch->vpifparams;
1860 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
1861 struct video_obj *vid_ch = &ch->video;
1862 struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
1863 int ret;
1864
1865 if (timings->type != V4L2_DV_BT_656_1120) {
1866 vpif_dbg(2, debug, "Timing type not defined\n");
1867 return -EINVAL;
1868 }
1869
1870 /* Configure subdevice timings, if any */
1871 ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
1872 video, s_dv_timings, timings);
1873 if (ret == -ENOIOCTLCMD) {
1874 vpif_dbg(2, debug, "Custom DV timings not supported by "
1875 "subdevice\n");
1876 return -EINVAL;
1877 }
1878 if (ret < 0) {
1879 vpif_dbg(2, debug, "Error setting custom DV timings\n");
1880 return ret;
1881 }
1882
1883 if (!(timings->bt.width && timings->bt.height &&
1884 (timings->bt.hbackporch ||
1885 timings->bt.hfrontporch ||
1886 timings->bt.hsync) &&
1887 timings->bt.vfrontporch &&
1888 (timings->bt.vbackporch ||
1889 timings->bt.vsync))) {
1890 vpif_dbg(2, debug, "Timings for width, height, "
1891 "horizontal back porch, horizontal sync, "
1892 "horizontal front porch, vertical back porch, "
1893 "vertical sync and vertical back porch "
1894 "must be defined\n");
1895 return -EINVAL;
1896 }
1897
1898 *bt = timings->bt;
1899
1900 /* Configure video port timings */
1901
1902 std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
1903 bt->hsync - 8;
1904 std_info->sav2eav = bt->width;
1905
1906 std_info->l1 = 1;
1907 std_info->l3 = bt->vsync + bt->vbackporch + 1;
1908
1909 if (bt->interlaced) {
1910 if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
1911 std_info->vsize = bt->height * 2 +
1912 bt->vfrontporch + bt->vsync + bt->vbackporch +
1913 bt->il_vfrontporch + bt->il_vsync +
1914 bt->il_vbackporch;
1915 std_info->l5 = std_info->vsize/2 -
1916 (bt->vfrontporch - 1);
1917 std_info->l7 = std_info->vsize/2 + 1;
1918 std_info->l9 = std_info->l7 + bt->il_vsync +
1919 bt->il_vbackporch + 1;
1920 std_info->l11 = std_info->vsize -
1921 (bt->il_vfrontporch - 1);
1922 } else {
1923 vpif_dbg(2, debug, "Required timing values for "
1924 "interlaced BT format missing\n");
1925 return -EINVAL;
1926 }
1927 } else {
1928 std_info->vsize = bt->height + bt->vfrontporch +
1929 bt->vsync + bt->vbackporch;
1930 std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
1931 }
1932 strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME);
1933 std_info->width = bt->width;
1934 std_info->height = bt->height;
1935 std_info->frm_fmt = bt->interlaced ? 0 : 1;
1936 std_info->ycmux_mode = 0;
1937 std_info->capture_format = 0;
1938 std_info->vbi_supported = 0;
1939 std_info->hd_sd = 1;
1940 std_info->stdid = 0;
1941 std_info->dv_preset = V4L2_DV_INVALID;
1942
1943 vid_ch->stdid = 0;
1944 vid_ch->dv_preset = V4L2_DV_INVALID;
1945 return 0;
1946}
1947
1948/**
1949 * vpif_g_dv_timings() - G_DV_TIMINGS handler
1950 * @file: file ptr
1951 * @priv: file handle
1952 * @timings: digital video timings
1953 */
1954static int vpif_g_dv_timings(struct file *file, void *priv,
1955 struct v4l2_dv_timings *timings)
1956{
1957 struct vpif_fh *fh = priv;
1958 struct channel_obj *ch = fh->channel;
1959 struct video_obj *vid_ch = &ch->video;
1960 struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
1961
1962 timings->bt = *bt;
1963
1964 return 0;
1965}
1966
1967/*
1968 * vpif_g_chip_ident() - Identify the chip
1969 * @file: file ptr
1970 * @priv: file handle
1971 * @chip: chip identity
1972 *
1973 * Returns zero or -EINVAL if read operations fails.
1974 */
1975static int vpif_g_chip_ident(struct file *file, void *priv,
1976 struct v4l2_dbg_chip_ident *chip)
1977{
1978 chip->ident = V4L2_IDENT_NONE;
1979 chip->revision = 0;
1980 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
1981 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) {
1982 vpif_dbg(2, debug, "match_type is invalid.\n");
1983 return -EINVAL;
1984 }
1985
1986 return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core,
1987 g_chip_ident, chip);
1988}
1989
1990#ifdef CONFIG_VIDEO_ADV_DEBUG
1991/*
1992 * vpif_dbg_g_register() - Read register
1993 * @file: file ptr
1994 * @priv: file handle
1995 * @reg: register to be read
1996 *
1997 * Debugging only
1998 * Returns zero or -EINVAL if read operations fails.
1999 */
2000static int vpif_dbg_g_register(struct file *file, void *priv,
2001 struct v4l2_dbg_register *reg){
2002 struct vpif_fh *fh = priv;
2003 struct channel_obj *ch = fh->channel;
2004
2005 return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
2006 g_register, reg);
2007}
2008
2009/*
2010 * vpif_dbg_s_register() - Write to register
2011 * @file: file ptr
2012 * @priv: file handle
2013 * @reg: register to be modified
2014 *
2015 * Debugging only
2016 * Returns zero or -EINVAL if write operations fails.
2017 */
2018static int vpif_dbg_s_register(struct file *file, void *priv,
2019 struct v4l2_dbg_register *reg){
2020 struct vpif_fh *fh = priv;
2021 struct channel_obj *ch = fh->channel;
2022
2023 return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
2024 s_register, reg);
2025}
2026#endif
2027
2028/*
2029 * vpif_log_status() - Status information
2030 * @file: file ptr
2031 * @priv: file handle
2032 *
2033 * Returns zero.
2034 */
2035static int vpif_log_status(struct file *filep, void *priv)
2036{
2037 /* status for sub devices */
2038 v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
2039
2040 return 0;
2041}
2042
2043/* vpif capture ioctl operations */
2044static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
2045 .vidioc_querycap = vpif_querycap,
2046 .vidioc_g_priority = vpif_g_priority,
2047 .vidioc_s_priority = vpif_s_priority,
2048 .vidioc_enum_fmt_vid_cap = vpif_enum_fmt_vid_cap,
2049 .vidioc_g_fmt_vid_cap = vpif_g_fmt_vid_cap,
2050 .vidioc_s_fmt_vid_cap = vpif_s_fmt_vid_cap,
2051 .vidioc_try_fmt_vid_cap = vpif_try_fmt_vid_cap,
2052 .vidioc_enum_input = vpif_enum_input,
2053 .vidioc_s_input = vpif_s_input,
2054 .vidioc_g_input = vpif_g_input,
2055 .vidioc_reqbufs = vpif_reqbufs,
2056 .vidioc_querybuf = vpif_querybuf,
2057 .vidioc_querystd = vpif_querystd,
2058 .vidioc_s_std = vpif_s_std,
2059 .vidioc_g_std = vpif_g_std,
2060 .vidioc_qbuf = vpif_qbuf,
2061 .vidioc_dqbuf = vpif_dqbuf,
2062 .vidioc_streamon = vpif_streamon,
2063 .vidioc_streamoff = vpif_streamoff,
2064 .vidioc_cropcap = vpif_cropcap,
2065 .vidioc_enum_dv_presets = vpif_enum_dv_presets,
2066 .vidioc_s_dv_preset = vpif_s_dv_preset,
2067 .vidioc_g_dv_preset = vpif_g_dv_preset,
2068 .vidioc_query_dv_preset = vpif_query_dv_preset,
2069 .vidioc_s_dv_timings = vpif_s_dv_timings,
2070 .vidioc_g_dv_timings = vpif_g_dv_timings,
2071 .vidioc_g_chip_ident = vpif_g_chip_ident,
2072#ifdef CONFIG_VIDEO_ADV_DEBUG
2073 .vidioc_g_register = vpif_dbg_g_register,
2074 .vidioc_s_register = vpif_dbg_s_register,
2075#endif
2076 .vidioc_log_status = vpif_log_status,
2077};
2078
2079/* vpif file operations */
2080static struct v4l2_file_operations vpif_fops = {
2081 .owner = THIS_MODULE,
2082 .open = vpif_open,
2083 .release = vpif_release,
2084 .unlocked_ioctl = video_ioctl2,
2085 .mmap = vpif_mmap,
2086 .poll = vpif_poll
2087};
2088
2089/* vpif video template */
2090static struct video_device vpif_video_template = {
2091 .name = "vpif",
2092 .fops = &vpif_fops,
2093 .minor = -1,
2094 .ioctl_ops = &vpif_ioctl_ops,
2095};
2096
2097/**
2098 * initialize_vpif() - Initialize vpif data structures
2099 *
2100 * Allocate memory for data structures and initialize them
2101 */
2102static int initialize_vpif(void)
2103{
2104 int err = 0, i, j;
2105 int free_channel_objects_index;
2106
2107 /* Default number of buffers should be 3 */
2108 if ((ch0_numbuffers > 0) &&
2109 (ch0_numbuffers < config_params.min_numbuffers))
2110 ch0_numbuffers = config_params.min_numbuffers;
2111 if ((ch1_numbuffers > 0) &&
2112 (ch1_numbuffers < config_params.min_numbuffers))
2113 ch1_numbuffers = config_params.min_numbuffers;
2114
2115 /* Set buffer size to min buffers size if it is invalid */
2116 if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
2117 ch0_bufsize =
2118 config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
2119 if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
2120 ch1_bufsize =
2121 config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
2122
2123 config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers;
2124 config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers;
2125 if (ch0_numbuffers) {
2126 config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
2127 = ch0_bufsize;
2128 }
2129 if (ch1_numbuffers) {
2130 config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
2131 = ch1_bufsize;
2132 }
2133
2134 /* Allocate memory for six channel objects */
2135 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2136 vpif_obj.dev[i] =
2137 kzalloc(sizeof(*vpif_obj.dev[i]), GFP_KERNEL);
2138 /* If memory allocation fails, return error */
2139 if (!vpif_obj.dev[i]) {
2140 free_channel_objects_index = i;
2141 err = -ENOMEM;
2142 goto vpif_init_free_channel_objects;
2143 }
2144 }
2145 return 0;
2146
2147vpif_init_free_channel_objects:
2148 for (j = 0; j < free_channel_objects_index; j++)
2149 kfree(vpif_obj.dev[j]);
2150 return err;
2151}
2152
2153/**
2154 * vpif_probe : This function probes the vpif capture driver
2155 * @pdev: platform device pointer
2156 *
2157 * This creates device entries by register itself to the V4L2 driver and
2158 * initializes fields of each channel objects
2159 */
2160static __init int vpif_probe(struct platform_device *pdev)
2161{
2162 struct vpif_subdev_info *subdevdata;
2163 struct vpif_capture_config *config;
2164 int i, j, k, m, q, err;
2165 struct i2c_adapter *i2c_adap;
2166 struct channel_obj *ch;
2167 struct common_obj *common;
2168 struct video_device *vfd;
2169 struct resource *res;
2170 int subdev_count;
2171
2172 vpif_dev = &pdev->dev;
2173
2174 err = initialize_vpif();
2175 if (err) {
2176 v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
2177 return err;
2178 }
2179
2180 k = 0;
2181 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
2182 for (i = res->start; i <= res->end; i++) {
2183 if (request_irq(i, vpif_channel_isr, IRQF_DISABLED,
2184 "DM646x_Capture",
2185 (void *)(&vpif_obj.dev[k]->channel_id))) {
2186 err = -EBUSY;
2187 i--;
2188 goto vpif_int_err;
2189 }
2190 }
2191 k++;
2192 }
2193
2194 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2195 /* Get the pointer to the channel object */
2196 ch = vpif_obj.dev[i];
2197 /* Allocate memory for video device */
2198 vfd = video_device_alloc();
2199 if (NULL == vfd) {
2200 for (j = 0; j < i; j++) {
2201 ch = vpif_obj.dev[j];
2202 video_device_release(ch->video_dev);
2203 }
2204 err = -ENOMEM;
2205 goto vpif_dev_alloc_err;
2206 }
2207
2208 /* Initialize field of video device */
2209 *vfd = vpif_video_template;
2210 vfd->v4l2_dev = &vpif_obj.v4l2_dev;
2211 vfd->release = video_device_release;
2212 snprintf(vfd->name, sizeof(vfd->name),
2213 "DM646x_VPIFCapture_DRIVER_V%s",
2214 VPIF_CAPTURE_VERSION);
2215 /* Set video_dev to the video device */
2216 ch->video_dev = vfd;
2217 }
2218
2219 for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
2220 ch = vpif_obj.dev[j];
2221 ch->channel_id = j;
2222 common = &(ch->common[VPIF_VIDEO_INDEX]);
2223 spin_lock_init(&common->irqlock);
2224 mutex_init(&common->lock);
2225 ch->video_dev->lock = &common->lock;
2226 /* Initialize prio member of channel object */
2227 v4l2_prio_init(&ch->prio);
2228 err = video_register_device(ch->video_dev,
2229 VFL_TYPE_GRABBER, (j ? 1 : 0));
2230 if (err)
2231 goto probe_out;
2232
2233 video_set_drvdata(ch->video_dev, ch);
2234
2235 }
2236
2237 i2c_adap = i2c_get_adapter(1);
2238 config = pdev->dev.platform_data;
2239
2240 subdev_count = config->subdev_count;
2241 vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
2242 GFP_KERNEL);
2243 if (vpif_obj.sd == NULL) {
2244 vpif_err("unable to allocate memory for subdevice pointers\n");
2245 err = -ENOMEM;
2246 goto probe_out;
2247 }
2248
2249 err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
2250 if (err) {
2251 v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
2252 goto probe_subdev_out;
2253 }
2254
2255 for (i = 0; i < subdev_count; i++) {
2256 subdevdata = &config->subdev_info[i];
2257 vpif_obj.sd[i] =
2258 v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
2259 i2c_adap,
2260 &subdevdata->board_info,
2261 NULL);
2262
2263 if (!vpif_obj.sd[i]) {
2264 vpif_err("Error registering v4l2 subdevice\n");
2265 goto probe_subdev_out;
2266 }
2267 v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
2268 subdevdata->name);
2269
2270 if (vpif_obj.sd[i])
2271 vpif_obj.sd[i]->grp_id = 1 << i;
2272 }
2273
2274 v4l2_info(&vpif_obj.v4l2_dev,
2275 "DM646x VPIF capture driver initialized\n");
2276 return 0;
2277
2278probe_subdev_out:
2279 /* free sub devices memory */
2280 kfree(vpif_obj.sd);
2281
2282 j = VPIF_CAPTURE_MAX_DEVICES;
2283probe_out:
2284 v4l2_device_unregister(&vpif_obj.v4l2_dev);
2285 for (k = 0; k < j; k++) {
2286 /* Get the pointer to the channel object */
2287 ch = vpif_obj.dev[k];
2288 /* Unregister video device */
2289 video_unregister_device(ch->video_dev);
2290 }
2291
2292vpif_dev_alloc_err:
2293 k = VPIF_CAPTURE_MAX_DEVICES-1;
2294 res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
2295 i = res->end;
2296
2297vpif_int_err:
2298 for (q = k; q >= 0; q--) {
2299 for (m = i; m >= (int)res->start; m--)
2300 free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));
2301
2302 res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
2303 if (res)
2304 i = res->end;
2305 }
2306 return err;
2307}
2308
2309/**
2310 * vpif_remove() - driver remove handler
2311 * @device: ptr to platform device structure
2312 *
2313 * The vidoe device is unregistered
2314 */
2315static int vpif_remove(struct platform_device *device)
2316{
2317 int i;
2318 struct channel_obj *ch;
2319
2320 v4l2_device_unregister(&vpif_obj.v4l2_dev);
2321
2322 /* un-register device */
2323 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2324 /* Get the pointer to the channel object */
2325 ch = vpif_obj.dev[i];
2326 /* Unregister video device */
2327 video_unregister_device(ch->video_dev);
2328 }
2329 return 0;
2330}
2331
2332/**
2333 * vpif_suspend: vpif device suspend
2334 *
2335 * TODO: Add suspend code here
2336 */
2337static int
2338vpif_suspend(struct device *dev)
2339{
2340 return -1;
2341}
2342
2343/**
2344 * vpif_resume: vpif device suspend
2345 *
2346 * TODO: Add resume code here
2347 */
2348static int
2349vpif_resume(struct device *dev)
2350{
2351 return -1;
2352}
2353
2354static const struct dev_pm_ops vpif_dev_pm_ops = {
2355 .suspend = vpif_suspend,
2356 .resume = vpif_resume,
2357};
2358
2359static __refdata struct platform_driver vpif_driver = {
2360 .driver = {
2361 .name = "vpif_capture",
2362 .owner = THIS_MODULE,
2363 .pm = &vpif_dev_pm_ops,
2364 },
2365 .probe = vpif_probe,
2366 .remove = vpif_remove,
2367};
2368
2369/**
2370 * vpif_init: initialize the vpif driver
2371 *
2372 * This function registers device and driver to the kernel, requests irq
2373 * handler and allocates memory
2374 * for channel objects
2375 */
2376static __init int vpif_init(void)
2377{
2378 return platform_driver_register(&vpif_driver);
2379}
2380
2381/**
2382 * vpif_cleanup : This function clean up the vpif capture resources
2383 *
2384 * This will un-registers device and driver to the kernel, frees
2385 * requested irq handler and de-allocates memory allocated for channel
2386 * objects.
2387 */
2388static void vpif_cleanup(void)
2389{
2390 struct platform_device *pdev;
2391 struct resource *res;
2392 int irq_num;
2393 int i = 0;
2394
2395 pdev = container_of(vpif_dev, struct platform_device, dev);
2396 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) {
2397 for (irq_num = res->start; irq_num <= res->end; irq_num++)
2398 free_irq(irq_num,
2399 (void *)(&vpif_obj.dev[i]->channel_id));
2400 i++;
2401 }
2402
2403 platform_driver_unregister(&vpif_driver);
2404
2405 kfree(vpif_obj.sd);
2406 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++)
2407 kfree(vpif_obj.dev[i]);
2408}
2409
2410/* Function for module initialization and cleanup */
2411module_init(vpif_init);
2412module_exit(vpif_cleanup);
diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h
new file mode 100644
index 00000000000..064550f5ce4
--- /dev/null
+++ b/drivers/media/video/davinci/vpif_capture.h
@@ -0,0 +1,162 @@
1/*
2 * Copyright (C) 2009 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#ifndef VPIF_CAPTURE_H
20#define VPIF_CAPTURE_H
21
22#ifdef __KERNEL__
23
24/* Header files */
25#include <linux/videodev2.h>
26#include <media/v4l2-common.h>
27#include <media/v4l2-device.h>
28#include <media/videobuf-core.h>
29#include <media/videobuf-dma-contig.h>
30#include <mach/dm646x.h>
31
32#include "vpif.h"
33
34/* Macros */
35#define VPIF_CAPTURE_VERSION "0.0.2"
36
37#define VPIF_VALID_FIELD(field) (((V4L2_FIELD_ANY == field) || \
38 (V4L2_FIELD_NONE == field)) || \
39 (((V4L2_FIELD_INTERLACED == field) || \
40 (V4L2_FIELD_SEQ_TB == field)) || \
41 (V4L2_FIELD_SEQ_BT == field)))
42
43#define VPIF_CAPTURE_MAX_DEVICES 2
44#define VPIF_VIDEO_INDEX 0
45#define VPIF_NUMBER_OF_OBJECTS 1
46
47/* Enumerated data type to give id to each device per channel */
48enum vpif_channel_id {
49 VPIF_CHANNEL0_VIDEO = 0,
50 VPIF_CHANNEL1_VIDEO,
51};
52
53struct video_obj {
54 enum v4l2_field buf_field;
55 /* Currently selected or default standard */
56 v4l2_std_id stdid;
57 u32 dv_preset;
58 struct v4l2_bt_timings bt_timings;
59 /* This is to track the last input that is passed to application */
60 u32 input_idx;
61};
62
63struct common_obj {
64 /* Pointer pointing to current v4l2_buffer */
65 struct videobuf_buffer *cur_frm;
66 /* Pointer pointing to current v4l2_buffer */
67 struct videobuf_buffer *next_frm;
68 /*
69 * This field keeps track of type of buffer exchange mechanism
70 * user has selected
71 */
72 enum v4l2_memory memory;
73 /* Used to store pixel format */
74 struct v4l2_format fmt;
75 /* Buffer queue used in video-buf */
76 struct videobuf_queue buffer_queue;
77 /* Queue of filled frames */
78 struct list_head dma_queue;
79 /* Used in video-buf */
80 spinlock_t irqlock;
81 /* lock used to access this structure */
82 struct mutex lock;
83 /* number of users performing IO */
84 u32 io_usrs;
85 /* Indicates whether streaming started */
86 u8 started;
87 /* Function pointer to set the addresses */
88 void (*set_addr) (unsigned long, unsigned long, unsigned long,
89 unsigned long);
90 /* offset where Y top starts from the starting of the buffer */
91 u32 ytop_off;
92 /* offset where Y bottom starts from the starting of the buffer */
93 u32 ybtm_off;
94 /* offset where C top starts from the starting of the buffer */
95 u32 ctop_off;
96 /* offset where C bottom starts from the starting of the buffer */
97 u32 cbtm_off;
98 /* Indicates width of the image data */
99 u32 width;
100 /* Indicates height of the image data */
101 u32 height;
102};
103
104struct channel_obj {
105 /* Identifies video device for this channel */
106 struct video_device *video_dev;
107 /* Used to keep track of state of the priority */
108 struct v4l2_prio_state prio;
109 /* number of open instances of the channel */
110 int usrs;
111 /* Indicates id of the field which is being displayed */
112 u32 field_id;
113 /* flag to indicate whether decoder is initialized */
114 u8 initialized;
115 /* Identifies channel */
116 enum vpif_channel_id channel_id;
117 /* index into sd table */
118 int curr_sd_index;
119 /* ptr to current sub device information */
120 struct vpif_subdev_info *curr_subdev_info;
121 /* vpif configuration params */
122 struct vpif_params vpifparams;
123 /* common object array */
124 struct common_obj common[VPIF_NUMBER_OF_OBJECTS];
125 /* video object */
126 struct video_obj video;
127};
128
129/* File handle structure */
130struct vpif_fh {
131 /* pointer to channel object for opened device */
132 struct channel_obj *channel;
133 /* Indicates whether this file handle is doing IO */
134 u8 io_allowed[VPIF_NUMBER_OF_OBJECTS];
135 /* Used to keep track priority of this instance */
136 enum v4l2_priority prio;
137 /* Used to indicate channel is initialize or not */
138 u8 initialized;
139};
140
141struct vpif_device {
142 struct v4l2_device v4l2_dev;
143 struct channel_obj *dev[VPIF_CAPTURE_NUM_CHANNELS];
144 struct v4l2_subdev **sd;
145};
146
147struct vpif_config_params {
148 u8 min_numbuffers;
149 u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS];
150 s8 device_type;
151 u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
152 u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
153 u8 default_device[VPIF_CAPTURE_NUM_CHANNELS];
154 u8 max_device_type;
155};
156/* Struct which keeps track of the line numbers for the sliced vbi service */
157struct vpif_service_line {
158 u16 service_id;
159 u16 service_line[2];
160};
161#endif /* End of __KERNEL__ */
162#endif /* VPIF_CAPTURE_H */
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
new file mode 100644
index 00000000000..286f0291004
--- /dev/null
+++ b/drivers/media/video/davinci/vpif_display.c
@@ -0,0 +1,1914 @@
1/*
2 * vpif-display - VPIF display driver
3 * Display driver for TI DaVinci VPIF
4 *
5 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation version 2.
10 *
11 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
12 * kind, whether express or implied; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/errno.h>
21#include <linux/fs.h>
22#include <linux/mm.h>
23#include <linux/interrupt.h>
24#include <linux/workqueue.h>
25#include <linux/string.h>
26#include <linux/videodev2.h>
27#include <linux/wait.h>
28#include <linux/time.h>
29#include <linux/i2c.h>
30#include <linux/platform_device.h>
31#include <linux/io.h>
32#include <linux/slab.h>
33
34#include <asm/irq.h>
35#include <asm/page.h>
36
37#include <media/adv7343.h>
38#include <media/v4l2-device.h>
39#include <media/v4l2-ioctl.h>
40#include <media/v4l2-chip-ident.h>
41
42#include <mach/dm646x.h>
43
44#include "vpif_display.h"
45#include "vpif.h"
46
47MODULE_DESCRIPTION("TI DaVinci VPIF Display driver");
48MODULE_LICENSE("GPL");
49MODULE_VERSION(VPIF_DISPLAY_VERSION);
50
51#define DM646X_V4L2_STD (V4L2_STD_525_60 | V4L2_STD_625_50)
52
53#define vpif_err(fmt, arg...) v4l2_err(&vpif_obj.v4l2_dev, fmt, ## arg)
54#define vpif_dbg(level, debug, fmt, arg...) \
55 v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
56
57static int debug = 1;
58static u32 ch2_numbuffers = 3;
59static u32 ch3_numbuffers = 3;
60static u32 ch2_bufsize = 1920 * 1080 * 2;
61static u32 ch3_bufsize = 720 * 576 * 2;
62
63module_param(debug, int, 0644);
64module_param(ch2_numbuffers, uint, S_IRUGO);
65module_param(ch3_numbuffers, uint, S_IRUGO);
66module_param(ch2_bufsize, uint, S_IRUGO);
67module_param(ch3_bufsize, uint, S_IRUGO);
68
69MODULE_PARM_DESC(debug, "Debug level 0-1");
70MODULE_PARM_DESC(ch2_numbuffers, "Channel2 buffer count (default:3)");
71MODULE_PARM_DESC(ch3_numbuffers, "Channel3 buffer count (default:3)");
72MODULE_PARM_DESC(ch2_bufsize, "Channel2 buffer size (default:1920 x 1080 x 2)");
73MODULE_PARM_DESC(ch3_bufsize, "Channel3 buffer size (default:720 x 576 x 2)");
74
75static struct vpif_config_params config_params = {
76 .min_numbuffers = 3,
77 .numbuffers[0] = 3,
78 .numbuffers[1] = 3,
79 .min_bufsize[0] = 720 * 480 * 2,
80 .min_bufsize[1] = 720 * 480 * 2,
81 .channel_bufsize[0] = 1920 * 1080 * 2,
82 .channel_bufsize[1] = 720 * 576 * 2,
83};
84
85static struct vpif_device vpif_obj = { {NULL} };
86static struct device *vpif_dev;
87
88/*
89 * vpif_uservirt_to_phys: This function is used to convert user
90 * space virtual address to physical address.
91 */
92static u32 vpif_uservirt_to_phys(u32 virtp)
93{
94 struct mm_struct *mm = current->mm;
95 unsigned long physp = 0;
96 struct vm_area_struct *vma;
97
98 vma = find_vma(mm, virtp);
99
100 /* For kernel direct-mapped memory, take the easy way */
101 if (virtp >= PAGE_OFFSET) {
102 physp = virt_to_phys((void *)virtp);
103 } else if (vma && (vma->vm_flags & VM_IO) && (vma->vm_pgoff)) {
104 /* this will catch, kernel-allocated, mmaped-to-usermode addr */
105 physp = (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
106 } else {
107 /* otherwise, use get_user_pages() for general userland pages */
108 int res, nr_pages = 1;
109 struct page *pages;
110 down_read(&current->mm->mmap_sem);
111
112 res = get_user_pages(current, current->mm,
113 virtp, nr_pages, 1, 0, &pages, NULL);
114 up_read(&current->mm->mmap_sem);
115
116 if (res == nr_pages) {
117 physp = __pa(page_address(&pages[0]) +
118 (virtp & ~PAGE_MASK));
119 } else {
120 vpif_err("get_user_pages failed\n");
121 return 0;
122 }
123 }
124
125 return physp;
126}
127
128/*
129 * buffer_prepare: This is the callback function called from videobuf_qbuf()
130 * function the buffer is prepared and user space virtual address is converted
131 * into physical address
132 */
133static int vpif_buffer_prepare(struct videobuf_queue *q,
134 struct videobuf_buffer *vb,
135 enum v4l2_field field)
136{
137 struct vpif_fh *fh = q->priv_data;
138 struct common_obj *common;
139 unsigned long addr;
140
141 common = &fh->channel->common[VPIF_VIDEO_INDEX];
142 if (VIDEOBUF_NEEDS_INIT == vb->state) {
143 vb->width = common->width;
144 vb->height = common->height;
145 vb->size = vb->width * vb->height;
146 vb->field = field;
147 }
148 vb->state = VIDEOBUF_PREPARED;
149
150 /* if user pointer memory mechanism is used, get the physical
151 * address of the buffer */
152 if (V4L2_MEMORY_USERPTR == common->memory) {
153 if (!vb->baddr) {
154 vpif_err("buffer_address is 0\n");
155 return -EINVAL;
156 }
157
158 vb->boff = vpif_uservirt_to_phys(vb->baddr);
159 if (!ISALIGNED(vb->boff))
160 goto buf_align_exit;
161 }
162
163 addr = vb->boff;
164 if (q->streaming && (V4L2_BUF_TYPE_SLICED_VBI_OUTPUT != q->type)) {
165 if (!ISALIGNED(addr + common->ytop_off) ||
166 !ISALIGNED(addr + common->ybtm_off) ||
167 !ISALIGNED(addr + common->ctop_off) ||
168 !ISALIGNED(addr + common->cbtm_off))
169 goto buf_align_exit;
170 }
171 return 0;
172
173buf_align_exit:
174 vpif_err("buffer offset not aligned to 8 bytes\n");
175 return -EINVAL;
176}
177
178/*
179 * vpif_buffer_setup: This function allocates memory for the buffers
180 */
181static int vpif_buffer_setup(struct videobuf_queue *q, unsigned int *count,
182 unsigned int *size)
183{
184 struct vpif_fh *fh = q->priv_data;
185 struct channel_obj *ch = fh->channel;
186 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
187
188 if (V4L2_MEMORY_MMAP != common->memory)
189 return 0;
190
191 *size = config_params.channel_bufsize[ch->channel_id];
192 if (*count < config_params.min_numbuffers)
193 *count = config_params.min_numbuffers;
194
195 return 0;
196}
197
198/*
199 * vpif_buffer_queue: This function adds the buffer to DMA queue
200 */
201static void vpif_buffer_queue(struct videobuf_queue *q,
202 struct videobuf_buffer *vb)
203{
204 struct vpif_fh *fh = q->priv_data;
205 struct common_obj *common;
206
207 common = &fh->channel->common[VPIF_VIDEO_INDEX];
208
209 /* add the buffer to the DMA queue */
210 list_add_tail(&vb->queue, &common->dma_queue);
211 vb->state = VIDEOBUF_QUEUED;
212}
213
214/*
215 * vpif_buffer_release: This function is called from the videobuf layer to
216 * free memory allocated to the buffers
217 */
218static void vpif_buffer_release(struct videobuf_queue *q,
219 struct videobuf_buffer *vb)
220{
221 struct vpif_fh *fh = q->priv_data;
222 struct channel_obj *ch = fh->channel;
223 struct common_obj *common;
224 unsigned int buf_size = 0;
225
226 common = &ch->common[VPIF_VIDEO_INDEX];
227
228 videobuf_dma_contig_free(q, vb);
229 vb->state = VIDEOBUF_NEEDS_INIT;
230
231 if (V4L2_MEMORY_MMAP != common->memory)
232 return;
233
234 buf_size = config_params.channel_bufsize[ch->channel_id];
235}
236
237static struct videobuf_queue_ops video_qops = {
238 .buf_setup = vpif_buffer_setup,
239 .buf_prepare = vpif_buffer_prepare,
240 .buf_queue = vpif_buffer_queue,
241 .buf_release = vpif_buffer_release,
242};
243static u8 channel_first_int[VPIF_NUMOBJECTS][2] = { {1, 1} };
244
245static void process_progressive_mode(struct common_obj *common)
246{
247 unsigned long addr = 0;
248
249 /* Get the next buffer from buffer queue */
250 common->next_frm = list_entry(common->dma_queue.next,
251 struct videobuf_buffer, queue);
252 /* Remove that buffer from the buffer queue */
253 list_del(&common->next_frm->queue);
254 /* Mark status of the buffer as active */
255 common->next_frm->state = VIDEOBUF_ACTIVE;
256
257 /* Set top and bottom field addrs in VPIF registers */
258 addr = videobuf_to_dma_contig(common->next_frm);
259 common->set_addr(addr + common->ytop_off,
260 addr + common->ybtm_off,
261 addr + common->ctop_off,
262 addr + common->cbtm_off);
263}
264
265static void process_interlaced_mode(int fid, struct common_obj *common)
266{
267 /* device field id and local field id are in sync */
268 /* If this is even field */
269 if (0 == fid) {
270 if (common->cur_frm == common->next_frm)
271 return;
272
273 /* one frame is displayed If next frame is
274 * available, release cur_frm and move on */
275 /* Copy frame display time */
276 do_gettimeofday(&common->cur_frm->ts);
277 /* Change status of the cur_frm */
278 common->cur_frm->state = VIDEOBUF_DONE;
279 /* unlock semaphore on cur_frm */
280 wake_up_interruptible(&common->cur_frm->done);
281 /* Make cur_frm pointing to next_frm */
282 common->cur_frm = common->next_frm;
283
284 } else if (1 == fid) { /* odd field */
285 if (list_empty(&common->dma_queue)
286 || (common->cur_frm != common->next_frm)) {
287 return;
288 }
289 /* one field is displayed configure the next
290 * frame if it is available else hold on current
291 * frame */
292 /* Get next from the buffer queue */
293 process_progressive_mode(common);
294
295 }
296}
297
298/*
299 * vpif_channel_isr: It changes status of the displayed buffer, takes next
300 * buffer from the queue and sets its address in VPIF registers
301 */
302static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
303{
304 struct vpif_device *dev = &vpif_obj;
305 struct channel_obj *ch;
306 struct common_obj *common;
307 enum v4l2_field field;
308 int fid = -1, i;
309 int channel_id = 0;
310
311 channel_id = *(int *)(dev_id);
312 ch = dev->dev[channel_id];
313 field = ch->common[VPIF_VIDEO_INDEX].fmt.fmt.pix.field;
314 for (i = 0; i < VPIF_NUMOBJECTS; i++) {
315 common = &ch->common[i];
316 /* If streaming is started in this channel */
317 if (0 == common->started)
318 continue;
319
320 if (1 == ch->vpifparams.std_info.frm_fmt) {
321 if (list_empty(&common->dma_queue))
322 continue;
323
324 /* Progressive mode */
325 if (!channel_first_int[i][channel_id]) {
326 /* Mark status of the cur_frm to
327 * done and unlock semaphore on it */
328 do_gettimeofday(&common->cur_frm->ts);
329 common->cur_frm->state = VIDEOBUF_DONE;
330 wake_up_interruptible(&common->cur_frm->done);
331 /* Make cur_frm pointing to next_frm */
332 common->cur_frm = common->next_frm;
333 }
334
335 channel_first_int[i][channel_id] = 0;
336 process_progressive_mode(common);
337 } else {
338 /* Interlaced mode */
339 /* If it is first interrupt, ignore it */
340
341 if (channel_first_int[i][channel_id]) {
342 channel_first_int[i][channel_id] = 0;
343 continue;
344 }
345
346 if (0 == i) {
347 ch->field_id ^= 1;
348 /* Get field id from VPIF registers */
349 fid = vpif_channel_getfid(ch->channel_id + 2);
350 /* If fid does not match with stored field id */
351 if (fid != ch->field_id) {
352 /* Make them in sync */
353 if (0 == fid)
354 ch->field_id = fid;
355
356 return IRQ_HANDLED;
357 }
358 }
359 process_interlaced_mode(fid, common);
360 }
361 }
362
363 return IRQ_HANDLED;
364}
365
366static int vpif_update_std_info(struct channel_obj *ch)
367{
368 struct video_obj *vid_ch = &ch->video;
369 struct vpif_params *vpifparams = &ch->vpifparams;
370 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
371 const struct vpif_channel_config_params *config;
372
373 int i;
374
375 for (i = 0; i < vpif_ch_params_count; i++) {
376 config = &ch_params[i];
377 if (config->hd_sd == 0) {
378 vpif_dbg(2, debug, "SD format\n");
379 if (config->stdid & vid_ch->stdid) {
380 memcpy(std_info, config, sizeof(*config));
381 break;
382 }
383 } else {
384 vpif_dbg(2, debug, "HD format\n");
385 if (config->dv_preset == vid_ch->dv_preset) {
386 memcpy(std_info, config, sizeof(*config));
387 break;
388 }
389 }
390 }
391
392 if (i == vpif_ch_params_count) {
393 vpif_dbg(1, debug, "Format not found\n");
394 return -EINVAL;
395 }
396
397 return 0;
398}
399
400static int vpif_update_resolution(struct channel_obj *ch)
401{
402 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
403 struct video_obj *vid_ch = &ch->video;
404 struct vpif_params *vpifparams = &ch->vpifparams;
405 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
406
407 if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height)
408 return -EINVAL;
409
410 if (vid_ch->stdid || vid_ch->dv_preset) {
411 if (vpif_update_std_info(ch))
412 return -EINVAL;
413 }
414
415 common->fmt.fmt.pix.width = std_info->width;
416 common->fmt.fmt.pix.height = std_info->height;
417 vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n",
418 common->fmt.fmt.pix.width, common->fmt.fmt.pix.height);
419
420 /* Set height and width paramateres */
421 common->height = std_info->height;
422 common->width = std_info->width;
423
424 return 0;
425}
426
427/*
428 * vpif_calculate_offsets: This function calculates buffers offset for Y and C
429 * in the top and bottom field
430 */
431static void vpif_calculate_offsets(struct channel_obj *ch)
432{
433 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
434 struct vpif_params *vpifparams = &ch->vpifparams;
435 enum v4l2_field field = common->fmt.fmt.pix.field;
436 struct video_obj *vid_ch = &ch->video;
437 unsigned int hpitch, vpitch, sizeimage;
438
439 if (V4L2_FIELD_ANY == common->fmt.fmt.pix.field) {
440 if (ch->vpifparams.std_info.frm_fmt)
441 vid_ch->buf_field = V4L2_FIELD_NONE;
442 else
443 vid_ch->buf_field = V4L2_FIELD_INTERLACED;
444 } else {
445 vid_ch->buf_field = common->fmt.fmt.pix.field;
446 }
447
448 if (V4L2_MEMORY_USERPTR == common->memory)
449 sizeimage = common->fmt.fmt.pix.sizeimage;
450 else
451 sizeimage = config_params.channel_bufsize[ch->channel_id];
452
453 hpitch = common->fmt.fmt.pix.bytesperline;
454 vpitch = sizeimage / (hpitch * 2);
455 if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||
456 (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) {
457 common->ytop_off = 0;
458 common->ybtm_off = hpitch;
459 common->ctop_off = sizeimage / 2;
460 common->cbtm_off = sizeimage / 2 + hpitch;
461 } else if (V4L2_FIELD_SEQ_TB == vid_ch->buf_field) {
462 common->ytop_off = 0;
463 common->ybtm_off = sizeimage / 4;
464 common->ctop_off = sizeimage / 2;
465 common->cbtm_off = common->ctop_off + sizeimage / 4;
466 } else if (V4L2_FIELD_SEQ_BT == vid_ch->buf_field) {
467 common->ybtm_off = 0;
468 common->ytop_off = sizeimage / 4;
469 common->cbtm_off = sizeimage / 2;
470 common->ctop_off = common->cbtm_off + sizeimage / 4;
471 }
472
473 if ((V4L2_FIELD_NONE == vid_ch->buf_field) ||
474 (V4L2_FIELD_INTERLACED == vid_ch->buf_field)) {
475 vpifparams->video_params.storage_mode = 1;
476 } else {
477 vpifparams->video_params.storage_mode = 0;
478 }
479
480 if (ch->vpifparams.std_info.frm_fmt == 1) {
481 vpifparams->video_params.hpitch =
482 common->fmt.fmt.pix.bytesperline;
483 } else {
484 if ((field == V4L2_FIELD_ANY) ||
485 (field == V4L2_FIELD_INTERLACED))
486 vpifparams->video_params.hpitch =
487 common->fmt.fmt.pix.bytesperline * 2;
488 else
489 vpifparams->video_params.hpitch =
490 common->fmt.fmt.pix.bytesperline;
491 }
492
493 ch->vpifparams.video_params.stdid = ch->vpifparams.std_info.stdid;
494}
495
496static void vpif_config_format(struct channel_obj *ch)
497{
498 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
499
500 common->fmt.fmt.pix.field = V4L2_FIELD_ANY;
501 if (config_params.numbuffers[ch->channel_id] == 0)
502 common->memory = V4L2_MEMORY_USERPTR;
503 else
504 common->memory = V4L2_MEMORY_MMAP;
505
506 common->fmt.fmt.pix.sizeimage =
507 config_params.channel_bufsize[ch->channel_id];
508 common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
509 common->fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
510}
511
512static int vpif_check_format(struct channel_obj *ch,
513 struct v4l2_pix_format *pixfmt)
514{
515 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
516 enum v4l2_field field = pixfmt->field;
517 u32 sizeimage, hpitch, vpitch;
518
519 if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P)
520 goto invalid_fmt_exit;
521
522 if (!(VPIF_VALID_FIELD(field)))
523 goto invalid_fmt_exit;
524
525 if (pixfmt->bytesperline <= 0)
526 goto invalid_pitch_exit;
527
528 if (V4L2_MEMORY_USERPTR == common->memory)
529 sizeimage = pixfmt->sizeimage;
530 else
531 sizeimage = config_params.channel_bufsize[ch->channel_id];
532
533 if (vpif_update_resolution(ch))
534 return -EINVAL;
535
536 hpitch = pixfmt->bytesperline;
537 vpitch = sizeimage / (hpitch * 2);
538
539 /* Check for valid value of pitch */
540 if ((hpitch < ch->vpifparams.std_info.width) ||
541 (vpitch < ch->vpifparams.std_info.height))
542 goto invalid_pitch_exit;
543
544 /* Check for 8 byte alignment */
545 if (!ISALIGNED(hpitch)) {
546 vpif_err("invalid pitch alignment\n");
547 return -EINVAL;
548 }
549 pixfmt->width = common->fmt.fmt.pix.width;
550 pixfmt->height = common->fmt.fmt.pix.height;
551
552 return 0;
553
554invalid_fmt_exit:
555 vpif_err("invalid field format\n");
556 return -EINVAL;
557
558invalid_pitch_exit:
559 vpif_err("invalid pitch\n");
560 return -EINVAL;
561}
562
563static void vpif_config_addr(struct channel_obj *ch, int muxmode)
564{
565 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
566
567 if (VPIF_CHANNEL3_VIDEO == ch->channel_id) {
568 common->set_addr = ch3_set_videobuf_addr;
569 } else {
570 if (2 == muxmode)
571 common->set_addr = ch2_set_videobuf_addr_yc_nmux;
572 else
573 common->set_addr = ch2_set_videobuf_addr;
574 }
575}
576
577/*
578 * vpif_mmap: It is used to map kernel space buffers into user spaces
579 */
580static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
581{
582 struct vpif_fh *fh = filep->private_data;
583 struct channel_obj *ch = fh->channel;
584 struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
585
586 vpif_dbg(2, debug, "vpif_mmap\n");
587
588 return videobuf_mmap_mapper(&common->buffer_queue, vma);
589}
590
591/*
592 * vpif_poll: It is used for select/poll system call
593 */
594static unsigned int vpif_poll(struct file *filep, poll_table *wait)
595{
596 struct vpif_fh *fh = filep->private_data;
597 struct channel_obj *ch = fh->channel;
598 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
599
600 if (common->started)
601 return videobuf_poll_stream(filep, &common->buffer_queue, wait);
602
603 return 0;
604}
605
606/*
607 * vpif_open: It creates object of file handle structure and stores it in
608 * private_data member of filepointer
609 */
610static int vpif_open(struct file *filep)
611{
612 struct video_device *vdev = video_devdata(filep);
613 struct channel_obj *ch = NULL;
614 struct vpif_fh *fh = NULL;
615
616 ch = video_get_drvdata(vdev);
617 /* Allocate memory for the file handle object */
618 fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
619 if (fh == NULL) {
620 vpif_err("unable to allocate memory for file handle object\n");
621 return -ENOMEM;
622 }
623
624 /* store pointer to fh in private_data member of filep */
625 filep->private_data = fh;
626 fh->channel = ch;
627 fh->initialized = 0;
628 if (!ch->initialized) {
629 fh->initialized = 1;
630 ch->initialized = 1;
631 memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
632 }
633
634 /* Increment channel usrs counter */
635 atomic_inc(&ch->usrs);
636 /* Set io_allowed[VPIF_VIDEO_INDEX] member to false */
637 fh->io_allowed[VPIF_VIDEO_INDEX] = 0;
638 /* Initialize priority of this instance to default priority */
639 fh->prio = V4L2_PRIORITY_UNSET;
640 v4l2_prio_open(&ch->prio, &fh->prio);
641
642 return 0;
643}
644
645/*
646 * vpif_release: This function deletes buffer queue, frees the buffers and
647 * the vpif file handle
648 */
649static int vpif_release(struct file *filep)
650{
651 struct vpif_fh *fh = filep->private_data;
652 struct channel_obj *ch = fh->channel;
653 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
654
655 /* if this instance is doing IO */
656 if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
657 /* Reset io_usrs member of channel object */
658 common->io_usrs = 0;
659 /* Disable channel */
660 if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
661 enable_channel2(0);
662 channel2_intr_enable(0);
663 }
664 if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
665 (2 == common->started)) {
666 enable_channel3(0);
667 channel3_intr_enable(0);
668 }
669 common->started = 0;
670 /* Free buffers allocated */
671 videobuf_queue_cancel(&common->buffer_queue);
672 videobuf_mmap_free(&common->buffer_queue);
673 common->numbuffers =
674 config_params.numbuffers[ch->channel_id];
675 }
676
677 /* Decrement channel usrs counter */
678 atomic_dec(&ch->usrs);
679 /* If this file handle has initialize encoder device, reset it */
680 if (fh->initialized)
681 ch->initialized = 0;
682
683 /* Close the priority */
684 v4l2_prio_close(&ch->prio, fh->prio);
685 filep->private_data = NULL;
686 fh->initialized = 0;
687 kfree(fh);
688
689 return 0;
690}
691
692/* functions implementing ioctls */
693/**
694 * vpif_querycap() - QUERYCAP handler
695 * @file: file ptr
696 * @priv: file handle
697 * @cap: ptr to v4l2_capability structure
698 */
699static int vpif_querycap(struct file *file, void *priv,
700 struct v4l2_capability *cap)
701{
702 struct vpif_display_config *config = vpif_dev->platform_data;
703
704 cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
705 strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
706 strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
707 strlcpy(cap->card, config->card_name, sizeof(cap->card));
708
709 return 0;
710}
711
712static int vpif_enum_fmt_vid_out(struct file *file, void *priv,
713 struct v4l2_fmtdesc *fmt)
714{
715 if (fmt->index != 0) {
716 vpif_err("Invalid format index\n");
717 return -EINVAL;
718 }
719
720 /* Fill in the information about format */
721 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
722 strcpy(fmt->description, "YCbCr4:2:2 YC Planar");
723 fmt->pixelformat = V4L2_PIX_FMT_YUV422P;
724
725 return 0;
726}
727
728static int vpif_g_fmt_vid_out(struct file *file, void *priv,
729 struct v4l2_format *fmt)
730{
731 struct vpif_fh *fh = priv;
732 struct channel_obj *ch = fh->channel;
733 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
734
735 /* Check the validity of the buffer type */
736 if (common->fmt.type != fmt->type)
737 return -EINVAL;
738
739 if (vpif_update_resolution(ch))
740 return -EINVAL;
741 *fmt = common->fmt;
742 return 0;
743}
744
745static int vpif_s_fmt_vid_out(struct file *file, void *priv,
746 struct v4l2_format *fmt)
747{
748 struct vpif_fh *fh = priv;
749 struct v4l2_pix_format *pixfmt;
750 struct channel_obj *ch = fh->channel;
751 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
752 int ret = 0;
753
754 if ((VPIF_CHANNEL2_VIDEO == ch->channel_id)
755 || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) {
756 if (!fh->initialized) {
757 vpif_dbg(1, debug, "Channel Busy\n");
758 return -EBUSY;
759 }
760
761 /* Check for the priority */
762 ret = v4l2_prio_check(&ch->prio, fh->prio);
763 if (0 != ret)
764 return ret;
765 fh->initialized = 1;
766 }
767
768 if (common->started) {
769 vpif_dbg(1, debug, "Streaming in progress\n");
770 return -EBUSY;
771 }
772
773 pixfmt = &fmt->fmt.pix;
774 /* Check for valid field format */
775 ret = vpif_check_format(ch, pixfmt);
776 if (ret)
777 return ret;
778
779 /* store the pix format in the channel object */
780 common->fmt.fmt.pix = *pixfmt;
781 /* store the format in the channel object */
782 common->fmt = *fmt;
783 return 0;
784}
785
786static int vpif_try_fmt_vid_out(struct file *file, void *priv,
787 struct v4l2_format *fmt)
788{
789 struct vpif_fh *fh = priv;
790 struct channel_obj *ch = fh->channel;
791 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
792 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
793 int ret = 0;
794
795 ret = vpif_check_format(ch, pixfmt);
796 if (ret) {
797 *pixfmt = common->fmt.fmt.pix;
798 pixfmt->sizeimage = pixfmt->width * pixfmt->height * 2;
799 }
800
801 return ret;
802}
803
804static int vpif_reqbufs(struct file *file, void *priv,
805 struct v4l2_requestbuffers *reqbuf)
806{
807 struct vpif_fh *fh = priv;
808 struct channel_obj *ch = fh->channel;
809 struct common_obj *common;
810 enum v4l2_field field;
811 u8 index = 0;
812
813 /* This file handle has not initialized the channel,
814 It is not allowed to do settings */
815 if ((VPIF_CHANNEL2_VIDEO == ch->channel_id)
816 || (VPIF_CHANNEL3_VIDEO == ch->channel_id)) {
817 if (!fh->initialized) {
818 vpif_err("Channel Busy\n");
819 return -EBUSY;
820 }
821 }
822
823 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != reqbuf->type)
824 return -EINVAL;
825
826 index = VPIF_VIDEO_INDEX;
827
828 common = &ch->common[index];
829
830 if (common->fmt.type != reqbuf->type)
831 return -EINVAL;
832
833 if (0 != common->io_usrs)
834 return -EBUSY;
835
836 if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
837 if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY)
838 field = V4L2_FIELD_INTERLACED;
839 else
840 field = common->fmt.fmt.pix.field;
841 } else {
842 field = V4L2_VBI_INTERLACED;
843 }
844
845 /* Initialize videobuf queue as per the buffer type */
846 videobuf_queue_dma_contig_init(&common->buffer_queue,
847 &video_qops, NULL,
848 &common->irqlock,
849 reqbuf->type, field,
850 sizeof(struct videobuf_buffer), fh,
851 &common->lock);
852
853 /* Set io allowed member of file handle to TRUE */
854 fh->io_allowed[index] = 1;
855 /* Increment io usrs member of channel object to 1 */
856 common->io_usrs = 1;
857 /* Store type of memory requested in channel object */
858 common->memory = reqbuf->memory;
859 INIT_LIST_HEAD(&common->dma_queue);
860
861 /* Allocate buffers */
862 return videobuf_reqbufs(&common->buffer_queue, reqbuf);
863}
864
865static int vpif_querybuf(struct file *file, void *priv,
866 struct v4l2_buffer *tbuf)
867{
868 struct vpif_fh *fh = priv;
869 struct channel_obj *ch = fh->channel;
870 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
871
872 if (common->fmt.type != tbuf->type)
873 return -EINVAL;
874
875 return videobuf_querybuf(&common->buffer_queue, tbuf);
876}
877
878static int vpif_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
879{
880
881 struct vpif_fh *fh = priv;
882 struct channel_obj *ch = fh->channel;
883 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
884 struct v4l2_buffer tbuf = *buf;
885 struct videobuf_buffer *buf1;
886 unsigned long addr = 0;
887 unsigned long flags;
888 int ret = 0;
889
890 if (common->fmt.type != tbuf.type)
891 return -EINVAL;
892
893 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
894 vpif_err("fh->io_allowed\n");
895 return -EACCES;
896 }
897
898 if (!(list_empty(&common->dma_queue)) ||
899 (common->cur_frm != common->next_frm) ||
900 !(common->started) ||
901 (common->started && (0 == ch->field_id)))
902 return videobuf_qbuf(&common->buffer_queue, buf);
903
904 /* bufferqueue is empty store buffer address in VPIF registers */
905 mutex_lock(&common->buffer_queue.vb_lock);
906 buf1 = common->buffer_queue.bufs[tbuf.index];
907 if (buf1->memory != tbuf.memory) {
908 vpif_err("invalid buffer type\n");
909 goto qbuf_exit;
910 }
911
912 if ((buf1->state == VIDEOBUF_QUEUED) ||
913 (buf1->state == VIDEOBUF_ACTIVE)) {
914 vpif_err("invalid state\n");
915 goto qbuf_exit;
916 }
917
918 switch (buf1->memory) {
919 case V4L2_MEMORY_MMAP:
920 if (buf1->baddr == 0)
921 goto qbuf_exit;
922 break;
923
924 case V4L2_MEMORY_USERPTR:
925 if (tbuf.length < buf1->bsize)
926 goto qbuf_exit;
927
928 if ((VIDEOBUF_NEEDS_INIT != buf1->state)
929 && (buf1->baddr != tbuf.m.userptr)) {
930 vpif_buffer_release(&common->buffer_queue, buf1);
931 buf1->baddr = tbuf.m.userptr;
932 }
933 break;
934
935 default:
936 goto qbuf_exit;
937 }
938
939 local_irq_save(flags);
940 ret = vpif_buffer_prepare(&common->buffer_queue, buf1,
941 common->buffer_queue.field);
942 if (ret < 0) {
943 local_irq_restore(flags);
944 goto qbuf_exit;
945 }
946
947 buf1->state = VIDEOBUF_ACTIVE;
948 addr = buf1->boff;
949 common->next_frm = buf1;
950 if (tbuf.type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
951 common->set_addr((addr + common->ytop_off),
952 (addr + common->ybtm_off),
953 (addr + common->ctop_off),
954 (addr + common->cbtm_off));
955 }
956
957 local_irq_restore(flags);
958 list_add_tail(&buf1->stream, &common->buffer_queue.stream);
959 mutex_unlock(&common->buffer_queue.vb_lock);
960 return 0;
961
962qbuf_exit:
963 mutex_unlock(&common->buffer_queue.vb_lock);
964 return -EINVAL;
965}
966
967static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
968{
969 struct vpif_fh *fh = priv;
970 struct channel_obj *ch = fh->channel;
971 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
972 int ret = 0;
973
974 if (!(*std_id & DM646X_V4L2_STD))
975 return -EINVAL;
976
977 if (common->started) {
978 vpif_err("streaming in progress\n");
979 return -EBUSY;
980 }
981
982 /* Call encoder subdevice function to set the standard */
983 ch->video.stdid = *std_id;
984 ch->video.dv_preset = V4L2_DV_INVALID;
985 memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
986
987 /* Get the information about the standard */
988 if (vpif_update_resolution(ch))
989 return -EINVAL;
990
991 if ((ch->vpifparams.std_info.width *
992 ch->vpifparams.std_info.height * 2) >
993 config_params.channel_bufsize[ch->channel_id]) {
994 vpif_err("invalid std for this size\n");
995 return -EINVAL;
996 }
997
998 common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width;
999 /* Configure the default format information */
1000 vpif_config_format(ch);
1001
1002 ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
1003 s_std_output, *std_id);
1004 if (ret < 0) {
1005 vpif_err("Failed to set output standard\n");
1006 return ret;
1007 }
1008
1009 ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core,
1010 s_std, *std_id);
1011 if (ret < 0)
1012 vpif_err("Failed to set standard for sub devices\n");
1013 return ret;
1014}
1015
1016static int vpif_g_std(struct file *file, void *priv, v4l2_std_id *std)
1017{
1018 struct vpif_fh *fh = priv;
1019 struct channel_obj *ch = fh->channel;
1020
1021 *std = ch->video.stdid;
1022 return 0;
1023}
1024
1025static int vpif_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
1026{
1027 struct vpif_fh *fh = priv;
1028 struct channel_obj *ch = fh->channel;
1029 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1030
1031 return videobuf_dqbuf(&common->buffer_queue, p,
1032 (file->f_flags & O_NONBLOCK));
1033}
1034
1035static int vpif_streamon(struct file *file, void *priv,
1036 enum v4l2_buf_type buftype)
1037{
1038 struct vpif_fh *fh = priv;
1039 struct channel_obj *ch = fh->channel;
1040 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1041 struct channel_obj *oth_ch = vpif_obj.dev[!ch->channel_id];
1042 struct vpif_params *vpif = &ch->vpifparams;
1043 struct vpif_display_config *vpif_config_data =
1044 vpif_dev->platform_data;
1045 unsigned long addr = 0;
1046 int ret = 0;
1047
1048 if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1049 vpif_err("buffer type not supported\n");
1050 return -EINVAL;
1051 }
1052
1053 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
1054 vpif_err("fh->io_allowed\n");
1055 return -EACCES;
1056 }
1057
1058 /* If Streaming is already started, return error */
1059 if (common->started) {
1060 vpif_err("channel->started\n");
1061 return -EBUSY;
1062 }
1063
1064 if ((ch->channel_id == VPIF_CHANNEL2_VIDEO
1065 && oth_ch->common[VPIF_VIDEO_INDEX].started &&
1066 ch->vpifparams.std_info.ycmux_mode == 0)
1067 || ((ch->channel_id == VPIF_CHANNEL3_VIDEO)
1068 && (2 == oth_ch->common[VPIF_VIDEO_INDEX].started))) {
1069 vpif_err("other channel is using\n");
1070 return -EBUSY;
1071 }
1072
1073 ret = vpif_check_format(ch, &common->fmt.fmt.pix);
1074 if (ret < 0)
1075 return ret;
1076
1077 /* Call videobuf_streamon to start streaming in videobuf */
1078 ret = videobuf_streamon(&common->buffer_queue);
1079 if (ret < 0) {
1080 vpif_err("videobuf_streamon\n");
1081 return ret;
1082 }
1083
1084 /* If buffer queue is empty, return error */
1085 if (list_empty(&common->dma_queue)) {
1086 vpif_err("buffer queue is empty\n");
1087 return -EIO;
1088 }
1089
1090 /* Get the next frame from the buffer queue */
1091 common->next_frm = common->cur_frm =
1092 list_entry(common->dma_queue.next,
1093 struct videobuf_buffer, queue);
1094
1095 list_del(&common->cur_frm->queue);
1096 /* Mark state of the current frame to active */
1097 common->cur_frm->state = VIDEOBUF_ACTIVE;
1098
1099 /* Initialize field_id and started member */
1100 ch->field_id = 0;
1101 common->started = 1;
1102 if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1103 addr = common->cur_frm->boff;
1104 /* Calculate the offset for Y and C data in the buffer */
1105 vpif_calculate_offsets(ch);
1106
1107 if ((ch->vpifparams.std_info.frm_fmt &&
1108 ((common->fmt.fmt.pix.field != V4L2_FIELD_NONE)
1109 && (common->fmt.fmt.pix.field != V4L2_FIELD_ANY)))
1110 || (!ch->vpifparams.std_info.frm_fmt
1111 && (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
1112 vpif_err("conflict in field format and std format\n");
1113 return -EINVAL;
1114 }
1115
1116 /* clock settings */
1117 ret =
1118 vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode,
1119 ch->vpifparams.std_info.hd_sd);
1120 if (ret < 0) {
1121 vpif_err("can't set clock\n");
1122 return ret;
1123 }
1124
1125 /* set the parameters and addresses */
1126 ret = vpif_set_video_params(vpif, ch->channel_id + 2);
1127 if (ret < 0)
1128 return ret;
1129
1130 common->started = ret;
1131 vpif_config_addr(ch, ret);
1132 common->set_addr((addr + common->ytop_off),
1133 (addr + common->ybtm_off),
1134 (addr + common->ctop_off),
1135 (addr + common->cbtm_off));
1136
1137 /* Set interrupt for both the fields in VPIF
1138 Register enable channel in VPIF register */
1139 if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
1140 channel2_intr_assert();
1141 channel2_intr_enable(1);
1142 enable_channel2(1);
1143 }
1144
1145 if ((VPIF_CHANNEL3_VIDEO == ch->channel_id)
1146 || (common->started == 2)) {
1147 channel3_intr_assert();
1148 channel3_intr_enable(1);
1149 enable_channel3(1);
1150 }
1151 channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
1152 }
1153 return ret;
1154}
1155
1156static int vpif_streamoff(struct file *file, void *priv,
1157 enum v4l2_buf_type buftype)
1158{
1159 struct vpif_fh *fh = priv;
1160 struct channel_obj *ch = fh->channel;
1161 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1162
1163 if (buftype != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1164 vpif_err("buffer type not supported\n");
1165 return -EINVAL;
1166 }
1167
1168 if (!fh->io_allowed[VPIF_VIDEO_INDEX]) {
1169 vpif_err("fh->io_allowed\n");
1170 return -EACCES;
1171 }
1172
1173 if (!common->started) {
1174 vpif_err("channel->started\n");
1175 return -EINVAL;
1176 }
1177
1178 if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1179 /* disable channel */
1180 if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
1181 enable_channel2(0);
1182 channel2_intr_enable(0);
1183 }
1184 if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
1185 (2 == common->started)) {
1186 enable_channel3(0);
1187 channel3_intr_enable(0);
1188 }
1189 }
1190
1191 common->started = 0;
1192 return videobuf_streamoff(&common->buffer_queue);
1193}
1194
1195static int vpif_cropcap(struct file *file, void *priv,
1196 struct v4l2_cropcap *crop)
1197{
1198 struct vpif_fh *fh = priv;
1199 struct channel_obj *ch = fh->channel;
1200 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1201 if (V4L2_BUF_TYPE_VIDEO_OUTPUT != crop->type)
1202 return -EINVAL;
1203
1204 crop->bounds.left = crop->bounds.top = 0;
1205 crop->defrect.left = crop->defrect.top = 0;
1206 crop->defrect.height = crop->bounds.height = common->height;
1207 crop->defrect.width = crop->bounds.width = common->width;
1208
1209 return 0;
1210}
1211
1212static int vpif_enum_output(struct file *file, void *fh,
1213 struct v4l2_output *output)
1214{
1215
1216 struct vpif_display_config *config = vpif_dev->platform_data;
1217
1218 if (output->index >= config->output_count) {
1219 vpif_dbg(1, debug, "Invalid output index\n");
1220 return -EINVAL;
1221 }
1222
1223 strcpy(output->name, config->output[output->index]);
1224 output->type = V4L2_OUTPUT_TYPE_ANALOG;
1225 output->std = DM646X_V4L2_STD;
1226
1227 return 0;
1228}
1229
1230static int vpif_s_output(struct file *file, void *priv, unsigned int i)
1231{
1232 struct vpif_fh *fh = priv;
1233 struct channel_obj *ch = fh->channel;
1234 struct video_obj *vid_ch = &ch->video;
1235 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1236 int ret = 0;
1237
1238 if (common->started) {
1239 vpif_err("Streaming in progress\n");
1240 return -EBUSY;
1241 }
1242
1243 ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
1244 s_routing, 0, i, 0);
1245
1246 if (ret < 0)
1247 vpif_err("Failed to set output standard\n");
1248
1249 vid_ch->output_id = i;
1250 return ret;
1251}
1252
1253static int vpif_g_output(struct file *file, void *priv, unsigned int *i)
1254{
1255 struct vpif_fh *fh = priv;
1256 struct channel_obj *ch = fh->channel;
1257 struct video_obj *vid_ch = &ch->video;
1258
1259 *i = vid_ch->output_id;
1260
1261 return 0;
1262}
1263
1264static int vpif_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
1265{
1266 struct vpif_fh *fh = priv;
1267 struct channel_obj *ch = fh->channel;
1268
1269 *p = v4l2_prio_max(&ch->prio);
1270
1271 return 0;
1272}
1273
1274static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p)
1275{
1276 struct vpif_fh *fh = priv;
1277 struct channel_obj *ch = fh->channel;
1278
1279 return v4l2_prio_change(&ch->prio, &fh->prio, p);
1280}
1281
1282/**
1283 * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
1284 * @file: file ptr
1285 * @priv: file handle
1286 * @preset: input preset
1287 */
1288static int vpif_enum_dv_presets(struct file *file, void *priv,
1289 struct v4l2_dv_enum_preset *preset)
1290{
1291 struct vpif_fh *fh = priv;
1292 struct channel_obj *ch = fh->channel;
1293 struct video_obj *vid_ch = &ch->video;
1294
1295 return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
1296 video, enum_dv_presets, preset);
1297}
1298
1299/**
1300 * vpif_s_dv_presets() - S_DV_PRESETS handler
1301 * @file: file ptr
1302 * @priv: file handle
1303 * @preset: input preset
1304 */
1305static int vpif_s_dv_preset(struct file *file, void *priv,
1306 struct v4l2_dv_preset *preset)
1307{
1308 struct vpif_fh *fh = priv;
1309 struct channel_obj *ch = fh->channel;
1310 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
1311 struct video_obj *vid_ch = &ch->video;
1312 int ret = 0;
1313
1314 if (common->started) {
1315 vpif_dbg(1, debug, "streaming in progress\n");
1316 return -EBUSY;
1317 }
1318
1319 ret = v4l2_prio_check(&ch->prio, fh->prio);
1320 if (ret != 0)
1321 return ret;
1322
1323 fh->initialized = 1;
1324
1325 /* Call encoder subdevice function to set the standard */
1326 if (mutex_lock_interruptible(&common->lock))
1327 return -ERESTARTSYS;
1328
1329 ch->video.dv_preset = preset->preset;
1330 ch->video.stdid = V4L2_STD_UNKNOWN;
1331 memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
1332
1333 /* Get the information about the standard */
1334 if (vpif_update_resolution(ch)) {
1335 ret = -EINVAL;
1336 } else {
1337 /* Configure the default format information */
1338 vpif_config_format(ch);
1339
1340 ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
1341 video, s_dv_preset, preset);
1342 }
1343
1344 mutex_unlock(&common->lock);
1345
1346 return ret;
1347}
1348/**
1349 * vpif_g_dv_presets() - G_DV_PRESETS handler
1350 * @file: file ptr
1351 * @priv: file handle
1352 * @preset: input preset
1353 */
1354static int vpif_g_dv_preset(struct file *file, void *priv,
1355 struct v4l2_dv_preset *preset)
1356{
1357 struct vpif_fh *fh = priv;
1358 struct channel_obj *ch = fh->channel;
1359
1360 preset->preset = ch->video.dv_preset;
1361
1362 return 0;
1363}
1364/**
1365 * vpif_s_dv_timings() - S_DV_TIMINGS handler
1366 * @file: file ptr
1367 * @priv: file handle
1368 * @timings: digital video timings
1369 */
1370static int vpif_s_dv_timings(struct file *file, void *priv,
1371 struct v4l2_dv_timings *timings)
1372{
1373 struct vpif_fh *fh = priv;
1374 struct channel_obj *ch = fh->channel;
1375 struct vpif_params *vpifparams = &ch->vpifparams;
1376 struct vpif_channel_config_params *std_info = &vpifparams->std_info;
1377 struct video_obj *vid_ch = &ch->video;
1378 struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
1379 int ret;
1380
1381 if (timings->type != V4L2_DV_BT_656_1120) {
1382 vpif_dbg(2, debug, "Timing type not defined\n");
1383 return -EINVAL;
1384 }
1385
1386 /* Configure subdevice timings, if any */
1387 ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
1388 video, s_dv_timings, timings);
1389 if (ret == -ENOIOCTLCMD) {
1390 vpif_dbg(2, debug, "Custom DV timings not supported by "
1391 "subdevice\n");
1392 return -EINVAL;
1393 }
1394 if (ret < 0) {
1395 vpif_dbg(2, debug, "Error setting custom DV timings\n");
1396 return ret;
1397 }
1398
1399 if (!(timings->bt.width && timings->bt.height &&
1400 (timings->bt.hbackporch ||
1401 timings->bt.hfrontporch ||
1402 timings->bt.hsync) &&
1403 timings->bt.vfrontporch &&
1404 (timings->bt.vbackporch ||
1405 timings->bt.vsync))) {
1406 vpif_dbg(2, debug, "Timings for width, height, "
1407 "horizontal back porch, horizontal sync, "
1408 "horizontal front porch, vertical back porch, "
1409 "vertical sync and vertical back porch "
1410 "must be defined\n");
1411 return -EINVAL;
1412 }
1413
1414 *bt = timings->bt;
1415
1416 /* Configure video port timings */
1417
1418 std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
1419 bt->hsync - 8;
1420 std_info->sav2eav = bt->width;
1421
1422 std_info->l1 = 1;
1423 std_info->l3 = bt->vsync + bt->vbackporch + 1;
1424
1425 if (bt->interlaced) {
1426 if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
1427 std_info->vsize = bt->height * 2 +
1428 bt->vfrontporch + bt->vsync + bt->vbackporch +
1429 bt->il_vfrontporch + bt->il_vsync +
1430 bt->il_vbackporch;
1431 std_info->l5 = std_info->vsize/2 -
1432 (bt->vfrontporch - 1);
1433 std_info->l7 = std_info->vsize/2 + 1;
1434 std_info->l9 = std_info->l7 + bt->il_vsync +
1435 bt->il_vbackporch + 1;
1436 std_info->l11 = std_info->vsize -
1437 (bt->il_vfrontporch - 1);
1438 } else {
1439 vpif_dbg(2, debug, "Required timing values for "
1440 "interlaced BT format missing\n");
1441 return -EINVAL;
1442 }
1443 } else {
1444 std_info->vsize = bt->height + bt->vfrontporch +
1445 bt->vsync + bt->vbackporch;
1446 std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
1447 }
1448 strncpy(std_info->name, "Custom timings BT656/1120",
1449 VPIF_MAX_NAME);
1450 std_info->width = bt->width;
1451 std_info->height = bt->height;
1452 std_info->frm_fmt = bt->interlaced ? 0 : 1;
1453 std_info->ycmux_mode = 0;
1454 std_info->capture_format = 0;
1455 std_info->vbi_supported = 0;
1456 std_info->hd_sd = 1;
1457 std_info->stdid = 0;
1458 std_info->dv_preset = V4L2_DV_INVALID;
1459
1460 vid_ch->stdid = 0;
1461 vid_ch->dv_preset = V4L2_DV_INVALID;
1462
1463 return 0;
1464}
1465
1466/**
1467 * vpif_g_dv_timings() - G_DV_TIMINGS handler
1468 * @file: file ptr
1469 * @priv: file handle
1470 * @timings: digital video timings
1471 */
1472static int vpif_g_dv_timings(struct file *file, void *priv,
1473 struct v4l2_dv_timings *timings)
1474{
1475 struct vpif_fh *fh = priv;
1476 struct channel_obj *ch = fh->channel;
1477 struct video_obj *vid_ch = &ch->video;
1478 struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
1479
1480 timings->bt = *bt;
1481
1482 return 0;
1483}
1484
1485/*
1486 * vpif_g_chip_ident() - Identify the chip
1487 * @file: file ptr
1488 * @priv: file handle
1489 * @chip: chip identity
1490 *
1491 * Returns zero or -EINVAL if read operations fails.
1492 */
1493static int vpif_g_chip_ident(struct file *file, void *priv,
1494 struct v4l2_dbg_chip_ident *chip)
1495{
1496 chip->ident = V4L2_IDENT_NONE;
1497 chip->revision = 0;
1498 if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
1499 chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) {
1500 vpif_dbg(2, debug, "match_type is invalid.\n");
1501 return -EINVAL;
1502 }
1503
1504 return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core,
1505 g_chip_ident, chip);
1506}
1507
1508#ifdef CONFIG_VIDEO_ADV_DEBUG
1509/*
1510 * vpif_dbg_g_register() - Read register
1511 * @file: file ptr
1512 * @priv: file handle
1513 * @reg: register to be read
1514 *
1515 * Debugging only
1516 * Returns zero or -EINVAL if read operations fails.
1517 */
1518static int vpif_dbg_g_register(struct file *file, void *priv,
1519 struct v4l2_dbg_register *reg){
1520 struct vpif_fh *fh = priv;
1521 struct channel_obj *ch = fh->channel;
1522 struct video_obj *vid_ch = &ch->video;
1523
1524 return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
1525 g_register, reg);
1526}
1527
1528/*
1529 * vpif_dbg_s_register() - Write to register
1530 * @file: file ptr
1531 * @priv: file handle
1532 * @reg: register to be modified
1533 *
1534 * Debugging only
1535 * Returns zero or -EINVAL if write operations fails.
1536 */
1537static int vpif_dbg_s_register(struct file *file, void *priv,
1538 struct v4l2_dbg_register *reg){
1539 struct vpif_fh *fh = priv;
1540 struct channel_obj *ch = fh->channel;
1541 struct video_obj *vid_ch = &ch->video;
1542
1543 return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
1544 s_register, reg);
1545}
1546#endif
1547
1548/*
1549 * vpif_log_status() - Status information
1550 * @file: file ptr
1551 * @priv: file handle
1552 *
1553 * Returns zero.
1554 */
1555static int vpif_log_status(struct file *filep, void *priv)
1556{
1557 /* status for sub devices */
1558 v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
1559
1560 return 0;
1561}
1562
1563/* vpif display ioctl operations */
1564static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
1565 .vidioc_querycap = vpif_querycap,
1566 .vidioc_g_priority = vpif_g_priority,
1567 .vidioc_s_priority = vpif_s_priority,
1568 .vidioc_enum_fmt_vid_out = vpif_enum_fmt_vid_out,
1569 .vidioc_g_fmt_vid_out = vpif_g_fmt_vid_out,
1570 .vidioc_s_fmt_vid_out = vpif_s_fmt_vid_out,
1571 .vidioc_try_fmt_vid_out = vpif_try_fmt_vid_out,
1572 .vidioc_reqbufs = vpif_reqbufs,
1573 .vidioc_querybuf = vpif_querybuf,
1574 .vidioc_qbuf = vpif_qbuf,
1575 .vidioc_dqbuf = vpif_dqbuf,
1576 .vidioc_streamon = vpif_streamon,
1577 .vidioc_streamoff = vpif_streamoff,
1578 .vidioc_s_std = vpif_s_std,
1579 .vidioc_g_std = vpif_g_std,
1580 .vidioc_enum_output = vpif_enum_output,
1581 .vidioc_s_output = vpif_s_output,
1582 .vidioc_g_output = vpif_g_output,
1583 .vidioc_cropcap = vpif_cropcap,
1584 .vidioc_enum_dv_presets = vpif_enum_dv_presets,
1585 .vidioc_s_dv_preset = vpif_s_dv_preset,
1586 .vidioc_g_dv_preset = vpif_g_dv_preset,
1587 .vidioc_s_dv_timings = vpif_s_dv_timings,
1588 .vidioc_g_dv_timings = vpif_g_dv_timings,
1589 .vidioc_g_chip_ident = vpif_g_chip_ident,
1590#ifdef CONFIG_VIDEO_ADV_DEBUG
1591 .vidioc_g_register = vpif_dbg_g_register,
1592 .vidioc_s_register = vpif_dbg_s_register,
1593#endif
1594 .vidioc_log_status = vpif_log_status,
1595};
1596
1597static const struct v4l2_file_operations vpif_fops = {
1598 .owner = THIS_MODULE,
1599 .open = vpif_open,
1600 .release = vpif_release,
1601 .unlocked_ioctl = video_ioctl2,
1602 .mmap = vpif_mmap,
1603 .poll = vpif_poll
1604};
1605
1606static struct video_device vpif_video_template = {
1607 .name = "vpif",
1608 .fops = &vpif_fops,
1609 .ioctl_ops = &vpif_ioctl_ops,
1610 .tvnorms = DM646X_V4L2_STD,
1611 .current_norm = V4L2_STD_625_50,
1612
1613};
1614
1615/*Configure the channels, buffer sizei, request irq */
1616static int initialize_vpif(void)
1617{
1618 int free_channel_objects_index;
1619 int free_buffer_channel_index;
1620 int free_buffer_index;
1621 int err = 0, i, j;
1622
1623 /* Default number of buffers should be 3 */
1624 if ((ch2_numbuffers > 0) &&
1625 (ch2_numbuffers < config_params.min_numbuffers))
1626 ch2_numbuffers = config_params.min_numbuffers;
1627 if ((ch3_numbuffers > 0) &&
1628 (ch3_numbuffers < config_params.min_numbuffers))
1629 ch3_numbuffers = config_params.min_numbuffers;
1630
1631 /* Set buffer size to min buffers size if invalid buffer size is
1632 * given */
1633 if (ch2_bufsize < config_params.min_bufsize[VPIF_CHANNEL2_VIDEO])
1634 ch2_bufsize =
1635 config_params.min_bufsize[VPIF_CHANNEL2_VIDEO];
1636 if (ch3_bufsize < config_params.min_bufsize[VPIF_CHANNEL3_VIDEO])
1637 ch3_bufsize =
1638 config_params.min_bufsize[VPIF_CHANNEL3_VIDEO];
1639
1640 config_params.numbuffers[VPIF_CHANNEL2_VIDEO] = ch2_numbuffers;
1641
1642 if (ch2_numbuffers) {
1643 config_params.channel_bufsize[VPIF_CHANNEL2_VIDEO] =
1644 ch2_bufsize;
1645 }
1646 config_params.numbuffers[VPIF_CHANNEL3_VIDEO] = ch3_numbuffers;
1647
1648 if (ch3_numbuffers) {
1649 config_params.channel_bufsize[VPIF_CHANNEL3_VIDEO] =
1650 ch3_bufsize;
1651 }
1652
1653 /* Allocate memory for six channel objects */
1654 for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
1655 vpif_obj.dev[i] =
1656 kzalloc(sizeof(struct channel_obj), GFP_KERNEL);
1657 /* If memory allocation fails, return error */
1658 if (!vpif_obj.dev[i]) {
1659 free_channel_objects_index = i;
1660 err = -ENOMEM;
1661 goto vpif_init_free_channel_objects;
1662 }
1663 }
1664
1665 free_channel_objects_index = VPIF_DISPLAY_MAX_DEVICES;
1666 free_buffer_channel_index = VPIF_DISPLAY_NUM_CHANNELS;
1667 free_buffer_index = config_params.numbuffers[i - 1];
1668
1669 return 0;
1670
1671vpif_init_free_channel_objects:
1672 for (j = 0; j < free_channel_objects_index; j++)
1673 kfree(vpif_obj.dev[j]);
1674 return err;
1675}
1676
1677/*
1678 * vpif_probe: This function creates device entries by register itself to the
1679 * V4L2 driver and initializes fields of each channel objects
1680 */
1681static __init int vpif_probe(struct platform_device *pdev)
1682{
1683 struct vpif_subdev_info *subdevdata;
1684 struct vpif_display_config *config;
1685 int i, j = 0, k, q, m, err = 0;
1686 struct i2c_adapter *i2c_adap;
1687 struct common_obj *common;
1688 struct channel_obj *ch;
1689 struct video_device *vfd;
1690 struct resource *res;
1691 int subdev_count;
1692
1693 vpif_dev = &pdev->dev;
1694
1695 err = initialize_vpif();
1696
1697 if (err) {
1698 v4l2_err(vpif_dev->driver, "Error initializing vpif\n");
1699 return err;
1700 }
1701
1702 err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev);
1703 if (err) {
1704 v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n");
1705 return err;
1706 }
1707
1708 k = 0;
1709 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
1710 for (i = res->start; i <= res->end; i++) {
1711 if (request_irq(i, vpif_channel_isr, IRQF_DISABLED,
1712 "DM646x_Display",
1713 (void *)(&vpif_obj.dev[k]->channel_id))) {
1714 err = -EBUSY;
1715 goto vpif_int_err;
1716 }
1717 }
1718 k++;
1719 }
1720
1721 for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
1722
1723 /* Get the pointer to the channel object */
1724 ch = vpif_obj.dev[i];
1725
1726 /* Allocate memory for video device */
1727 vfd = video_device_alloc();
1728 if (vfd == NULL) {
1729 for (j = 0; j < i; j++) {
1730 ch = vpif_obj.dev[j];
1731 video_device_release(ch->video_dev);
1732 }
1733 err = -ENOMEM;
1734 goto vpif_int_err;
1735 }
1736
1737 /* Initialize field of video device */
1738 *vfd = vpif_video_template;
1739 vfd->v4l2_dev = &vpif_obj.v4l2_dev;
1740 vfd->release = video_device_release;
1741 snprintf(vfd->name, sizeof(vfd->name),
1742 "DM646x_VPIFDisplay_DRIVER_V%s",
1743 VPIF_DISPLAY_VERSION);
1744
1745 /* Set video_dev to the video device */
1746 ch->video_dev = vfd;
1747 }
1748
1749 for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
1750 ch = vpif_obj.dev[j];
1751 /* Initialize field of the channel objects */
1752 atomic_set(&ch->usrs, 0);
1753 for (k = 0; k < VPIF_NUMOBJECTS; k++) {
1754 ch->common[k].numbuffers = 0;
1755 common = &ch->common[k];
1756 common->io_usrs = 0;
1757 common->started = 0;
1758 spin_lock_init(&common->irqlock);
1759 mutex_init(&common->lock);
1760 common->numbuffers = 0;
1761 common->set_addr = NULL;
1762 common->ytop_off = common->ybtm_off = 0;
1763 common->ctop_off = common->cbtm_off = 0;
1764 common->cur_frm = common->next_frm = NULL;
1765 memset(&common->fmt, 0, sizeof(common->fmt));
1766 common->numbuffers = config_params.numbuffers[k];
1767
1768 }
1769 ch->initialized = 0;
1770 ch->channel_id = j;
1771 if (j < 2)
1772 ch->common[VPIF_VIDEO_INDEX].numbuffers =
1773 config_params.numbuffers[ch->channel_id];
1774 else
1775 ch->common[VPIF_VIDEO_INDEX].numbuffers = 0;
1776
1777 memset(&ch->vpifparams, 0, sizeof(ch->vpifparams));
1778
1779 /* Initialize prio member of channel object */
1780 v4l2_prio_init(&ch->prio);
1781 ch->common[VPIF_VIDEO_INDEX].fmt.type =
1782 V4L2_BUF_TYPE_VIDEO_OUTPUT;
1783 ch->video_dev->lock = &common->lock;
1784
1785 /* register video device */
1786 vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
1787 (int)ch, (int)&ch->video_dev);
1788
1789 err = video_register_device(ch->video_dev,
1790 VFL_TYPE_GRABBER, (j ? 3 : 2));
1791 if (err < 0)
1792 goto probe_out;
1793
1794 video_set_drvdata(ch->video_dev, ch);
1795 }
1796
1797 i2c_adap = i2c_get_adapter(1);
1798 config = pdev->dev.platform_data;
1799 subdev_count = config->subdev_count;
1800 subdevdata = config->subdevinfo;
1801 vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
1802 GFP_KERNEL);
1803 if (vpif_obj.sd == NULL) {
1804 vpif_err("unable to allocate memory for subdevice pointers\n");
1805 err = -ENOMEM;
1806 goto probe_out;
1807 }
1808
1809 for (i = 0; i < subdev_count; i++) {
1810 vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
1811 i2c_adap,
1812 &subdevdata[i].board_info,
1813 NULL);
1814 if (!vpif_obj.sd[i]) {
1815 vpif_err("Error registering v4l2 subdevice\n");
1816 goto probe_subdev_out;
1817 }
1818
1819 if (vpif_obj.sd[i])
1820 vpif_obj.sd[i]->grp_id = 1 << i;
1821 }
1822
1823 v4l2_info(&vpif_obj.v4l2_dev,
1824 "DM646x VPIF display driver initialized\n");
1825 return 0;
1826
1827probe_subdev_out:
1828 kfree(vpif_obj.sd);
1829probe_out:
1830 for (k = 0; k < j; k++) {
1831 ch = vpif_obj.dev[k];
1832 video_unregister_device(ch->video_dev);
1833 video_device_release(ch->video_dev);
1834 ch->video_dev = NULL;
1835 }
1836vpif_int_err:
1837 v4l2_device_unregister(&vpif_obj.v4l2_dev);
1838 vpif_err("VPIF IRQ request failed\n");
1839 for (q = k; k >= 0; k--) {
1840 for (m = i; m >= res->start; m--)
1841 free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
1842 res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
1843 m = res->end;
1844 }
1845
1846 return err;
1847}
1848
1849/*
1850 * vpif_remove: It un-register channels from V4L2 driver
1851 */
1852static int vpif_remove(struct platform_device *device)
1853{
1854 struct channel_obj *ch;
1855 int i;
1856
1857 v4l2_device_unregister(&vpif_obj.v4l2_dev);
1858
1859 /* un-register device */
1860 for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
1861 /* Get the pointer to the channel object */
1862 ch = vpif_obj.dev[i];
1863 /* Unregister video device */
1864 video_unregister_device(ch->video_dev);
1865
1866 ch->video_dev = NULL;
1867 }
1868
1869 return 0;
1870}
1871
1872static __refdata struct platform_driver vpif_driver = {
1873 .driver = {
1874 .name = "vpif_display",
1875 .owner = THIS_MODULE,
1876 },
1877 .probe = vpif_probe,
1878 .remove = vpif_remove,
1879};
1880
1881static __init int vpif_init(void)
1882{
1883 return platform_driver_register(&vpif_driver);
1884}
1885
1886/*
1887 * vpif_cleanup: This function un-registers device and driver to the kernel,
1888 * frees requested irq handler and de-allocates memory allocated for channel
1889 * objects.
1890 */
1891static void vpif_cleanup(void)
1892{
1893 struct platform_device *pdev;
1894 struct resource *res;
1895 int irq_num;
1896 int i = 0;
1897
1898 pdev = container_of(vpif_dev, struct platform_device, dev);
1899
1900 while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, i))) {
1901 for (irq_num = res->start; irq_num <= res->end; irq_num++)
1902 free_irq(irq_num,
1903 (void *)(&vpif_obj.dev[i]->channel_id));
1904 i++;
1905 }
1906
1907 platform_driver_unregister(&vpif_driver);
1908 kfree(vpif_obj.sd);
1909 for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++)
1910 kfree(vpif_obj.dev[i]);
1911}
1912
1913module_init(vpif_init);
1914module_exit(vpif_cleanup);
diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h
new file mode 100644
index 00000000000..5d1936dafed
--- /dev/null
+++ b/drivers/media/video/davinci/vpif_display.h
@@ -0,0 +1,171 @@
1/*
2 * DM646x display header file
3 *
4 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef DAVINCIHD_DISPLAY_H
17#define DAVINCIHD_DISPLAY_H
18
19/* Header files */
20#include <linux/videodev2.h>
21#include <media/v4l2-common.h>
22#include <media/v4l2-device.h>
23#include <media/videobuf-core.h>
24#include <media/videobuf-dma-contig.h>
25
26#include "vpif.h"
27
28/* Macros */
29#define VPIF_DISPLAY_VERSION "0.0.2"
30
31#define VPIF_VALID_FIELD(field) \
32 (((V4L2_FIELD_ANY == field) || (V4L2_FIELD_NONE == field)) || \
33 (((V4L2_FIELD_INTERLACED == field) || (V4L2_FIELD_SEQ_TB == field)) || \
34 (V4L2_FIELD_SEQ_BT == field)))
35
36#define VPIF_DISPLAY_MAX_DEVICES (2)
37#define VPIF_SLICED_BUF_SIZE (256)
38#define VPIF_SLICED_MAX_SERVICES (3)
39#define VPIF_VIDEO_INDEX (0)
40#define VPIF_VBI_INDEX (1)
41#define VPIF_HBI_INDEX (2)
42
43/* Setting it to 1 as HBI/VBI support yet to be added , else 3*/
44#define VPIF_NUMOBJECTS (1)
45
46/* Macros */
47#define ISALIGNED(a) (0 == ((a) & 7))
48
49/* enumerated data types */
50/* Enumerated data type to give id to each device per channel */
51enum vpif_channel_id {
52 VPIF_CHANNEL2_VIDEO = 0, /* Channel2 Video */
53 VPIF_CHANNEL3_VIDEO, /* Channel3 Video */
54};
55
56/* structures */
57
58struct video_obj {
59 enum v4l2_field buf_field;
60 u32 latest_only; /* indicate whether to return
61 * most recent displayed frame only */
62 v4l2_std_id stdid; /* Currently selected or default
63 * standard */
64 u32 dv_preset;
65 struct v4l2_bt_timings bt_timings;
66 u32 output_id; /* Current output id */
67};
68
69struct vbi_obj {
70 int num_services;
71 struct vpif_vbi_params vbiparams; /* vpif parameters for the raw
72 * vbi data */
73};
74
75struct common_obj {
76 /* Buffer specific parameters */
77 u8 *fbuffers[VIDEO_MAX_FRAME]; /* List of buffer pointers for
78 * storing frames */
79 u32 numbuffers; /* number of buffers */
80 struct videobuf_buffer *cur_frm; /* Pointer pointing to current
81 * videobuf_buffer */
82 struct videobuf_buffer *next_frm; /* Pointer pointing to next
83 * videobuf_buffer */
84 enum v4l2_memory memory; /* This field keeps track of
85 * type of buffer exchange
86 * method user has selected */
87 struct v4l2_format fmt; /* Used to store the format */
88 struct videobuf_queue buffer_queue; /* Buffer queue used in
89 * video-buf */
90 struct list_head dma_queue; /* Queue of filled frames */
91 spinlock_t irqlock; /* Used in video-buf */
92
93 /* channel specific parameters */
94 struct mutex lock; /* lock used to access this
95 * structure */
96 u32 io_usrs; /* number of users performing
97 * IO */
98 u8 started; /* Indicates whether streaming
99 * started */
100 u32 ytop_off; /* offset of Y top from the
101 * starting of the buffer */
102 u32 ybtm_off; /* offset of Y bottom from the
103 * starting of the buffer */
104 u32 ctop_off; /* offset of C top from the
105 * starting of the buffer */
106 u32 cbtm_off; /* offset of C bottom from the
107 * starting of the buffer */
108 /* Function pointer to set the addresses */
109 void (*set_addr) (unsigned long, unsigned long,
110 unsigned long, unsigned long);
111 u32 height;
112 u32 width;
113};
114
115struct channel_obj {
116 /* V4l2 specific parameters */
117 struct video_device *video_dev; /* Identifies video device for
118 * this channel */
119 struct v4l2_prio_state prio; /* Used to keep track of state of
120 * the priority */
121 atomic_t usrs; /* number of open instances of
122 * the channel */
123 u32 field_id; /* Indicates id of the field
124 * which is being displayed */
125 u8 initialized; /* flag to indicate whether
126 * encoder is initialized */
127
128 enum vpif_channel_id channel_id;/* Identifies channel */
129 struct vpif_params vpifparams;
130 struct common_obj common[VPIF_NUMOBJECTS];
131 struct video_obj video;
132 struct vbi_obj vbi;
133};
134
135/* File handle structure */
136struct vpif_fh {
137 struct channel_obj *channel; /* pointer to channel object for
138 * opened device */
139 u8 io_allowed[VPIF_NUMOBJECTS]; /* Indicates whether this file handle
140 * is doing IO */
141 enum v4l2_priority prio; /* Used to keep track priority of
142 * this instance */
143 u8 initialized; /* Used to keep track of whether this
144 * file handle has initialized
145 * channel or not */
146};
147
148/* vpif device structure */
149struct vpif_device {
150 struct v4l2_device v4l2_dev;
151 struct channel_obj *dev[VPIF_DISPLAY_NUM_CHANNELS];
152 struct v4l2_subdev **sd;
153
154};
155
156struct vpif_config_params {
157 u32 min_bufsize[VPIF_DISPLAY_NUM_CHANNELS];
158 u32 channel_bufsize[VPIF_DISPLAY_NUM_CHANNELS];
159 u8 numbuffers[VPIF_DISPLAY_NUM_CHANNELS];
160 u8 min_numbuffers;
161};
162
163/* Struct which keeps track of the line numbers for the sliced vbi service */
164struct vpif_service_line {
165 u16 service_id;
166 u16 service_line[2];
167 u16 enc_service_id;
168 u8 bytestowrite;
169};
170
171#endif /* DAVINCIHD_DISPLAY_H */
diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c
new file mode 100644
index 00000000000..3e5cf27ec2b
--- /dev/null
+++ b/drivers/media/video/davinci/vpss.c
@@ -0,0 +1,482 @@
1/*
2 * Copyright (C) 2009 Texas Instruments.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 * common vpss system module platform driver for all video drivers.
19 */
20#include <linux/kernel.h>
21#include <linux/sched.h>
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/spinlock.h>
26#include <linux/compiler.h>
27#include <linux/io.h>
28#include <mach/hardware.h>
29#include <media/davinci/vpss.h>
30
31MODULE_LICENSE("GPL");
32MODULE_DESCRIPTION("VPSS Driver");
33MODULE_AUTHOR("Texas Instruments");
34
35/* DM644x defines */
36#define DM644X_SBL_PCR_VPSS (4)
37
38#define DM355_VPSSBL_INTSEL 0x10
39#define DM355_VPSSBL_EVTSEL 0x14
40/* vpss BL register offsets */
41#define DM355_VPSSBL_CCDCMUX 0x1c
42/* vpss CLK register offsets */
43#define DM355_VPSSCLK_CLKCTRL 0x04
44/* masks and shifts */
45#define VPSS_HSSISEL_SHIFT 4
46/*
47 * VDINT0 - vpss_int0, VDINT1 - vpss_int1, H3A - vpss_int4,
48 * IPIPE_INT1_SDR - vpss_int5
49 */
50#define DM355_VPSSBL_INTSEL_DEFAULT 0xff83ff10
51/* VENCINT - vpss_int8 */
52#define DM355_VPSSBL_EVTSEL_DEFAULT 0x4
53
54#define DM365_ISP5_PCCR 0x04
55#define DM365_ISP5_INTSEL1 0x10
56#define DM365_ISP5_INTSEL2 0x14
57#define DM365_ISP5_INTSEL3 0x18
58#define DM365_ISP5_CCDCMUX 0x20
59#define DM365_ISP5_PG_FRAME_SIZE 0x28
60#define DM365_VPBE_CLK_CTRL 0x00
61/*
62 * vpss interrupts. VDINT0 - vpss_int0, VDINT1 - vpss_int1,
63 * AF - vpss_int3
64 */
65#define DM365_ISP5_INTSEL1_DEFAULT 0x0b1f0100
66/* AEW - vpss_int6, RSZ_INT_DMA - vpss_int5 */
67#define DM365_ISP5_INTSEL2_DEFAULT 0x1f0a0f1f
68/* VENC - vpss_int8 */
69#define DM365_ISP5_INTSEL3_DEFAULT 0x00000015
70
71/* masks and shifts for DM365*/
72#define DM365_CCDC_PG_VD_POL_SHIFT 0
73#define DM365_CCDC_PG_HD_POL_SHIFT 1
74
75#define CCD_SRC_SEL_MASK (BIT_MASK(5) | BIT_MASK(4))
76#define CCD_SRC_SEL_SHIFT 4
77
78/* Different SoC platforms supported by this driver */
79enum vpss_platform_type {
80 DM644X,
81 DM355,
82 DM365,
83};
84
85/*
86 * vpss operations. Depends on platform. Not all functions are available
87 * on all platforms. The api, first check if a functio is available before
88 * invoking it. In the probe, the function ptrs are initialized based on
89 * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc.
90 */
91struct vpss_hw_ops {
92 /* enable clock */
93 int (*enable_clock)(enum vpss_clock_sel clock_sel, int en);
94 /* select input to ccdc */
95 void (*select_ccdc_source)(enum vpss_ccdc_source_sel src_sel);
96 /* clear wbl overflow bit */
97 int (*clear_wbl_overflow)(enum vpss_wbl_sel wbl_sel);
98};
99
100/* vpss configuration */
101struct vpss_oper_config {
102 __iomem void *vpss_regs_base0;
103 __iomem void *vpss_regs_base1;
104 enum vpss_platform_type platform;
105 spinlock_t vpss_lock;
106 struct vpss_hw_ops hw_ops;
107};
108
109static struct vpss_oper_config oper_cfg;
110
111/* register access routines */
112static inline u32 bl_regr(u32 offset)
113{
114 return __raw_readl(oper_cfg.vpss_regs_base0 + offset);
115}
116
117static inline void bl_regw(u32 val, u32 offset)
118{
119 __raw_writel(val, oper_cfg.vpss_regs_base0 + offset);
120}
121
122static inline u32 vpss_regr(u32 offset)
123{
124 return __raw_readl(oper_cfg.vpss_regs_base1 + offset);
125}
126
127static inline void vpss_regw(u32 val, u32 offset)
128{
129 __raw_writel(val, oper_cfg.vpss_regs_base1 + offset);
130}
131
132/* For DM365 only */
133static inline u32 isp5_read(u32 offset)
134{
135 return __raw_readl(oper_cfg.vpss_regs_base0 + offset);
136}
137
138/* For DM365 only */
139static inline void isp5_write(u32 val, u32 offset)
140{
141 __raw_writel(val, oper_cfg.vpss_regs_base0 + offset);
142}
143
144static void dm365_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
145{
146 u32 temp = isp5_read(DM365_ISP5_CCDCMUX) & ~CCD_SRC_SEL_MASK;
147
148 /* if we are using pattern generator, enable it */
149 if (src_sel == VPSS_PGLPBK || src_sel == VPSS_CCDCPG)
150 temp |= 0x08;
151
152 temp |= (src_sel << CCD_SRC_SEL_SHIFT);
153 isp5_write(temp, DM365_ISP5_CCDCMUX);
154}
155
156static void dm355_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
157{
158 bl_regw(src_sel << VPSS_HSSISEL_SHIFT, DM355_VPSSBL_CCDCMUX);
159}
160
161int vpss_select_ccdc_source(enum vpss_ccdc_source_sel src_sel)
162{
163 if (!oper_cfg.hw_ops.select_ccdc_source)
164 return -EINVAL;
165
166 oper_cfg.hw_ops.select_ccdc_source(src_sel);
167 return 0;
168}
169EXPORT_SYMBOL(vpss_select_ccdc_source);
170
171static int dm644x_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
172{
173 u32 mask = 1, val;
174
175 if (wbl_sel < VPSS_PCR_AEW_WBL_0 ||
176 wbl_sel > VPSS_PCR_CCDC_WBL_O)
177 return -EINVAL;
178
179 /* writing a 0 clear the overflow */
180 mask = ~(mask << wbl_sel);
181 val = bl_regr(DM644X_SBL_PCR_VPSS) & mask;
182 bl_regw(val, DM644X_SBL_PCR_VPSS);
183 return 0;
184}
185
186int vpss_clear_wbl_overflow(enum vpss_wbl_sel wbl_sel)
187{
188 if (!oper_cfg.hw_ops.clear_wbl_overflow)
189 return -EINVAL;
190
191 return oper_cfg.hw_ops.clear_wbl_overflow(wbl_sel);
192}
193EXPORT_SYMBOL(vpss_clear_wbl_overflow);
194
195/*
196 * dm355_enable_clock - Enable VPSS Clock
197 * @clock_sel: CLock to be enabled/disabled
198 * @en: enable/disable flag
199 *
200 * This is called to enable or disable a vpss clock
201 */
202static int dm355_enable_clock(enum vpss_clock_sel clock_sel, int en)
203{
204 unsigned long flags;
205 u32 utemp, mask = 0x1, shift = 0;
206
207 switch (clock_sel) {
208 case VPSS_VPBE_CLOCK:
209 /* nothing since lsb */
210 break;
211 case VPSS_VENC_CLOCK_SEL:
212 shift = 2;
213 break;
214 case VPSS_CFALD_CLOCK:
215 shift = 3;
216 break;
217 case VPSS_H3A_CLOCK:
218 shift = 4;
219 break;
220 case VPSS_IPIPE_CLOCK:
221 shift = 5;
222 break;
223 case VPSS_CCDC_CLOCK:
224 shift = 6;
225 break;
226 default:
227 printk(KERN_ERR "dm355_enable_clock:"
228 " Invalid selector: %d\n", clock_sel);
229 return -EINVAL;
230 }
231
232 spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
233 utemp = vpss_regr(DM355_VPSSCLK_CLKCTRL);
234 if (!en)
235 utemp &= ~(mask << shift);
236 else
237 utemp |= (mask << shift);
238
239 vpss_regw(utemp, DM355_VPSSCLK_CLKCTRL);
240 spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
241 return 0;
242}
243
244static int dm365_enable_clock(enum vpss_clock_sel clock_sel, int en)
245{
246 unsigned long flags;
247 u32 utemp, mask = 0x1, shift = 0, offset = DM365_ISP5_PCCR;
248 u32 (*read)(u32 offset) = isp5_read;
249 void(*write)(u32 val, u32 offset) = isp5_write;
250
251 switch (clock_sel) {
252 case VPSS_BL_CLOCK:
253 break;
254 case VPSS_CCDC_CLOCK:
255 shift = 1;
256 break;
257 case VPSS_H3A_CLOCK:
258 shift = 2;
259 break;
260 case VPSS_RSZ_CLOCK:
261 shift = 3;
262 break;
263 case VPSS_IPIPE_CLOCK:
264 shift = 4;
265 break;
266 case VPSS_IPIPEIF_CLOCK:
267 shift = 5;
268 break;
269 case VPSS_PCLK_INTERNAL:
270 shift = 6;
271 break;
272 case VPSS_PSYNC_CLOCK_SEL:
273 shift = 7;
274 break;
275 case VPSS_VPBE_CLOCK:
276 read = vpss_regr;
277 write = vpss_regw;
278 offset = DM365_VPBE_CLK_CTRL;
279 break;
280 case VPSS_VENC_CLOCK_SEL:
281 shift = 2;
282 read = vpss_regr;
283 write = vpss_regw;
284 offset = DM365_VPBE_CLK_CTRL;
285 break;
286 case VPSS_LDC_CLOCK:
287 shift = 3;
288 read = vpss_regr;
289 write = vpss_regw;
290 offset = DM365_VPBE_CLK_CTRL;
291 break;
292 case VPSS_FDIF_CLOCK:
293 shift = 4;
294 read = vpss_regr;
295 write = vpss_regw;
296 offset = DM365_VPBE_CLK_CTRL;
297 break;
298 case VPSS_OSD_CLOCK_SEL:
299 shift = 6;
300 read = vpss_regr;
301 write = vpss_regw;
302 offset = DM365_VPBE_CLK_CTRL;
303 break;
304 case VPSS_LDC_CLOCK_SEL:
305 shift = 7;
306 read = vpss_regr;
307 write = vpss_regw;
308 offset = DM365_VPBE_CLK_CTRL;
309 break;
310 default:
311 printk(KERN_ERR "dm365_enable_clock: Invalid selector: %d\n",
312 clock_sel);
313 return -1;
314 }
315
316 spin_lock_irqsave(&oper_cfg.vpss_lock, flags);
317 utemp = read(offset);
318 if (!en) {
319 mask = ~mask;
320 utemp &= (mask << shift);
321 } else
322 utemp |= (mask << shift);
323
324 write(utemp, offset);
325 spin_unlock_irqrestore(&oper_cfg.vpss_lock, flags);
326
327 return 0;
328}
329
330int vpss_enable_clock(enum vpss_clock_sel clock_sel, int en)
331{
332 if (!oper_cfg.hw_ops.enable_clock)
333 return -EINVAL;
334
335 return oper_cfg.hw_ops.enable_clock(clock_sel, en);
336}
337EXPORT_SYMBOL(vpss_enable_clock);
338
339void dm365_vpss_set_sync_pol(struct vpss_sync_pol sync)
340{
341 int val = 0;
342 val = isp5_read(DM365_ISP5_CCDCMUX);
343
344 val |= (sync.ccdpg_hdpol << DM365_CCDC_PG_HD_POL_SHIFT);
345 val |= (sync.ccdpg_vdpol << DM365_CCDC_PG_VD_POL_SHIFT);
346
347 isp5_write(val, DM365_ISP5_CCDCMUX);
348}
349EXPORT_SYMBOL(dm365_vpss_set_sync_pol);
350
351void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
352{
353 int current_reg = ((frame_size.hlpfr >> 1) - 1) << 16;
354
355 current_reg |= (frame_size.pplen - 1);
356 isp5_write(current_reg, DM365_ISP5_PG_FRAME_SIZE);
357}
358EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size);
359
360static int __init vpss_probe(struct platform_device *pdev)
361{
362 struct resource *r1, *r2;
363 char *platform_name;
364 int status;
365
366 if (!pdev->dev.platform_data) {
367 dev_err(&pdev->dev, "no platform data\n");
368 return -ENOENT;
369 }
370
371 platform_name = pdev->dev.platform_data;
372 if (!strcmp(platform_name, "dm355_vpss"))
373 oper_cfg.platform = DM355;
374 else if (!strcmp(platform_name, "dm365_vpss"))
375 oper_cfg.platform = DM365;
376 else if (!strcmp(platform_name, "dm644x_vpss"))
377 oper_cfg.platform = DM644X;
378 else {
379 dev_err(&pdev->dev, "vpss driver not supported on"
380 " this platform\n");
381 return -ENODEV;
382 }
383
384 dev_info(&pdev->dev, "%s vpss probed\n", platform_name);
385 r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
386 if (!r1)
387 return -ENOENT;
388
389 r1 = request_mem_region(r1->start, resource_size(r1), r1->name);
390 if (!r1)
391 return -EBUSY;
392
393 oper_cfg.vpss_regs_base0 = ioremap(r1->start, resource_size(r1));
394 if (!oper_cfg.vpss_regs_base0) {
395 status = -EBUSY;
396 goto fail1;
397 }
398
399 if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
400 r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
401 if (!r2) {
402 status = -ENOENT;
403 goto fail2;
404 }
405 r2 = request_mem_region(r2->start, resource_size(r2), r2->name);
406 if (!r2) {
407 status = -EBUSY;
408 goto fail2;
409 }
410
411 oper_cfg.vpss_regs_base1 = ioremap(r2->start,
412 resource_size(r2));
413 if (!oper_cfg.vpss_regs_base1) {
414 status = -EBUSY;
415 goto fail3;
416 }
417 }
418
419 if (oper_cfg.platform == DM355) {
420 oper_cfg.hw_ops.enable_clock = dm355_enable_clock;
421 oper_cfg.hw_ops.select_ccdc_source = dm355_select_ccdc_source;
422 /* Setup vpss interrupts */
423 bl_regw(DM355_VPSSBL_INTSEL_DEFAULT, DM355_VPSSBL_INTSEL);
424 bl_regw(DM355_VPSSBL_EVTSEL_DEFAULT, DM355_VPSSBL_EVTSEL);
425 } else if (oper_cfg.platform == DM365) {
426 oper_cfg.hw_ops.enable_clock = dm365_enable_clock;
427 oper_cfg.hw_ops.select_ccdc_source = dm365_select_ccdc_source;
428 /* Setup vpss interrupts */
429 isp5_write(DM365_ISP5_INTSEL1_DEFAULT, DM365_ISP5_INTSEL1);
430 isp5_write(DM365_ISP5_INTSEL2_DEFAULT, DM365_ISP5_INTSEL2);
431 isp5_write(DM365_ISP5_INTSEL3_DEFAULT, DM365_ISP5_INTSEL3);
432 } else
433 oper_cfg.hw_ops.clear_wbl_overflow = dm644x_clear_wbl_overflow;
434
435 spin_lock_init(&oper_cfg.vpss_lock);
436 dev_info(&pdev->dev, "%s vpss probe success\n", platform_name);
437 return 0;
438
439fail3:
440 release_mem_region(r2->start, resource_size(r2));
441fail2:
442 iounmap(oper_cfg.vpss_regs_base0);
443fail1:
444 release_mem_region(r1->start, resource_size(r1));
445 return status;
446}
447
448static int __devexit vpss_remove(struct platform_device *pdev)
449{
450 struct resource *res;
451
452 iounmap(oper_cfg.vpss_regs_base0);
453 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
454 release_mem_region(res->start, resource_size(res));
455 if (oper_cfg.platform == DM355 || oper_cfg.platform == DM365) {
456 iounmap(oper_cfg.vpss_regs_base1);
457 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
458 release_mem_region(res->start, resource_size(res));
459 }
460 return 0;
461}
462
463static struct platform_driver vpss_driver = {
464 .driver = {
465 .name = "vpss",
466 .owner = THIS_MODULE,
467 },
468 .remove = __devexit_p(vpss_remove),
469 .probe = vpss_probe,
470};
471
472static void vpss_exit(void)
473{
474 platform_driver_unregister(&vpss_driver);
475}
476
477static int __init vpss_init(void)
478{
479 return platform_driver_register(&vpss_driver);
480}
481subsys_initcall(vpss_init);
482module_exit(vpss_exit);