Linux-libre 3.0.53-gnu1
[librecmc/linux-libre.git] / drivers / media / video / davinci / dm355_ccdc.c
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
49 MODULE_LICENSE("GPL");
50 MODULE_DESCRIPTION("CCDC Driver for DM355");
51 MODULE_AUTHOR("Texas Instruments");
52
53 static 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 */
123 static u32 ccdc_raw_bayer_pix_formats[] =
124                 {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
125
126 /* Raw YUV formats */
127 static u32 ccdc_raw_yuv_pix_formats[] =
128                 {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
129
130 /* register access routines */
131 static inline u32 regr(u32 offset)
132 {
133         return __raw_readl(ccdc_cfg.base_addr + offset);
134 }
135
136 static inline void regw(u32 val, u32 offset)
137 {
138         __raw_writel(val, ccdc_cfg.base_addr + offset);
139 }
140
141 static 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
150 static 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
159 static 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  */
174 static 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
210 static int ccdc_open(struct device *device)
211 {
212         return ccdc_restore_defaults();
213 }
214
215 static 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  */
227 static 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
271 static 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 */
330 static 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 */
356 static 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  */
421 static 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  */
447 static 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  */
467 int 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  */
504 static 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  */
557 static 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  */
602 static 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 */
614 static 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
781 static 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
790 static 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 }
798 static 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
805 static 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
822 static 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 }
842 static 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 }
860 static 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
869 static 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
877 static 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
894 static 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
903 static 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
911 static int ccdc_getfid(void)
912 {
913         return  (regr(MODESET) >> 15) & 1;
914 }
915
916 /* misc operations */
917 static inline void ccdc_setfbaddr(unsigned long addr)
918 {
919         regw((addr >> 21) & 0x007f, STADRH);
920         regw((addr >> 5) & 0x0ffff, STADRL);
921 }
922
923 static 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
941 static 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
967 static 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;
1035 fail_sclk:
1036         clk_put(ccdc_cfg.sclk);
1037 fail_mclk:
1038         clk_put(ccdc_cfg.mclk);
1039 fail_nomap:
1040         iounmap(ccdc_cfg.base_addr);
1041 fail_nomem:
1042         release_mem_region(res->start, resource_size(res));
1043 fail_nores:
1044         vpfe_unregister_ccdc_device(&ccdc_hw_dev);
1045         return status;
1046 }
1047
1048 static 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
1062 static 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
1071 static int __init dm355_ccdc_init(void)
1072 {
1073         return platform_driver_register(&dm355_ccdc_driver);
1074 }
1075
1076 static void __exit dm355_ccdc_exit(void)
1077 {
1078         platform_driver_unregister(&dm355_ccdc_driver);
1079 }
1080
1081 module_init(dm355_ccdc_init);
1082 module_exit(dm355_ccdc_exit);