Merge airlied/drm-next into drm-misc-next
[sfrench/cifs-2.6.git] / drivers / media / platform / davinci / dm644x_ccdc.c
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  * CCDC hardware module for DM6446
15  * ------------------------------
16  *
17  * This module is for configuring CCD controller of DM6446 VPFE to capture
18  * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules
19  * such as Defect Pixel Correction, Color Space Conversion etc to
20  * pre-process the Raw Bayer RGB data, before writing it to SDRAM.
21  * This file is named DM644x so that other variants such DM6443
22  * may be supported using the same module.
23  *
24  * TODO: Test Raw bayer parameter settings and bayer capture
25  *       Split module parameter structure to module specific ioctl structs
26  *       investigate if enum used for user space type definition
27  *       to be replaced by #defines or integer
28  */
29 #include <linux/platform_device.h>
30 #include <linux/uaccess.h>
31 #include <linux/videodev2.h>
32 #include <linux/gfp.h>
33 #include <linux/err.h>
34 #include <linux/module.h>
35
36 #include <media/davinci/dm644x_ccdc.h>
37 #include <media/davinci/vpss.h>
38
39 #include "dm644x_ccdc_regs.h"
40 #include "ccdc_hw_device.h"
41
42 MODULE_LICENSE("GPL");
43 MODULE_DESCRIPTION("CCDC Driver for DM6446");
44 MODULE_AUTHOR("Texas Instruments");
45
46 static struct ccdc_oper_config {
47         struct device *dev;
48         /* CCDC interface type */
49         enum vpfe_hw_if_type if_type;
50         /* Raw Bayer configuration */
51         struct ccdc_params_raw bayer;
52         /* YCbCr configuration */
53         struct ccdc_params_ycbcr ycbcr;
54         /* ccdc base address */
55         void __iomem *base_addr;
56 } ccdc_cfg = {
57         /* Raw configurations */
58         .bayer = {
59                 .pix_fmt = CCDC_PIXFMT_RAW,
60                 .frm_fmt = CCDC_FRMFMT_PROGRESSIVE,
61                 .win = CCDC_WIN_VGA,
62                 .fid_pol = VPFE_PINPOL_POSITIVE,
63                 .vd_pol = VPFE_PINPOL_POSITIVE,
64                 .hd_pol = VPFE_PINPOL_POSITIVE,
65                 .config_params = {
66                         .data_sz = CCDC_DATA_10BITS,
67                 },
68         },
69         .ycbcr = {
70                 .pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
71                 .frm_fmt = CCDC_FRMFMT_INTERLACED,
72                 .win = CCDC_WIN_PAL,
73                 .fid_pol = VPFE_PINPOL_POSITIVE,
74                 .vd_pol = VPFE_PINPOL_POSITIVE,
75                 .hd_pol = VPFE_PINPOL_POSITIVE,
76                 .bt656_enable = 1,
77                 .pix_order = CCDC_PIXORDER_CBYCRY,
78                 .buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
79         },
80 };
81
82 #define CCDC_MAX_RAW_YUV_FORMATS        2
83
84 /* Raw Bayer formats */
85 static u32 ccdc_raw_bayer_pix_formats[] =
86         {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
87
88 /* Raw YUV formats */
89 static u32 ccdc_raw_yuv_pix_formats[] =
90         {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
91
92 /* CCDC Save/Restore context */
93 static u32 ccdc_ctx[CCDC_REG_END / sizeof(u32)];
94
95 /* register access routines */
96 static inline u32 regr(u32 offset)
97 {
98         return __raw_readl(ccdc_cfg.base_addr + offset);
99 }
100
101 static inline void regw(u32 val, u32 offset)
102 {
103         __raw_writel(val, ccdc_cfg.base_addr + offset);
104 }
105
106 static void ccdc_enable(int flag)
107 {
108         regw(flag, CCDC_PCR);
109 }
110
111 static void ccdc_enable_vport(int flag)
112 {
113         if (flag)
114                 /* enable video port */
115                 regw(CCDC_ENABLE_VIDEO_PORT, CCDC_FMTCFG);
116         else
117                 regw(CCDC_DISABLE_VIDEO_PORT, CCDC_FMTCFG);
118 }
119
120 /*
121  * ccdc_setwin()
122  * This function will configure the window size
123  * to be capture in CCDC reg
124  */
125 static void ccdc_setwin(struct v4l2_rect *image_win,
126                         enum ccdc_frmfmt frm_fmt,
127                         int ppc)
128 {
129         int horz_start, horz_nr_pixels;
130         int vert_start, vert_nr_lines;
131         int val = 0, mid_img = 0;
132
133         dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin...");
134         /*
135          * ppc - per pixel count. indicates how many pixels per cell
136          * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
137          * raw capture this is 1
138          */
139         horz_start = image_win->left << (ppc - 1);
140         horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
141         regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels,
142              CCDC_HORZ_INFO);
143
144         vert_start = image_win->top;
145
146         if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
147                 vert_nr_lines = (image_win->height >> 1) - 1;
148                 vert_start >>= 1;
149                 /* Since first line doesn't have any data */
150                 vert_start += 1;
151                 /* configure VDINT0 */
152                 val = (vert_start << CCDC_VDINT_VDINT0_SHIFT);
153                 regw(val, CCDC_VDINT);
154
155         } else {
156                 /* Since first line doesn't have any data */
157                 vert_start += 1;
158                 vert_nr_lines = image_win->height - 1;
159                 /*
160                  * configure VDINT0 and VDINT1. VDINT1 will be at half
161                  * of image height
162                  */
163                 mid_img = vert_start + (image_win->height / 2);
164                 val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) |
165                     (mid_img & CCDC_VDINT_VDINT1_MASK);
166                 regw(val, CCDC_VDINT);
167
168         }
169         regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start,
170              CCDC_VERT_START);
171         regw(vert_nr_lines, CCDC_VERT_LINES);
172         dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin...");
173 }
174
175 static void ccdc_readregs(void)
176 {
177         unsigned int val = 0;
178
179         val = regr(CCDC_ALAW);
180         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to ALAW...\n", val);
181         val = regr(CCDC_CLAMP);
182         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to CLAMP...\n", val);
183         val = regr(CCDC_DCSUB);
184         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to DCSUB...\n", val);
185         val = regr(CCDC_BLKCMP);
186         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to BLKCMP...\n", val);
187         val = regr(CCDC_FPC_ADDR);
188         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC_ADDR...\n", val);
189         val = regr(CCDC_FPC);
190         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC...\n", val);
191         val = regr(CCDC_FMTCFG);
192         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMTCFG...\n", val);
193         val = regr(CCDC_COLPTN);
194         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to COLPTN...\n", val);
195         val = regr(CCDC_FMT_HORZ);
196         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_HORZ...\n", val);
197         val = regr(CCDC_FMT_VERT);
198         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_VERT...\n", val);
199         val = regr(CCDC_HSIZE_OFF);
200         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HSIZE_OFF...\n", val);
201         val = regr(CCDC_SDOFST);
202         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SDOFST...\n", val);
203         val = regr(CCDC_VP_OUT);
204         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VP_OUT...\n", val);
205         val = regr(CCDC_SYN_MODE);
206         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SYN_MODE...\n", val);
207         val = regr(CCDC_HORZ_INFO);
208         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HORZ_INFO...\n", val);
209         val = regr(CCDC_VERT_START);
210         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_START...\n", val);
211         val = regr(CCDC_VERT_LINES);
212         dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val);
213 }
214
215 static int ccdc_close(struct device *dev)
216 {
217         return 0;
218 }
219
220 /*
221  * ccdc_restore_defaults()
222  * This function will write defaults to all CCDC registers
223  */
224 static void ccdc_restore_defaults(void)
225 {
226         int i;
227
228         /* disable CCDC */
229         ccdc_enable(0);
230         /* set all registers to default value */
231         for (i = 4; i <= 0x94; i += 4)
232                 regw(0,  i);
233         regw(CCDC_NO_CULLING, CCDC_CULLING);
234         regw(CCDC_GAMMA_BITS_11_2, CCDC_ALAW);
235 }
236
237 static int ccdc_open(struct device *device)
238 {
239         ccdc_restore_defaults();
240         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
241                 ccdc_enable_vport(1);
242         return 0;
243 }
244
245 static void ccdc_sbl_reset(void)
246 {
247         vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O);
248 }
249
250 /*
251  * ccdc_config_ycbcr()
252  * This function will configure CCDC for YCbCr video capture
253  */
254 static void ccdc_config_ycbcr(void)
255 {
256         struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr;
257         u32 syn_mode;
258
259         dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr...");
260         /*
261          * first restore the CCDC registers to default values
262          * This is important since we assume default values to be set in
263          * a lot of registers that we didn't touch
264          */
265         ccdc_restore_defaults();
266
267         /*
268          * configure pixel format, frame format, configure video frame
269          * format, enable output to SDRAM, enable internal timing generator
270          * and 8bit pack mode
271          */
272         syn_mode = (((params->pix_fmt & CCDC_SYN_MODE_INPMOD_MASK) <<
273                     CCDC_SYN_MODE_INPMOD_SHIFT) |
274                     ((params->frm_fmt & CCDC_SYN_FLDMODE_MASK) <<
275                     CCDC_SYN_FLDMODE_SHIFT) | CCDC_VDHDEN_ENABLE |
276                     CCDC_WEN_ENABLE | CCDC_DATA_PACK_ENABLE);
277
278         /* setup BT.656 sync mode */
279         if (params->bt656_enable) {
280                 regw(CCDC_REC656IF_BT656_EN, CCDC_REC656IF);
281
282                 /*
283                  * configure the FID, VD, HD pin polarity,
284                  * fld,hd pol positive, vd negative, 8-bit data
285                  */
286                 syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE;
287                 if (ccdc_cfg.if_type == VPFE_BT656_10BIT)
288                         syn_mode |= CCDC_SYN_MODE_10BITS;
289                 else
290                         syn_mode |= CCDC_SYN_MODE_8BITS;
291         } else {
292                 /* y/c external sync mode */
293                 syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) <<
294                              CCDC_FID_POL_SHIFT) |
295                              ((params->hd_pol & CCDC_HD_POL_MASK) <<
296                              CCDC_HD_POL_SHIFT) |
297                              ((params->vd_pol & CCDC_VD_POL_MASK) <<
298                              CCDC_VD_POL_SHIFT));
299         }
300         regw(syn_mode, CCDC_SYN_MODE);
301
302         /* configure video window */
303         ccdc_setwin(&params->win, params->frm_fmt, 2);
304
305         /*
306          * configure the order of y cb cr in SDRAM, and disable latch
307          * internal register on vsync
308          */
309         if (ccdc_cfg.if_type == VPFE_BT656_10BIT)
310                 regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) |
311                         CCDC_LATCH_ON_VSYNC_DISABLE | CCDC_CCDCFG_BW656_10BIT,
312                         CCDC_CCDCFG);
313         else
314                 regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) |
315                         CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
316
317         /*
318          * configure the horizontal line offset. This should be a
319          * on 32 byte boundary. So clear LSB 5 bits
320          */
321         regw(((params->win.width * 2  + 31) & ~0x1f), CCDC_HSIZE_OFF);
322
323         /* configure the memory line offset */
324         if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
325                 /* two fields are interleaved in memory */
326                 regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST);
327
328         ccdc_sbl_reset();
329         dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n");
330 }
331
332 static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp)
333 {
334         u32 val;
335
336         if (!bclamp->enable) {
337                 /* configure DCSub */
338                 val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK;
339                 regw(val, CCDC_DCSUB);
340                 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to DCSUB...\n", val);
341                 regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP);
342                 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to CLAMP...\n");
343                 return;
344         }
345         /*
346          * Configure gain,  Start pixel, No of line to be avg,
347          * No of pixel/line to be avg, & Enable the Black clamping
348          */
349         val = ((bclamp->sgain & CCDC_BLK_SGAIN_MASK) |
350                ((bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) <<
351                 CCDC_BLK_ST_PXL_SHIFT) |
352                ((bclamp->sample_ln & CCDC_BLK_SAMPLE_LINE_MASK) <<
353                 CCDC_BLK_SAMPLE_LINE_SHIFT) |
354                ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) <<
355                 CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE);
356         regw(val, CCDC_CLAMP);
357         dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to CLAMP...\n", val);
358         /* If Black clamping is enable then make dcsub 0 */
359         regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB);
360         dev_dbg(ccdc_cfg.dev, "\nWriting 0x00000000 to DCSUB...\n");
361 }
362
363 static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp)
364 {
365         u32 val;
366
367         val = ((bcomp->b & CCDC_BLK_COMP_MASK) |
368               ((bcomp->gb & CCDC_BLK_COMP_MASK) <<
369                CCDC_BLK_COMP_GB_COMP_SHIFT) |
370               ((bcomp->gr & CCDC_BLK_COMP_MASK) <<
371                CCDC_BLK_COMP_GR_COMP_SHIFT) |
372               ((bcomp->r & CCDC_BLK_COMP_MASK) <<
373                CCDC_BLK_COMP_R_COMP_SHIFT));
374         regw(val, CCDC_BLKCMP);
375 }
376
377 /*
378  * ccdc_config_raw()
379  * This function will configure CCDC for Raw capture mode
380  */
381 static void ccdc_config_raw(void)
382 {
383         struct ccdc_params_raw *params = &ccdc_cfg.bayer;
384         struct ccdc_config_params_raw *config_params =
385                                 &ccdc_cfg.bayer.config_params;
386         unsigned int syn_mode = 0;
387         unsigned int val;
388
389         dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw...");
390
391         /*      Reset CCDC */
392         ccdc_restore_defaults();
393
394         /* Disable latching function registers on VSYNC  */
395         regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
396
397         /*
398          * Configure the vertical sync polarity(SYN_MODE.VDPOL),
399          * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity
400          * (SYN_MODE.FLDPOL), frame format(progressive or interlace),
401          * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output
402          * SDRAM, enable internal timing generator
403          */
404         syn_mode =
405                 (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
406                 ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
407                 ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
408                 ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
409                 ((config_params->data_sz & CCDC_DATA_SZ_MASK) <<
410                 CCDC_DATA_SZ_SHIFT) |
411                 ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT) |
412                 CCDC_WEN_ENABLE | CCDC_VDHDEN_ENABLE);
413
414         /* Enable and configure aLaw register if needed */
415         if (config_params->alaw.enable) {
416                 val = ((config_params->alaw.gamma_wd &
417                       CCDC_ALAW_GAMMA_WD_MASK) | CCDC_ALAW_ENABLE);
418                 regw(val, CCDC_ALAW);
419                 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val);
420         }
421
422         /* Configure video window */
423         ccdc_setwin(&params->win, params->frm_fmt, CCDC_PPC_RAW);
424
425         /* Configure Black Clamp */
426         ccdc_config_black_clamp(&config_params->blk_clamp);
427
428         /* Configure Black level compensation */
429         ccdc_config_black_compense(&config_params->blk_comp);
430
431         /* If data size is 8 bit then pack the data */
432         if ((config_params->data_sz == CCDC_DATA_8BITS) ||
433              config_params->alaw.enable)
434                 syn_mode |= CCDC_DATA_PACK_ENABLE;
435
436         /* disable video port */
437         val = CCDC_DISABLE_VIDEO_PORT;
438
439         if (config_params->data_sz == CCDC_DATA_8BITS)
440                 val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
441                     << CCDC_FMTCFG_VPIN_SHIFT;
442         else
443                 val |= (config_params->data_sz & CCDC_FMTCFG_VPIN_MASK)
444                     << CCDC_FMTCFG_VPIN_SHIFT;
445         /* Write value in FMTCFG */
446         regw(val, CCDC_FMTCFG);
447
448         dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMTCFG...\n", val);
449         /* Configure the color pattern according to mt9t001 sensor */
450         regw(CCDC_COLPTN_VAL, CCDC_COLPTN);
451
452         dev_dbg(ccdc_cfg.dev, "\nWriting 0xBB11BB11 to COLPTN...\n");
453         /*
454          * Configure Data formatter(Video port) pixel selection
455          * (FMT_HORZ, FMT_VERT)
456          */
457         val = ((params->win.left & CCDC_FMT_HORZ_FMTSPH_MASK) <<
458               CCDC_FMT_HORZ_FMTSPH_SHIFT) |
459               (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK);
460         regw(val, CCDC_FMT_HORZ);
461
462         dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_HORZ...\n", val);
463         val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK)
464             << CCDC_FMT_VERT_FMTSLV_SHIFT;
465         if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
466                 val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK;
467         else
468                 val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK;
469
470         dev_dbg(ccdc_cfg.dev, "\nparams->win.height  0x%x ...\n",
471                params->win.height);
472         regw(val, CCDC_FMT_VERT);
473
474         dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_VERT...\n", val);
475
476         dev_dbg(ccdc_cfg.dev, "\nbelow regw(val, FMT_VERT)...");
477
478         /*
479          * Configure Horizontal offset register. If pack 8 is enabled then
480          * 1 pixel will take 1 byte
481          */
482         if ((config_params->data_sz == CCDC_DATA_8BITS) ||
483             config_params->alaw.enable)
484                 regw((params->win.width + CCDC_32BYTE_ALIGN_VAL) &
485                     CCDC_HSIZE_OFF_MASK, CCDC_HSIZE_OFF);
486         else
487                 /* else one pixel will take 2 byte */
488                 regw(((params->win.width * CCDC_TWO_BYTES_PER_PIXEL) +
489                     CCDC_32BYTE_ALIGN_VAL) & CCDC_HSIZE_OFF_MASK,
490                     CCDC_HSIZE_OFF);
491
492         /* Set value for SDOFST */
493         if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
494                 if (params->image_invert_enable) {
495                         /* For intelace inverse mode */
496                         regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST);
497                         dev_dbg(ccdc_cfg.dev, "\nWriting 0x4B6D to SDOFST..\n");
498                 }
499
500                 else {
501                         /* For intelace non inverse mode */
502                         regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST);
503                         dev_dbg(ccdc_cfg.dev, "\nWriting 0x0249 to SDOFST..\n");
504                 }
505         } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
506                 regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST);
507                 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to SDOFST...\n");
508         }
509
510         /*
511          * Configure video port pixel selection (VPOUT)
512          * Here -1 is to make the height value less than FMT_VERT.FMTLNV
513          */
514         if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
515                 val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK))
516                     << CCDC_VP_OUT_VERT_NUM_SHIFT;
517         else
518                 val =
519                     ((((params->win.height >> CCDC_INTERLACED_HEIGHT_SHIFT) -
520                      1) & CCDC_VP_OUT_VERT_NUM_MASK)) <<
521                     CCDC_VP_OUT_VERT_NUM_SHIFT;
522
523         val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK)
524             << CCDC_VP_OUT_HORZ_NUM_SHIFT;
525         val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK;
526         regw(val, CCDC_VP_OUT);
527
528         dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to VP_OUT...\n", val);
529         regw(syn_mode, CCDC_SYN_MODE);
530         dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode);
531
532         ccdc_sbl_reset();
533         dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw...");
534         ccdc_readregs();
535 }
536
537 static int ccdc_configure(void)
538 {
539         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
540                 ccdc_config_raw();
541         else
542                 ccdc_config_ycbcr();
543         return 0;
544 }
545
546 static int ccdc_set_buftype(enum ccdc_buftype buf_type)
547 {
548         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
549                 ccdc_cfg.bayer.buf_type = buf_type;
550         else
551                 ccdc_cfg.ycbcr.buf_type = buf_type;
552         return 0;
553 }
554
555 static enum ccdc_buftype ccdc_get_buftype(void)
556 {
557         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
558                 return ccdc_cfg.bayer.buf_type;
559         return ccdc_cfg.ycbcr.buf_type;
560 }
561
562 static int ccdc_enum_pix(u32 *pix, int i)
563 {
564         int ret = -EINVAL;
565         if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
566                 if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
567                         *pix = ccdc_raw_bayer_pix_formats[i];
568                         ret = 0;
569                 }
570         } else {
571                 if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
572                         *pix = ccdc_raw_yuv_pix_formats[i];
573                         ret = 0;
574                 }
575         }
576         return ret;
577 }
578
579 static int ccdc_set_pixel_format(u32 pixfmt)
580 {
581         if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
582                 ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
583                 if (pixfmt == V4L2_PIX_FMT_SBGGR8)
584                         ccdc_cfg.bayer.config_params.alaw.enable = 1;
585                 else if (pixfmt != V4L2_PIX_FMT_SBGGR16)
586                         return -EINVAL;
587         } else {
588                 if (pixfmt == V4L2_PIX_FMT_YUYV)
589                         ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
590                 else if (pixfmt == V4L2_PIX_FMT_UYVY)
591                         ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
592                 else
593                         return -EINVAL;
594         }
595         return 0;
596 }
597
598 static u32 ccdc_get_pixel_format(void)
599 {
600         struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw;
601         u32 pixfmt;
602
603         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
604                 if (alaw->enable)
605                         pixfmt = V4L2_PIX_FMT_SBGGR8;
606                 else
607                         pixfmt = V4L2_PIX_FMT_SBGGR16;
608         else {
609                 if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
610                         pixfmt = V4L2_PIX_FMT_YUYV;
611                 else
612                         pixfmt = V4L2_PIX_FMT_UYVY;
613         }
614         return pixfmt;
615 }
616
617 static int ccdc_set_image_window(struct v4l2_rect *win)
618 {
619         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
620                 ccdc_cfg.bayer.win = *win;
621         else
622                 ccdc_cfg.ycbcr.win = *win;
623         return 0;
624 }
625
626 static void ccdc_get_image_window(struct v4l2_rect *win)
627 {
628         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
629                 *win = ccdc_cfg.bayer.win;
630         else
631                 *win = ccdc_cfg.ycbcr.win;
632 }
633
634 static unsigned int ccdc_get_line_length(void)
635 {
636         struct ccdc_config_params_raw *config_params =
637                                 &ccdc_cfg.bayer.config_params;
638         unsigned int len;
639
640         if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
641                 if ((config_params->alaw.enable) ||
642                     (config_params->data_sz == CCDC_DATA_8BITS))
643                         len = ccdc_cfg.bayer.win.width;
644                 else
645                         len = ccdc_cfg.bayer.win.width * 2;
646         } else
647                 len = ccdc_cfg.ycbcr.win.width * 2;
648         return ALIGN(len, 32);
649 }
650
651 static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
652 {
653         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
654                 ccdc_cfg.bayer.frm_fmt = frm_fmt;
655         else
656                 ccdc_cfg.ycbcr.frm_fmt = frm_fmt;
657         return 0;
658 }
659
660 static enum ccdc_frmfmt ccdc_get_frame_format(void)
661 {
662         if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
663                 return ccdc_cfg.bayer.frm_fmt;
664         else
665                 return ccdc_cfg.ycbcr.frm_fmt;
666 }
667
668 static int ccdc_getfid(void)
669 {
670         return (regr(CCDC_SYN_MODE) >> 15) & 1;
671 }
672
673 /* misc operations */
674 static inline void ccdc_setfbaddr(unsigned long addr)
675 {
676         regw(addr & 0xffffffe0, CCDC_SDR_ADDR);
677 }
678
679 static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
680 {
681         ccdc_cfg.if_type = params->if_type;
682
683         switch (params->if_type) {
684         case VPFE_BT656:
685         case VPFE_YCBCR_SYNC_16:
686         case VPFE_YCBCR_SYNC_8:
687         case VPFE_BT656_10BIT:
688                 ccdc_cfg.ycbcr.vd_pol = params->vdpol;
689                 ccdc_cfg.ycbcr.hd_pol = params->hdpol;
690                 break;
691         default:
692                 /* TODO add support for raw bayer here */
693                 return -EINVAL;
694         }
695         return 0;
696 }
697
698 static void ccdc_save_context(void)
699 {
700         ccdc_ctx[CCDC_PCR >> 2] = regr(CCDC_PCR);
701         ccdc_ctx[CCDC_SYN_MODE >> 2] = regr(CCDC_SYN_MODE);
702         ccdc_ctx[CCDC_HD_VD_WID >> 2] = regr(CCDC_HD_VD_WID);
703         ccdc_ctx[CCDC_PIX_LINES >> 2] = regr(CCDC_PIX_LINES);
704         ccdc_ctx[CCDC_HORZ_INFO >> 2] = regr(CCDC_HORZ_INFO);
705         ccdc_ctx[CCDC_VERT_START >> 2] = regr(CCDC_VERT_START);
706         ccdc_ctx[CCDC_VERT_LINES >> 2] = regr(CCDC_VERT_LINES);
707         ccdc_ctx[CCDC_CULLING >> 2] = regr(CCDC_CULLING);
708         ccdc_ctx[CCDC_HSIZE_OFF >> 2] = regr(CCDC_HSIZE_OFF);
709         ccdc_ctx[CCDC_SDOFST >> 2] = regr(CCDC_SDOFST);
710         ccdc_ctx[CCDC_SDR_ADDR >> 2] = regr(CCDC_SDR_ADDR);
711         ccdc_ctx[CCDC_CLAMP >> 2] = regr(CCDC_CLAMP);
712         ccdc_ctx[CCDC_DCSUB >> 2] = regr(CCDC_DCSUB);
713         ccdc_ctx[CCDC_COLPTN >> 2] = regr(CCDC_COLPTN);
714         ccdc_ctx[CCDC_BLKCMP >> 2] = regr(CCDC_BLKCMP);
715         ccdc_ctx[CCDC_FPC >> 2] = regr(CCDC_FPC);
716         ccdc_ctx[CCDC_FPC_ADDR >> 2] = regr(CCDC_FPC_ADDR);
717         ccdc_ctx[CCDC_VDINT >> 2] = regr(CCDC_VDINT);
718         ccdc_ctx[CCDC_ALAW >> 2] = regr(CCDC_ALAW);
719         ccdc_ctx[CCDC_REC656IF >> 2] = regr(CCDC_REC656IF);
720         ccdc_ctx[CCDC_CCDCFG >> 2] = regr(CCDC_CCDCFG);
721         ccdc_ctx[CCDC_FMTCFG >> 2] = regr(CCDC_FMTCFG);
722         ccdc_ctx[CCDC_FMT_HORZ >> 2] = regr(CCDC_FMT_HORZ);
723         ccdc_ctx[CCDC_FMT_VERT >> 2] = regr(CCDC_FMT_VERT);
724         ccdc_ctx[CCDC_FMT_ADDR0 >> 2] = regr(CCDC_FMT_ADDR0);
725         ccdc_ctx[CCDC_FMT_ADDR1 >> 2] = regr(CCDC_FMT_ADDR1);
726         ccdc_ctx[CCDC_FMT_ADDR2 >> 2] = regr(CCDC_FMT_ADDR2);
727         ccdc_ctx[CCDC_FMT_ADDR3 >> 2] = regr(CCDC_FMT_ADDR3);
728         ccdc_ctx[CCDC_FMT_ADDR4 >> 2] = regr(CCDC_FMT_ADDR4);
729         ccdc_ctx[CCDC_FMT_ADDR5 >> 2] = regr(CCDC_FMT_ADDR5);
730         ccdc_ctx[CCDC_FMT_ADDR6 >> 2] = regr(CCDC_FMT_ADDR6);
731         ccdc_ctx[CCDC_FMT_ADDR7 >> 2] = regr(CCDC_FMT_ADDR7);
732         ccdc_ctx[CCDC_PRGEVEN_0 >> 2] = regr(CCDC_PRGEVEN_0);
733         ccdc_ctx[CCDC_PRGEVEN_1 >> 2] = regr(CCDC_PRGEVEN_1);
734         ccdc_ctx[CCDC_PRGODD_0 >> 2] = regr(CCDC_PRGODD_0);
735         ccdc_ctx[CCDC_PRGODD_1 >> 2] = regr(CCDC_PRGODD_1);
736         ccdc_ctx[CCDC_VP_OUT >> 2] = regr(CCDC_VP_OUT);
737 }
738
739 static void ccdc_restore_context(void)
740 {
741         regw(ccdc_ctx[CCDC_SYN_MODE >> 2], CCDC_SYN_MODE);
742         regw(ccdc_ctx[CCDC_HD_VD_WID >> 2], CCDC_HD_VD_WID);
743         regw(ccdc_ctx[CCDC_PIX_LINES >> 2], CCDC_PIX_LINES);
744         regw(ccdc_ctx[CCDC_HORZ_INFO >> 2], CCDC_HORZ_INFO);
745         regw(ccdc_ctx[CCDC_VERT_START >> 2], CCDC_VERT_START);
746         regw(ccdc_ctx[CCDC_VERT_LINES >> 2], CCDC_VERT_LINES);
747         regw(ccdc_ctx[CCDC_CULLING >> 2], CCDC_CULLING);
748         regw(ccdc_ctx[CCDC_HSIZE_OFF >> 2], CCDC_HSIZE_OFF);
749         regw(ccdc_ctx[CCDC_SDOFST >> 2], CCDC_SDOFST);
750         regw(ccdc_ctx[CCDC_SDR_ADDR >> 2], CCDC_SDR_ADDR);
751         regw(ccdc_ctx[CCDC_CLAMP >> 2], CCDC_CLAMP);
752         regw(ccdc_ctx[CCDC_DCSUB >> 2], CCDC_DCSUB);
753         regw(ccdc_ctx[CCDC_COLPTN >> 2], CCDC_COLPTN);
754         regw(ccdc_ctx[CCDC_BLKCMP >> 2], CCDC_BLKCMP);
755         regw(ccdc_ctx[CCDC_FPC >> 2], CCDC_FPC);
756         regw(ccdc_ctx[CCDC_FPC_ADDR >> 2], CCDC_FPC_ADDR);
757         regw(ccdc_ctx[CCDC_VDINT >> 2], CCDC_VDINT);
758         regw(ccdc_ctx[CCDC_ALAW >> 2], CCDC_ALAW);
759         regw(ccdc_ctx[CCDC_REC656IF >> 2], CCDC_REC656IF);
760         regw(ccdc_ctx[CCDC_CCDCFG >> 2], CCDC_CCDCFG);
761         regw(ccdc_ctx[CCDC_FMTCFG >> 2], CCDC_FMTCFG);
762         regw(ccdc_ctx[CCDC_FMT_HORZ >> 2], CCDC_FMT_HORZ);
763         regw(ccdc_ctx[CCDC_FMT_VERT >> 2], CCDC_FMT_VERT);
764         regw(ccdc_ctx[CCDC_FMT_ADDR0 >> 2], CCDC_FMT_ADDR0);
765         regw(ccdc_ctx[CCDC_FMT_ADDR1 >> 2], CCDC_FMT_ADDR1);
766         regw(ccdc_ctx[CCDC_FMT_ADDR2 >> 2], CCDC_FMT_ADDR2);
767         regw(ccdc_ctx[CCDC_FMT_ADDR3 >> 2], CCDC_FMT_ADDR3);
768         regw(ccdc_ctx[CCDC_FMT_ADDR4 >> 2], CCDC_FMT_ADDR4);
769         regw(ccdc_ctx[CCDC_FMT_ADDR5 >> 2], CCDC_FMT_ADDR5);
770         regw(ccdc_ctx[CCDC_FMT_ADDR6 >> 2], CCDC_FMT_ADDR6);
771         regw(ccdc_ctx[CCDC_FMT_ADDR7 >> 2], CCDC_FMT_ADDR7);
772         regw(ccdc_ctx[CCDC_PRGEVEN_0 >> 2], CCDC_PRGEVEN_0);
773         regw(ccdc_ctx[CCDC_PRGEVEN_1 >> 2], CCDC_PRGEVEN_1);
774         regw(ccdc_ctx[CCDC_PRGODD_0 >> 2], CCDC_PRGODD_0);
775         regw(ccdc_ctx[CCDC_PRGODD_1 >> 2], CCDC_PRGODD_1);
776         regw(ccdc_ctx[CCDC_VP_OUT >> 2], CCDC_VP_OUT);
777         regw(ccdc_ctx[CCDC_PCR >> 2], CCDC_PCR);
778 }
779 static const struct ccdc_hw_device ccdc_hw_dev = {
780         .name = "DM6446 CCDC",
781         .owner = THIS_MODULE,
782         .hw_ops = {
783                 .open = ccdc_open,
784                 .close = ccdc_close,
785                 .reset = ccdc_sbl_reset,
786                 .enable = ccdc_enable,
787                 .set_hw_if_params = ccdc_set_hw_if_params,
788                 .configure = ccdc_configure,
789                 .set_buftype = ccdc_set_buftype,
790                 .get_buftype = ccdc_get_buftype,
791                 .enum_pix = ccdc_enum_pix,
792                 .set_pixel_format = ccdc_set_pixel_format,
793                 .get_pixel_format = ccdc_get_pixel_format,
794                 .set_frame_format = ccdc_set_frame_format,
795                 .get_frame_format = ccdc_get_frame_format,
796                 .set_image_window = ccdc_set_image_window,
797                 .get_image_window = ccdc_get_image_window,
798                 .get_line_length = ccdc_get_line_length,
799                 .setfbaddr = ccdc_setfbaddr,
800                 .getfid = ccdc_getfid,
801         },
802 };
803
804 static int dm644x_ccdc_probe(struct platform_device *pdev)
805 {
806         struct resource *res;
807         int status = 0;
808
809         /*
810          * first try to register with vpfe. If not correct platform, then we
811          * don't have to iomap
812          */
813         status = vpfe_register_ccdc_device(&ccdc_hw_dev);
814         if (status < 0)
815                 return status;
816
817         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
818         if (!res) {
819                 status = -ENODEV;
820                 goto fail_nores;
821         }
822
823         res = request_mem_region(res->start, resource_size(res), res->name);
824         if (!res) {
825                 status = -EBUSY;
826                 goto fail_nores;
827         }
828
829         ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res));
830         if (!ccdc_cfg.base_addr) {
831                 status = -ENOMEM;
832                 goto fail_nomem;
833         }
834
835         ccdc_cfg.dev = &pdev->dev;
836         printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
837         return 0;
838 fail_nomem:
839         release_mem_region(res->start, resource_size(res));
840 fail_nores:
841         vpfe_unregister_ccdc_device(&ccdc_hw_dev);
842         return status;
843 }
844
845 static int dm644x_ccdc_remove(struct platform_device *pdev)
846 {
847         struct resource *res;
848
849         iounmap(ccdc_cfg.base_addr);
850         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
851         if (res)
852                 release_mem_region(res->start, resource_size(res));
853         vpfe_unregister_ccdc_device(&ccdc_hw_dev);
854         return 0;
855 }
856
857 static int dm644x_ccdc_suspend(struct device *dev)
858 {
859         /* Save CCDC context */
860         ccdc_save_context();
861         /* Disable CCDC */
862         ccdc_enable(0);
863
864         return 0;
865 }
866
867 static int dm644x_ccdc_resume(struct device *dev)
868 {
869         /* Restore CCDC context */
870         ccdc_restore_context();
871
872         return 0;
873 }
874
875 static const struct dev_pm_ops dm644x_ccdc_pm_ops = {
876         .suspend = dm644x_ccdc_suspend,
877         .resume = dm644x_ccdc_resume,
878 };
879
880 static struct platform_driver dm644x_ccdc_driver = {
881         .driver = {
882                 .name   = "dm644x_ccdc",
883                 .pm = &dm644x_ccdc_pm_ops,
884         },
885         .remove = dm644x_ccdc_remove,
886         .probe = dm644x_ccdc_probe,
887 };
888
889 module_platform_driver(dm644x_ccdc_driver);