dm644x_ccdc.c 24 KB

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