include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[GitHub/mt8127/android_kernel_alcatel_ttab.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 /* register access routines */
105 static inline u32 regr(u32 offset)
106 {
107 return __raw_readl(ccdc_cfg.base_addr + offset);
108 }
109
110 static inline void regw(u32 val, u32 offset)
111 {
112 __raw_writel(val, ccdc_cfg.base_addr + offset);
113 }
114
115 static void ccdc_enable(int flag)
116 {
117 regw(flag, CCDC_PCR);
118 }
119
120 static void ccdc_enable_vport(int flag)
121 {
122 if (flag)
123 /* enable video port */
124 regw(CCDC_ENABLE_VIDEO_PORT, CCDC_FMTCFG);
125 else
126 regw(CCDC_DISABLE_VIDEO_PORT, CCDC_FMTCFG);
127 }
128
129 /*
130 * ccdc_setwin()
131 * This function will configure the window size
132 * to be capture in CCDC reg
133 */
134 void ccdc_setwin(struct v4l2_rect *image_win,
135 enum ccdc_frmfmt frm_fmt,
136 int ppc)
137 {
138 int horz_start, horz_nr_pixels;
139 int vert_start, vert_nr_lines;
140 int val = 0, mid_img = 0;
141
142 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_setwin...");
143 /*
144 * ppc - per pixel count. indicates how many pixels per cell
145 * output to SDRAM. example, for ycbcr, it is one y and one c, so 2.
146 * raw capture this is 1
147 */
148 horz_start = image_win->left << (ppc - 1);
149 horz_nr_pixels = (image_win->width << (ppc - 1)) - 1;
150 regw((horz_start << CCDC_HORZ_INFO_SPH_SHIFT) | horz_nr_pixels,
151 CCDC_HORZ_INFO);
152
153 vert_start = image_win->top;
154
155 if (frm_fmt == CCDC_FRMFMT_INTERLACED) {
156 vert_nr_lines = (image_win->height >> 1) - 1;
157 vert_start >>= 1;
158 /* Since first line doesn't have any data */
159 vert_start += 1;
160 /* configure VDINT0 */
161 val = (vert_start << CCDC_VDINT_VDINT0_SHIFT);
162 regw(val, CCDC_VDINT);
163
164 } else {
165 /* Since first line doesn't have any data */
166 vert_start += 1;
167 vert_nr_lines = image_win->height - 1;
168 /*
169 * configure VDINT0 and VDINT1. VDINT1 will be at half
170 * of image height
171 */
172 mid_img = vert_start + (image_win->height / 2);
173 val = (vert_start << CCDC_VDINT_VDINT0_SHIFT) |
174 (mid_img & CCDC_VDINT_VDINT1_MASK);
175 regw(val, CCDC_VDINT);
176
177 }
178 regw((vert_start << CCDC_VERT_START_SLV0_SHIFT) | vert_start,
179 CCDC_VERT_START);
180 regw(vert_nr_lines, CCDC_VERT_LINES);
181 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin...");
182 }
183
184 static void ccdc_readregs(void)
185 {
186 unsigned int val = 0;
187
188 val = regr(CCDC_ALAW);
189 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to ALAW...\n", val);
190 val = regr(CCDC_CLAMP);
191 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to CLAMP...\n", val);
192 val = regr(CCDC_DCSUB);
193 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to DCSUB...\n", val);
194 val = regr(CCDC_BLKCMP);
195 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to BLKCMP...\n", val);
196 val = regr(CCDC_FPC_ADDR);
197 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC_ADDR...\n", val);
198 val = regr(CCDC_FPC);
199 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FPC...\n", val);
200 val = regr(CCDC_FMTCFG);
201 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMTCFG...\n", val);
202 val = regr(CCDC_COLPTN);
203 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to COLPTN...\n", val);
204 val = regr(CCDC_FMT_HORZ);
205 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_HORZ...\n", val);
206 val = regr(CCDC_FMT_VERT);
207 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to FMT_VERT...\n", val);
208 val = regr(CCDC_HSIZE_OFF);
209 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HSIZE_OFF...\n", val);
210 val = regr(CCDC_SDOFST);
211 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SDOFST...\n", val);
212 val = regr(CCDC_VP_OUT);
213 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VP_OUT...\n", val);
214 val = regr(CCDC_SYN_MODE);
215 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to SYN_MODE...\n", val);
216 val = regr(CCDC_HORZ_INFO);
217 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to HORZ_INFO...\n", val);
218 val = regr(CCDC_VERT_START);
219 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_START...\n", val);
220 val = regr(CCDC_VERT_LINES);
221 dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val);
222 }
223
224 static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam)
225 {
226 if (ccdcparam->alaw.enable) {
227 if ((ccdcparam->alaw.gama_wd > CCDC_GAMMA_BITS_09_0) ||
228 (ccdcparam->alaw.gama_wd < CCDC_GAMMA_BITS_15_6) ||
229 (ccdcparam->alaw.gama_wd < ccdcparam->data_sz)) {
230 dev_dbg(ccdc_cfg.dev, "\nInvalid data line select");
231 return -1;
232 }
233 }
234 return 0;
235 }
236
237 static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params)
238 {
239 struct ccdc_config_params_raw *config_params =
240 &ccdc_cfg.bayer.config_params;
241 unsigned int *fpc_virtaddr = NULL;
242 unsigned int *fpc_physaddr = NULL;
243
244 memcpy(config_params, raw_params, sizeof(*raw_params));
245 /*
246 * allocate memory for fault pixel table and copy the user
247 * values to the table
248 */
249 if (!config_params->fault_pxl.enable)
250 return 0;
251
252 fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr;
253 fpc_virtaddr = (unsigned int *)phys_to_virt(
254 (unsigned long)fpc_physaddr);
255 /*
256 * Allocate memory for FPC table if current
257 * FPC table buffer is not big enough to
258 * accomodate FPC Number requested
259 */
260 if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) {
261 if (fpc_physaddr != NULL) {
262 free_pages((unsigned long)fpc_physaddr,
263 get_order
264 (config_params->fault_pxl.fp_num *
265 FP_NUM_BYTES));
266 }
267
268 /* Allocate memory for FPC table */
269 fpc_virtaddr =
270 (unsigned int *)__get_free_pages(GFP_KERNEL | GFP_DMA,
271 get_order(raw_params->
272 fault_pxl.fp_num *
273 FP_NUM_BYTES));
274
275 if (fpc_virtaddr == NULL) {
276 dev_dbg(ccdc_cfg.dev,
277 "\nUnable to allocate memory for FPC");
278 return -EFAULT;
279 }
280 fpc_physaddr =
281 (unsigned int *)virt_to_phys((void *)fpc_virtaddr);
282 }
283
284 /* Copy number of fault pixels and FPC table */
285 config_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num;
286 if (copy_from_user(fpc_virtaddr,
287 (void __user *)raw_params->fault_pxl.fpc_table_addr,
288 config_params->fault_pxl.fp_num * FP_NUM_BYTES)) {
289 dev_dbg(ccdc_cfg.dev, "\n copy_from_user failed");
290 return -EFAULT;
291 }
292 config_params->fault_pxl.fpc_table_addr = (unsigned int)fpc_physaddr;
293 return 0;
294 }
295
296 static int ccdc_close(struct device *dev)
297 {
298 struct ccdc_config_params_raw *config_params =
299 &ccdc_cfg.bayer.config_params;
300 unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL;
301
302 fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr;
303
304 if (fpc_physaddr != NULL) {
305 fpc_virtaddr = (unsigned int *)
306 phys_to_virt((unsigned long)fpc_physaddr);
307 free_pages((unsigned long)fpc_virtaddr,
308 get_order(config_params->fault_pxl.fp_num *
309 FP_NUM_BYTES));
310 }
311 return 0;
312 }
313
314 /*
315 * ccdc_restore_defaults()
316 * This function will write defaults to all CCDC registers
317 */
318 static void ccdc_restore_defaults(void)
319 {
320 int i;
321
322 /* disable CCDC */
323 ccdc_enable(0);
324 /* set all registers to default value */
325 for (i = 4; i <= 0x94; i += 4)
326 regw(0, i);
327 regw(CCDC_NO_CULLING, CCDC_CULLING);
328 regw(CCDC_GAMMA_BITS_11_2, CCDC_ALAW);
329 }
330
331 static int ccdc_open(struct device *device)
332 {
333 ccdc_restore_defaults();
334 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
335 ccdc_enable_vport(1);
336 return 0;
337 }
338
339 static void ccdc_sbl_reset(void)
340 {
341 vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O);
342 }
343
344 /* Parameter operations */
345 static int ccdc_set_params(void __user *params)
346 {
347 struct ccdc_config_params_raw ccdc_raw_params;
348 int x;
349
350 if (ccdc_cfg.if_type != VPFE_RAW_BAYER)
351 return -EINVAL;
352
353 x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
354 if (x) {
355 dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying"
356 "ccdc params, %d\n", x);
357 return -EFAULT;
358 }
359
360 if (!validate_ccdc_param(&ccdc_raw_params)) {
361 if (!ccdc_update_raw_params(&ccdc_raw_params))
362 return 0;
363 }
364 return -EINVAL;
365 }
366
367 /*
368 * ccdc_config_ycbcr()
369 * This function will configure CCDC for YCbCr video capture
370 */
371 void ccdc_config_ycbcr(void)
372 {
373 struct ccdc_params_ycbcr *params = &ccdc_cfg.ycbcr;
374 u32 syn_mode;
375
376 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_ycbcr...");
377 /*
378 * first restore the CCDC registers to default values
379 * This is important since we assume default values to be set in
380 * a lot of registers that we didn't touch
381 */
382 ccdc_restore_defaults();
383
384 /*
385 * configure pixel format, frame format, configure video frame
386 * format, enable output to SDRAM, enable internal timing generator
387 * and 8bit pack mode
388 */
389 syn_mode = (((params->pix_fmt & CCDC_SYN_MODE_INPMOD_MASK) <<
390 CCDC_SYN_MODE_INPMOD_SHIFT) |
391 ((params->frm_fmt & CCDC_SYN_FLDMODE_MASK) <<
392 CCDC_SYN_FLDMODE_SHIFT) | CCDC_VDHDEN_ENABLE |
393 CCDC_WEN_ENABLE | CCDC_DATA_PACK_ENABLE);
394
395 /* setup BT.656 sync mode */
396 if (params->bt656_enable) {
397 regw(CCDC_REC656IF_BT656_EN, CCDC_REC656IF);
398
399 /*
400 * configure the FID, VD, HD pin polarity,
401 * fld,hd pol positive, vd negative, 8-bit data
402 */
403 syn_mode |= CCDC_SYN_MODE_VD_POL_NEGATIVE | CCDC_SYN_MODE_8BITS;
404 } else {
405 /* y/c external sync mode */
406 syn_mode |= (((params->fid_pol & CCDC_FID_POL_MASK) <<
407 CCDC_FID_POL_SHIFT) |
408 ((params->hd_pol & CCDC_HD_POL_MASK) <<
409 CCDC_HD_POL_SHIFT) |
410 ((params->vd_pol & CCDC_VD_POL_MASK) <<
411 CCDC_VD_POL_SHIFT));
412 }
413 regw(syn_mode, CCDC_SYN_MODE);
414
415 /* configure video window */
416 ccdc_setwin(&params->win, params->frm_fmt, 2);
417
418 /*
419 * configure the order of y cb cr in SDRAM, and disable latch
420 * internal register on vsync
421 */
422 regw((params->pix_order << CCDC_CCDCFG_Y8POS_SHIFT) |
423 CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
424
425 /*
426 * configure the horizontal line offset. This should be a
427 * on 32 byte bondary. So clear LSB 5 bits
428 */
429 regw(((params->win.width * 2 + 31) & ~0x1f), CCDC_HSIZE_OFF);
430
431 /* configure the memory line offset */
432 if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED)
433 /* two fields are interleaved in memory */
434 regw(CCDC_SDOFST_FIELD_INTERLEAVED, CCDC_SDOFST);
435
436 ccdc_sbl_reset();
437 dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_config_ycbcr...\n");
438 ccdc_readregs();
439 }
440
441 static void ccdc_config_black_clamp(struct ccdc_black_clamp *bclamp)
442 {
443 u32 val;
444
445 if (!bclamp->enable) {
446 /* configure DCSub */
447 val = (bclamp->dc_sub) & CCDC_BLK_DC_SUB_MASK;
448 regw(val, CCDC_DCSUB);
449 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to DCSUB...\n", val);
450 regw(CCDC_CLAMP_DEFAULT_VAL, CCDC_CLAMP);
451 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to CLAMP...\n");
452 return;
453 }
454 /*
455 * Configure gain, Start pixel, No of line to be avg,
456 * No of pixel/line to be avg, & Enable the Black clamping
457 */
458 val = ((bclamp->sgain & CCDC_BLK_SGAIN_MASK) |
459 ((bclamp->start_pixel & CCDC_BLK_ST_PXL_MASK) <<
460 CCDC_BLK_ST_PXL_SHIFT) |
461 ((bclamp->sample_ln & CCDC_BLK_SAMPLE_LINE_MASK) <<
462 CCDC_BLK_SAMPLE_LINE_SHIFT) |
463 ((bclamp->sample_pixel & CCDC_BLK_SAMPLE_LN_MASK) <<
464 CCDC_BLK_SAMPLE_LN_SHIFT) | CCDC_BLK_CLAMP_ENABLE);
465 regw(val, CCDC_CLAMP);
466 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to CLAMP...\n", val);
467 /* If Black clamping is enable then make dcsub 0 */
468 regw(CCDC_DCSUB_DEFAULT_VAL, CCDC_DCSUB);
469 dev_dbg(ccdc_cfg.dev, "\nWriting 0x00000000 to DCSUB...\n");
470 }
471
472 static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp)
473 {
474 u32 val;
475
476 val = ((bcomp->b & CCDC_BLK_COMP_MASK) |
477 ((bcomp->gb & CCDC_BLK_COMP_MASK) <<
478 CCDC_BLK_COMP_GB_COMP_SHIFT) |
479 ((bcomp->gr & CCDC_BLK_COMP_MASK) <<
480 CCDC_BLK_COMP_GR_COMP_SHIFT) |
481 ((bcomp->r & CCDC_BLK_COMP_MASK) <<
482 CCDC_BLK_COMP_R_COMP_SHIFT));
483 regw(val, CCDC_BLKCMP);
484 }
485
486 static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc)
487 {
488 u32 val;
489
490 /* Initially disable FPC */
491 val = CCDC_FPC_DISABLE;
492 regw(val, CCDC_FPC);
493
494 if (!fpc->enable)
495 return;
496
497 /* Configure Fault pixel if needed */
498 regw(fpc->fpc_table_addr, CCDC_FPC_ADDR);
499 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC_ADDR...\n",
500 (fpc->fpc_table_addr));
501 /* Write the FPC params with FPC disable */
502 val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK;
503 regw(val, CCDC_FPC);
504
505 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val);
506 /* read the FPC register */
507 val = regr(CCDC_FPC) | CCDC_FPC_ENABLE;
508 regw(val, CCDC_FPC);
509 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val);
510 }
511
512 /*
513 * ccdc_config_raw()
514 * This function will configure CCDC for Raw capture mode
515 */
516 void ccdc_config_raw(void)
517 {
518 struct ccdc_params_raw *params = &ccdc_cfg.bayer;
519 struct ccdc_config_params_raw *config_params =
520 &ccdc_cfg.bayer.config_params;
521 unsigned int syn_mode = 0;
522 unsigned int val;
523
524 dev_dbg(ccdc_cfg.dev, "\nStarting ccdc_config_raw...");
525
526 /* Reset CCDC */
527 ccdc_restore_defaults();
528
529 /* Disable latching function registers on VSYNC */
530 regw(CCDC_LATCH_ON_VSYNC_DISABLE, CCDC_CCDCFG);
531
532 /*
533 * Configure the vertical sync polarity(SYN_MODE.VDPOL),
534 * horizontal sync polarity (SYN_MODE.HDPOL), frame id polarity
535 * (SYN_MODE.FLDPOL), frame format(progressive or interlace),
536 * data size(SYNMODE.DATSIZ), &pixel format (Input mode), output
537 * SDRAM, enable internal timing generator
538 */
539 syn_mode =
540 (((params->vd_pol & CCDC_VD_POL_MASK) << CCDC_VD_POL_SHIFT) |
541 ((params->hd_pol & CCDC_HD_POL_MASK) << CCDC_HD_POL_SHIFT) |
542 ((params->fid_pol & CCDC_FID_POL_MASK) << CCDC_FID_POL_SHIFT) |
543 ((params->frm_fmt & CCDC_FRM_FMT_MASK) << CCDC_FRM_FMT_SHIFT) |
544 ((config_params->data_sz & CCDC_DATA_SZ_MASK) <<
545 CCDC_DATA_SZ_SHIFT) |
546 ((params->pix_fmt & CCDC_PIX_FMT_MASK) << CCDC_PIX_FMT_SHIFT) |
547 CCDC_WEN_ENABLE | CCDC_VDHDEN_ENABLE);
548
549 /* Enable and configure aLaw register if needed */
550 if (config_params->alaw.enable) {
551 val = ((config_params->alaw.gama_wd &
552 CCDC_ALAW_GAMA_WD_MASK) | CCDC_ALAW_ENABLE);
553 regw(val, CCDC_ALAW);
554 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to ALAW...\n", val);
555 }
556
557 /* Configure video window */
558 ccdc_setwin(&params->win, params->frm_fmt, CCDC_PPC_RAW);
559
560 /* Configure Black Clamp */
561 ccdc_config_black_clamp(&config_params->blk_clamp);
562
563 /* Configure Black level compensation */
564 ccdc_config_black_compense(&config_params->blk_comp);
565
566 /* Configure Fault Pixel Correction */
567 ccdc_config_fpc(&config_params->fault_pxl);
568
569 /* If data size is 8 bit then pack the data */
570 if ((config_params->data_sz == CCDC_DATA_8BITS) ||
571 config_params->alaw.enable)
572 syn_mode |= CCDC_DATA_PACK_ENABLE;
573
574 #ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE
575 /* enable video port */
576 val = CCDC_ENABLE_VIDEO_PORT;
577 #else
578 /* disable video port */
579 val = CCDC_DISABLE_VIDEO_PORT;
580 #endif
581
582 if (config_params->data_sz == CCDC_DATA_8BITS)
583 val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
584 << CCDC_FMTCFG_VPIN_SHIFT;
585 else
586 val |= (config_params->data_sz & CCDC_FMTCFG_VPIN_MASK)
587 << CCDC_FMTCFG_VPIN_SHIFT;
588 /* Write value in FMTCFG */
589 regw(val, CCDC_FMTCFG);
590
591 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMTCFG...\n", val);
592 /* Configure the color pattern according to mt9t001 sensor */
593 regw(CCDC_COLPTN_VAL, CCDC_COLPTN);
594
595 dev_dbg(ccdc_cfg.dev, "\nWriting 0xBB11BB11 to COLPTN...\n");
596 /*
597 * Configure Data formatter(Video port) pixel selection
598 * (FMT_HORZ, FMT_VERT)
599 */
600 val = ((params->win.left & CCDC_FMT_HORZ_FMTSPH_MASK) <<
601 CCDC_FMT_HORZ_FMTSPH_SHIFT) |
602 (params->win.width & CCDC_FMT_HORZ_FMTLNH_MASK);
603 regw(val, CCDC_FMT_HORZ);
604
605 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_HORZ...\n", val);
606 val = (params->win.top & CCDC_FMT_VERT_FMTSLV_MASK)
607 << CCDC_FMT_VERT_FMTSLV_SHIFT;
608 if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
609 val |= (params->win.height) & CCDC_FMT_VERT_FMTLNV_MASK;
610 else
611 val |= (params->win.height >> 1) & CCDC_FMT_VERT_FMTLNV_MASK;
612
613 dev_dbg(ccdc_cfg.dev, "\nparams->win.height 0x%x ...\n",
614 params->win.height);
615 regw(val, CCDC_FMT_VERT);
616
617 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FMT_VERT...\n", val);
618
619 dev_dbg(ccdc_cfg.dev, "\nbelow regw(val, FMT_VERT)...");
620
621 /*
622 * Configure Horizontal offset register. If pack 8 is enabled then
623 * 1 pixel will take 1 byte
624 */
625 if ((config_params->data_sz == CCDC_DATA_8BITS) ||
626 config_params->alaw.enable)
627 regw((params->win.width + CCDC_32BYTE_ALIGN_VAL) &
628 CCDC_HSIZE_OFF_MASK, CCDC_HSIZE_OFF);
629 else
630 /* else one pixel will take 2 byte */
631 regw(((params->win.width * CCDC_TWO_BYTES_PER_PIXEL) +
632 CCDC_32BYTE_ALIGN_VAL) & CCDC_HSIZE_OFF_MASK,
633 CCDC_HSIZE_OFF);
634
635 /* Set value for SDOFST */
636 if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
637 if (params->image_invert_enable) {
638 /* For intelace inverse mode */
639 regw(CCDC_INTERLACED_IMAGE_INVERT, CCDC_SDOFST);
640 dev_dbg(ccdc_cfg.dev, "\nWriting 0x4B6D to SDOFST..\n");
641 }
642
643 else {
644 /* For intelace non inverse mode */
645 regw(CCDC_INTERLACED_NO_IMAGE_INVERT, CCDC_SDOFST);
646 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0249 to SDOFST..\n");
647 }
648 } else if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE) {
649 regw(CCDC_PROGRESSIVE_NO_IMAGE_INVERT, CCDC_SDOFST);
650 dev_dbg(ccdc_cfg.dev, "\nWriting 0x0000 to SDOFST...\n");
651 }
652
653 /*
654 * Configure video port pixel selection (VPOUT)
655 * Here -1 is to make the height value less than FMT_VERT.FMTLNV
656 */
657 if (params->frm_fmt == CCDC_FRMFMT_PROGRESSIVE)
658 val = (((params->win.height - 1) & CCDC_VP_OUT_VERT_NUM_MASK))
659 << CCDC_VP_OUT_VERT_NUM_SHIFT;
660 else
661 val =
662 ((((params->win.height >> CCDC_INTERLACED_HEIGHT_SHIFT) -
663 1) & CCDC_VP_OUT_VERT_NUM_MASK)) <<
664 CCDC_VP_OUT_VERT_NUM_SHIFT;
665
666 val |= ((((params->win.width))) & CCDC_VP_OUT_HORZ_NUM_MASK)
667 << CCDC_VP_OUT_HORZ_NUM_SHIFT;
668 val |= (params->win.left) & CCDC_VP_OUT_HORZ_ST_MASK;
669 regw(val, CCDC_VP_OUT);
670
671 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to VP_OUT...\n", val);
672 regw(syn_mode, CCDC_SYN_MODE);
673 dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to SYN_MODE...\n", syn_mode);
674
675 ccdc_sbl_reset();
676 dev_dbg(ccdc_cfg.dev, "\nend of ccdc_config_raw...");
677 ccdc_readregs();
678 }
679
680 static int ccdc_configure(void)
681 {
682 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
683 ccdc_config_raw();
684 else
685 ccdc_config_ycbcr();
686 return 0;
687 }
688
689 static int ccdc_set_buftype(enum ccdc_buftype buf_type)
690 {
691 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
692 ccdc_cfg.bayer.buf_type = buf_type;
693 else
694 ccdc_cfg.ycbcr.buf_type = buf_type;
695 return 0;
696 }
697
698 static enum ccdc_buftype ccdc_get_buftype(void)
699 {
700 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
701 return ccdc_cfg.bayer.buf_type;
702 return ccdc_cfg.ycbcr.buf_type;
703 }
704
705 static int ccdc_enum_pix(u32 *pix, int i)
706 {
707 int ret = -EINVAL;
708 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
709 if (i < ARRAY_SIZE(ccdc_raw_bayer_pix_formats)) {
710 *pix = ccdc_raw_bayer_pix_formats[i];
711 ret = 0;
712 }
713 } else {
714 if (i < ARRAY_SIZE(ccdc_raw_yuv_pix_formats)) {
715 *pix = ccdc_raw_yuv_pix_formats[i];
716 ret = 0;
717 }
718 }
719 return ret;
720 }
721
722 static int ccdc_set_pixel_format(u32 pixfmt)
723 {
724 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
725 ccdc_cfg.bayer.pix_fmt = CCDC_PIXFMT_RAW;
726 if (pixfmt == V4L2_PIX_FMT_SBGGR8)
727 ccdc_cfg.bayer.config_params.alaw.enable = 1;
728 else if (pixfmt != V4L2_PIX_FMT_SBGGR16)
729 return -EINVAL;
730 } else {
731 if (pixfmt == V4L2_PIX_FMT_YUYV)
732 ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_YCBYCR;
733 else if (pixfmt == V4L2_PIX_FMT_UYVY)
734 ccdc_cfg.ycbcr.pix_order = CCDC_PIXORDER_CBYCRY;
735 else
736 return -EINVAL;
737 }
738 return 0;
739 }
740
741 static u32 ccdc_get_pixel_format(void)
742 {
743 struct ccdc_a_law *alaw = &ccdc_cfg.bayer.config_params.alaw;
744 u32 pixfmt;
745
746 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
747 if (alaw->enable)
748 pixfmt = V4L2_PIX_FMT_SBGGR8;
749 else
750 pixfmt = V4L2_PIX_FMT_SBGGR16;
751 else {
752 if (ccdc_cfg.ycbcr.pix_order == CCDC_PIXORDER_YCBYCR)
753 pixfmt = V4L2_PIX_FMT_YUYV;
754 else
755 pixfmt = V4L2_PIX_FMT_UYVY;
756 }
757 return pixfmt;
758 }
759
760 static int ccdc_set_image_window(struct v4l2_rect *win)
761 {
762 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
763 ccdc_cfg.bayer.win = *win;
764 else
765 ccdc_cfg.ycbcr.win = *win;
766 return 0;
767 }
768
769 static void ccdc_get_image_window(struct v4l2_rect *win)
770 {
771 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
772 *win = ccdc_cfg.bayer.win;
773 else
774 *win = ccdc_cfg.ycbcr.win;
775 }
776
777 static unsigned int ccdc_get_line_length(void)
778 {
779 struct ccdc_config_params_raw *config_params =
780 &ccdc_cfg.bayer.config_params;
781 unsigned int len;
782
783 if (ccdc_cfg.if_type == VPFE_RAW_BAYER) {
784 if ((config_params->alaw.enable) ||
785 (config_params->data_sz == CCDC_DATA_8BITS))
786 len = ccdc_cfg.bayer.win.width;
787 else
788 len = ccdc_cfg.bayer.win.width * 2;
789 } else
790 len = ccdc_cfg.ycbcr.win.width * 2;
791 return ALIGN(len, 32);
792 }
793
794 static int ccdc_set_frame_format(enum ccdc_frmfmt frm_fmt)
795 {
796 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
797 ccdc_cfg.bayer.frm_fmt = frm_fmt;
798 else
799 ccdc_cfg.ycbcr.frm_fmt = frm_fmt;
800 return 0;
801 }
802
803 static enum ccdc_frmfmt ccdc_get_frame_format(void)
804 {
805 if (ccdc_cfg.if_type == VPFE_RAW_BAYER)
806 return ccdc_cfg.bayer.frm_fmt;
807 else
808 return ccdc_cfg.ycbcr.frm_fmt;
809 }
810
811 static int ccdc_getfid(void)
812 {
813 return (regr(CCDC_SYN_MODE) >> 15) & 1;
814 }
815
816 /* misc operations */
817 static inline void ccdc_setfbaddr(unsigned long addr)
818 {
819 regw(addr & 0xffffffe0, CCDC_SDR_ADDR);
820 }
821
822 static int ccdc_set_hw_if_params(struct vpfe_hw_if_param *params)
823 {
824 ccdc_cfg.if_type = params->if_type;
825
826 switch (params->if_type) {
827 case VPFE_BT656:
828 case VPFE_YCBCR_SYNC_16:
829 case VPFE_YCBCR_SYNC_8:
830 ccdc_cfg.ycbcr.vd_pol = params->vdpol;
831 ccdc_cfg.ycbcr.hd_pol = params->hdpol;
832 break;
833 default:
834 /* TODO add support for raw bayer here */
835 return -EINVAL;
836 }
837 return 0;
838 }
839
840 static struct ccdc_hw_device ccdc_hw_dev = {
841 .name = "DM6446 CCDC",
842 .owner = THIS_MODULE,
843 .hw_ops = {
844 .open = ccdc_open,
845 .close = ccdc_close,
846 .reset = ccdc_sbl_reset,
847 .enable = ccdc_enable,
848 .set_hw_if_params = ccdc_set_hw_if_params,
849 .set_params = ccdc_set_params,
850 .configure = ccdc_configure,
851 .set_buftype = ccdc_set_buftype,
852 .get_buftype = ccdc_get_buftype,
853 .enum_pix = ccdc_enum_pix,
854 .set_pixel_format = ccdc_set_pixel_format,
855 .get_pixel_format = ccdc_get_pixel_format,
856 .set_frame_format = ccdc_set_frame_format,
857 .get_frame_format = ccdc_get_frame_format,
858 .set_image_window = ccdc_set_image_window,
859 .get_image_window = ccdc_get_image_window,
860 .get_line_length = ccdc_get_line_length,
861 .setfbaddr = ccdc_setfbaddr,
862 .getfid = ccdc_getfid,
863 },
864 };
865
866 static int __init dm644x_ccdc_probe(struct platform_device *pdev)
867 {
868 struct resource *res;
869 int status = 0;
870
871 /*
872 * first try to register with vpfe. If not correct platform, then we
873 * don't have to iomap
874 */
875 status = vpfe_register_ccdc_device(&ccdc_hw_dev);
876 if (status < 0)
877 return status;
878
879 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
880 if (!res) {
881 status = -ENODEV;
882 goto fail_nores;
883 }
884
885 res = request_mem_region(res->start, resource_size(res), res->name);
886 if (!res) {
887 status = -EBUSY;
888 goto fail_nores;
889 }
890
891 ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res));
892 if (!ccdc_cfg.base_addr) {
893 status = -ENOMEM;
894 goto fail_nomem;
895 }
896
897 /* Get and enable Master clock */
898 ccdc_cfg.mclk = clk_get(&pdev->dev, "master");
899 if (IS_ERR(ccdc_cfg.mclk)) {
900 status = PTR_ERR(ccdc_cfg.mclk);
901 goto fail_nomap;
902 }
903 if (clk_enable(ccdc_cfg.mclk)) {
904 status = -ENODEV;
905 goto fail_mclk;
906 }
907
908 /* Get and enable Slave clock */
909 ccdc_cfg.sclk = clk_get(&pdev->dev, "slave");
910 if (IS_ERR(ccdc_cfg.sclk)) {
911 status = PTR_ERR(ccdc_cfg.sclk);
912 goto fail_mclk;
913 }
914 if (clk_enable(ccdc_cfg.sclk)) {
915 status = -ENODEV;
916 goto fail_sclk;
917 }
918 ccdc_cfg.dev = &pdev->dev;
919 printk(KERN_NOTICE "%s is registered with vpfe.\n", ccdc_hw_dev.name);
920 return 0;
921 fail_sclk:
922 clk_put(ccdc_cfg.sclk);
923 fail_mclk:
924 clk_put(ccdc_cfg.mclk);
925 fail_nomap:
926 iounmap(ccdc_cfg.base_addr);
927 fail_nomem:
928 release_mem_region(res->start, resource_size(res));
929 fail_nores:
930 vpfe_unregister_ccdc_device(&ccdc_hw_dev);
931 return status;
932 }
933
934 static int dm644x_ccdc_remove(struct platform_device *pdev)
935 {
936 struct resource *res;
937
938 clk_put(ccdc_cfg.mclk);
939 clk_put(ccdc_cfg.sclk);
940 iounmap(ccdc_cfg.base_addr);
941 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
942 if (res)
943 release_mem_region(res->start, resource_size(res));
944 vpfe_unregister_ccdc_device(&ccdc_hw_dev);
945 return 0;
946 }
947
948 static struct platform_driver dm644x_ccdc_driver = {
949 .driver = {
950 .name = "dm644x_ccdc",
951 .owner = THIS_MODULE,
952 },
953 .remove = __devexit_p(dm644x_ccdc_remove),
954 .probe = dm644x_ccdc_probe,
955 };
956
957 static int __init dm644x_ccdc_init(void)
958 {
959 return platform_driver_register(&dm644x_ccdc_driver);
960 }
961
962 static void __exit dm644x_ccdc_exit(void)
963 {
964 platform_driver_unregister(&dm644x_ccdc_driver);
965 }
966
967 module_init(dm644x_ccdc_init);
968 module_exit(dm644x_ccdc_exit);