dm644x_ccdc.c 31 KB

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