~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/davinci/dm644x_ccdc.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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