dm644x_ccdc.c 32 KB

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