Merge branch 'for-greg' of git://gitorious.org/usb/usb into usb-linus
[pandora-kernel.git] / drivers / media / video / 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  * 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
50 MODULE_LICENSE("GPL");
51 MODULE_DESCRIPTION("CCDC Driver for DM6446");
52 MODULE_AUTHOR("Texas Instruments");
53
54 static 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 */
97 static u32 ccdc_raw_bayer_pix_formats[] =
98         {V4L2_PIX_FMT_SBGGR8, V4L2_PIX_FMT_SBGGR16};
99
100 /* Raw YUV formats */
101 static u32 ccdc_raw_yuv_pix_formats[] =
102         {V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_YUYV};
103
104 /* CCDC Save/Restore context */
105 static u32 ccdc_ctx[CCDC_REG_END / sizeof(u32)];
106
107 /* register access routines */
108 static inline u32 regr(u32 offset)
109 {
110         return __raw_readl(ccdc_cfg.base_addr + offset);
111 }
112
113 static inline void regw(u32 val, u32 offset)
114 {
115         __raw_writel(val, ccdc_cfg.base_addr + offset);
116 }
117
118 static void ccdc_enable(int flag)
119 {
120         regw(flag, CCDC_PCR);
121 }
122
123 static 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  */
137 void 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
187 static 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
227 static 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
240 static 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
299 static 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  */
321 static 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
334 static 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
342 static void ccdc_sbl_reset(void)
343 {
344         vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O);
345 }
346
347 /* Parameter operations */
348 static 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  */
374 void 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
452 static 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
483 static 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
497 static 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  */
527 void 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
691 static 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
700 static 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
709 static 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
716 static 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
733 static 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
752 static 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
771 static 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
780 static 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
788 static 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
805 static 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
814 static 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
822 static int ccdc_getfid(void)
823 {
824         return (regr(CCDC_SYN_MODE) >> 15) & 1;
825 }
826
827 /* misc operations */
828 static inline void ccdc_setfbaddr(unsigned long addr)
829 {
830         regw(addr & 0xffffffe0, CCDC_SDR_ADDR);
831 }
832
833 static 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
852 static 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
893 static 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 }
933 static 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
959 static 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;
1014 fail_sclk:
1015         clk_put(ccdc_cfg.sclk);
1016 fail_mclk:
1017         clk_put(ccdc_cfg.mclk);
1018 fail_nomap:
1019         iounmap(ccdc_cfg.base_addr);
1020 fail_nomem:
1021         release_mem_region(res->start, resource_size(res));
1022 fail_nores:
1023         vpfe_unregister_ccdc_device(&ccdc_hw_dev);
1024         return status;
1025 }
1026
1027 static 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
1041 static 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
1054 static 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
1065 static const struct dev_pm_ops dm644x_ccdc_pm_ops = {
1066         .suspend = dm644x_ccdc_suspend,
1067         .resume = dm644x_ccdc_resume,
1068 };
1069
1070 static 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
1080 static int __init dm644x_ccdc_init(void)
1081 {
1082         return platform_driver_register(&dm644x_ccdc_driver);
1083 }
1084
1085 static void __exit dm644x_ccdc_exit(void)
1086 {
1087         platform_driver_unregister(&dm644x_ccdc_driver);
1088 }
1089
1090 module_init(dm644x_ccdc_init);
1091 module_exit(dm644x_ccdc_exit);