dm644x_ccdc.c 32 KB

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