camif-regs.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /*
  2. * Samsung s3c24xx/s3c64xx SoC CAMIF driver
  3. *
  4. * Copyright (C) 2012 Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
  5. * Copyright (C) 2012 Tomasz Figa <tomasz.figa@gmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
  12. #include <linux/delay.h>
  13. #include "camif-regs.h"
  14. #define camif_write(_camif, _off, _val) writel(_val, (_camif)->io_base + (_off))
  15. #define camif_read(_camif, _off) readl((_camif)->io_base + (_off))
  16. void camif_hw_reset(struct camif_dev *camif)
  17. {
  18. u32 cfg;
  19. cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
  20. cfg |= CISRCFMT_ITU601_8BIT;
  21. camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
  22. /* S/W reset */
  23. cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  24. cfg |= CIGCTRL_SWRST;
  25. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
  26. cfg |= CIGCTRL_IRQ_LEVEL;
  27. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  28. udelay(10);
  29. cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  30. cfg &= ~CIGCTRL_SWRST;
  31. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  32. udelay(10);
  33. }
  34. void camif_hw_clear_pending_irq(struct camif_vp *vp)
  35. {
  36. u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_CIGCTRL);
  37. cfg |= CIGCTRL_IRQ_CLR(vp->id);
  38. camif_write(vp->camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  39. }
  40. /*
  41. * Sets video test pattern (off, color bar, horizontal or vertical gradient).
  42. * External sensor pixel clock must be active for the test pattern to work.
  43. */
  44. void camif_hw_set_test_pattern(struct camif_dev *camif, unsigned int pattern)
  45. {
  46. u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  47. cfg &= ~CIGCTRL_TESTPATTERN_MASK;
  48. cfg |= (pattern << 27);
  49. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  50. }
  51. void camif_hw_set_effect(struct camif_dev *camif, unsigned int effect,
  52. unsigned int cr, unsigned int cb)
  53. {
  54. static const struct v4l2_control colorfx[] = {
  55. { V4L2_COLORFX_NONE, CIIMGEFF_FIN_BYPASS },
  56. { V4L2_COLORFX_BW, CIIMGEFF_FIN_ARBITRARY },
  57. { V4L2_COLORFX_SEPIA, CIIMGEFF_FIN_ARBITRARY },
  58. { V4L2_COLORFX_NEGATIVE, CIIMGEFF_FIN_NEGATIVE },
  59. { V4L2_COLORFX_ART_FREEZE, CIIMGEFF_FIN_ARTFREEZE },
  60. { V4L2_COLORFX_EMBOSS, CIIMGEFF_FIN_EMBOSSING },
  61. { V4L2_COLORFX_SILHOUETTE, CIIMGEFF_FIN_SILHOUETTE },
  62. { V4L2_COLORFX_SET_CBCR, CIIMGEFF_FIN_ARBITRARY },
  63. };
  64. unsigned int i, cfg;
  65. for (i = 0; i < ARRAY_SIZE(colorfx); i++)
  66. if (colorfx[i].id == effect)
  67. break;
  68. if (i == ARRAY_SIZE(colorfx))
  69. return;
  70. cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset));
  71. /* Set effect */
  72. cfg &= ~CIIMGEFF_FIN_MASK;
  73. cfg |= colorfx[i].value;
  74. /* Set both paths */
  75. if (camif->variant->ip_revision >= S3C6400_CAMIF_IP_REV) {
  76. if (effect == V4L2_COLORFX_NONE)
  77. cfg &= ~CIIMGEFF_IE_ENABLE_MASK;
  78. else
  79. cfg |= CIIMGEFF_IE_ENABLE_MASK;
  80. }
  81. cfg &= ~CIIMGEFF_PAT_CBCR_MASK;
  82. cfg |= cr | (cb << 13);
  83. camif_write(camif, S3C_CAMIF_REG_CIIMGEFF(camif->vp->offset), cfg);
  84. }
  85. static const u32 src_pixfmt_map[8][2] = {
  86. { MEDIA_BUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
  87. { MEDIA_BUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
  88. { MEDIA_BUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
  89. { MEDIA_BUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
  90. };
  91. /* Set camera input pixel format and resolution */
  92. void camif_hw_set_source_format(struct camif_dev *camif)
  93. {
  94. struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
  95. int i;
  96. u32 cfg;
  97. for (i = ARRAY_SIZE(src_pixfmt_map) - 1; i >= 0; i--) {
  98. if (src_pixfmt_map[i][0] == mf->code)
  99. break;
  100. }
  101. if (i < 0) {
  102. i = 0;
  103. dev_err(camif->dev,
  104. "Unsupported pixel code, falling back to %#08x\n",
  105. src_pixfmt_map[i][0]);
  106. }
  107. cfg = camif_read(camif, S3C_CAMIF_REG_CISRCFMT);
  108. cfg &= ~(CISRCFMT_ORDER422_MASK | CISRCFMT_SIZE_CAM_MASK);
  109. cfg |= (mf->width << 16) | mf->height;
  110. cfg |= src_pixfmt_map[i][1];
  111. camif_write(camif, S3C_CAMIF_REG_CISRCFMT, cfg);
  112. }
  113. /* Set the camera host input window offsets (cropping) */
  114. void camif_hw_set_camera_crop(struct camif_dev *camif)
  115. {
  116. struct v4l2_mbus_framefmt *mf = &camif->mbus_fmt;
  117. struct v4l2_rect *crop = &camif->camif_crop;
  118. u32 hoff2, voff2;
  119. u32 cfg;
  120. /* Note: s3c244x requirement: left = f_width - rect.width / 2 */
  121. cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
  122. cfg &= ~(CIWDOFST_OFST_MASK | CIWDOFST_WINOFSEN);
  123. cfg |= (crop->left << 16) | crop->top;
  124. if (crop->left != 0 || crop->top != 0)
  125. cfg |= CIWDOFST_WINOFSEN;
  126. camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
  127. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
  128. hoff2 = mf->width - crop->width - crop->left;
  129. voff2 = mf->height - crop->height - crop->top;
  130. cfg = (hoff2 << 16) | voff2;
  131. camif_write(camif, S3C_CAMIF_REG_CIWDOFST2, cfg);
  132. }
  133. }
  134. void camif_hw_clear_fifo_overflow(struct camif_vp *vp)
  135. {
  136. struct camif_dev *camif = vp->camif;
  137. u32 cfg;
  138. cfg = camif_read(camif, S3C_CAMIF_REG_CIWDOFST);
  139. if (vp->id == 0)
  140. cfg |= (CIWDOFST_CLROVCOFIY | CIWDOFST_CLROVCOFICB |
  141. CIWDOFST_CLROVCOFICR);
  142. else
  143. cfg |= (/* CIWDOFST_CLROVPRFIY | */ CIWDOFST_CLROVPRFICB |
  144. CIWDOFST_CLROVPRFICR);
  145. camif_write(camif, S3C_CAMIF_REG_CIWDOFST, cfg);
  146. }
  147. /* Set video bus signals polarity */
  148. void camif_hw_set_camera_bus(struct camif_dev *camif)
  149. {
  150. unsigned int flags = camif->pdata.sensor.flags;
  151. u32 cfg = camif_read(camif, S3C_CAMIF_REG_CIGCTRL);
  152. cfg &= ~(CIGCTRL_INVPOLPCLK | CIGCTRL_INVPOLVSYNC |
  153. CIGCTRL_INVPOLHREF | CIGCTRL_INVPOLFIELD);
  154. if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
  155. cfg |= CIGCTRL_INVPOLPCLK;
  156. if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
  157. cfg |= CIGCTRL_INVPOLVSYNC;
  158. /*
  159. * HREF is normally high during frame active data
  160. * transmission and low during horizontal synchronization
  161. * period. Thus HREF active high means HSYNC active low.
  162. */
  163. if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
  164. cfg |= CIGCTRL_INVPOLHREF; /* HREF active low */
  165. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
  166. if (flags & V4L2_MBUS_FIELD_EVEN_LOW)
  167. cfg |= CIGCTRL_INVPOLFIELD;
  168. cfg |= CIGCTRL_FIELDMODE;
  169. }
  170. pr_debug("Setting CIGCTRL to: %#x\n", cfg);
  171. camif_write(camif, S3C_CAMIF_REG_CIGCTRL, cfg);
  172. }
  173. void camif_hw_set_output_addr(struct camif_vp *vp,
  174. struct camif_addr *paddr, int i)
  175. {
  176. struct camif_dev *camif = vp->camif;
  177. camif_write(camif, S3C_CAMIF_REG_CIYSA(vp->id, i), paddr->y);
  178. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV
  179. || vp->id == VP_CODEC) {
  180. camif_write(camif, S3C_CAMIF_REG_CICBSA(vp->id, i),
  181. paddr->cb);
  182. camif_write(camif, S3C_CAMIF_REG_CICRSA(vp->id, i),
  183. paddr->cr);
  184. }
  185. pr_debug("dst_buf[%d]: %pad, cb: %pad, cr: %pad\n",
  186. i, &paddr->y, &paddr->cb, &paddr->cr);
  187. }
  188. static void camif_hw_set_out_dma_size(struct camif_vp *vp)
  189. {
  190. struct camif_frame *frame = &vp->out_frame;
  191. u32 cfg;
  192. cfg = camif_read(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
  193. cfg &= ~CITRGFMT_TARGETSIZE_MASK;
  194. cfg |= (frame->f_width << 16) | frame->f_height;
  195. camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
  196. }
  197. static void camif_get_dma_burst(u32 width, u32 ybpp, u32 *mburst, u32 *rburst)
  198. {
  199. unsigned int nwords = width * ybpp / 4;
  200. unsigned int div, rem;
  201. if (WARN_ON(width < 8 || (width * ybpp) & 7))
  202. return;
  203. for (div = 16; div >= 2; div /= 2) {
  204. if (nwords < div)
  205. continue;
  206. rem = nwords & (div - 1);
  207. if (rem == 0) {
  208. *mburst = div;
  209. *rburst = div;
  210. break;
  211. }
  212. if (rem == div / 2 || rem == div / 4) {
  213. *mburst = div;
  214. *rburst = rem;
  215. break;
  216. }
  217. }
  218. }
  219. void camif_hw_set_output_dma(struct camif_vp *vp)
  220. {
  221. struct camif_dev *camif = vp->camif;
  222. struct camif_frame *frame = &vp->out_frame;
  223. const struct camif_fmt *fmt = vp->out_fmt;
  224. unsigned int ymburst = 0, yrburst = 0;
  225. u32 cfg;
  226. camif_hw_set_out_dma_size(vp);
  227. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV) {
  228. struct camif_dma_offset *offset = &frame->dma_offset;
  229. /* Set the input dma offsets. */
  230. cfg = S3C_CISS_OFFS_INITIAL(offset->initial);
  231. cfg |= S3C_CISS_OFFS_LINE(offset->line);
  232. camif_write(camif, S3C_CAMIF_REG_CISSY(vp->id), cfg);
  233. camif_write(camif, S3C_CAMIF_REG_CISSCB(vp->id), cfg);
  234. camif_write(camif, S3C_CAMIF_REG_CISSCR(vp->id), cfg);
  235. }
  236. /* Configure DMA burst values */
  237. camif_get_dma_burst(frame->rect.width, fmt->ybpp, &ymburst, &yrburst);
  238. cfg = camif_read(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset));
  239. cfg &= ~CICTRL_BURST_MASK;
  240. cfg |= CICTRL_YBURST1(ymburst) | CICTRL_YBURST2(yrburst);
  241. cfg |= CICTRL_CBURST1(ymburst / 2) | CICTRL_CBURST2(yrburst / 2);
  242. camif_write(camif, S3C_CAMIF_REG_CICTRL(vp->id, vp->offset), cfg);
  243. pr_debug("ymburst: %u, yrburst: %u\n", ymburst, yrburst);
  244. }
  245. void camif_hw_set_input_path(struct camif_vp *vp)
  246. {
  247. u32 cfg = camif_read(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id));
  248. cfg &= ~MSCTRL_SEL_DMA_CAM;
  249. camif_write(vp->camif, S3C_CAMIF_REG_MSCTRL(vp->id), cfg);
  250. }
  251. void camif_hw_set_target_format(struct camif_vp *vp)
  252. {
  253. struct camif_dev *camif = vp->camif;
  254. struct camif_frame *frame = &vp->out_frame;
  255. u32 cfg;
  256. pr_debug("fw: %d, fh: %d color: %d\n", frame->f_width,
  257. frame->f_height, vp->out_fmt->color);
  258. cfg = camif_read(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
  259. cfg &= ~CITRGFMT_TARGETSIZE_MASK;
  260. if (camif->variant->ip_revision == S3C244X_CAMIF_IP_REV) {
  261. /* We currently support only YCbCr 4:2:2 at the camera input */
  262. cfg |= CITRGFMT_IN422;
  263. cfg &= ~CITRGFMT_OUT422;
  264. if (vp->out_fmt->color == IMG_FMT_YCBCR422P)
  265. cfg |= CITRGFMT_OUT422;
  266. } else {
  267. cfg &= ~CITRGFMT_OUTFORMAT_MASK;
  268. switch (vp->out_fmt->color) {
  269. case IMG_FMT_RGB565...IMG_FMT_XRGB8888:
  270. cfg |= CITRGFMT_OUTFORMAT_RGB;
  271. break;
  272. case IMG_FMT_YCBCR420...IMG_FMT_YCRCB420:
  273. cfg |= CITRGFMT_OUTFORMAT_YCBCR420;
  274. break;
  275. case IMG_FMT_YCBCR422P:
  276. cfg |= CITRGFMT_OUTFORMAT_YCBCR422;
  277. break;
  278. case IMG_FMT_YCBYCR422...IMG_FMT_CRYCBY422:
  279. cfg |= CITRGFMT_OUTFORMAT_YCBCR422I;
  280. break;
  281. }
  282. }
  283. /* Rotation is only supported by s3c64xx */
  284. if (vp->rotation == 90 || vp->rotation == 270)
  285. cfg |= (frame->f_height << 16) | frame->f_width;
  286. else
  287. cfg |= (frame->f_width << 16) | frame->f_height;
  288. camif_write(camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
  289. /* Target area, output pixel width * height */
  290. cfg = camif_read(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset));
  291. cfg &= ~CITAREA_MASK;
  292. cfg |= (frame->f_width * frame->f_height);
  293. camif_write(camif, S3C_CAMIF_REG_CITAREA(vp->id, vp->offset), cfg);
  294. }
  295. void camif_hw_set_flip(struct camif_vp *vp)
  296. {
  297. u32 cfg = camif_read(vp->camif,
  298. S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset));
  299. cfg &= ~CITRGFMT_FLIP_MASK;
  300. if (vp->hflip)
  301. cfg |= CITRGFMT_FLIP_Y_MIRROR;
  302. if (vp->vflip)
  303. cfg |= CITRGFMT_FLIP_X_MIRROR;
  304. camif_write(vp->camif, S3C_CAMIF_REG_CITRGFMT(vp->id, vp->offset), cfg);
  305. }
  306. static void camif_hw_set_prescaler(struct camif_vp *vp)
  307. {
  308. struct camif_dev *camif = vp->camif;
  309. struct camif_scaler *sc = &vp->scaler;
  310. u32 cfg, shfactor, addr;
  311. addr = S3C_CAMIF_REG_CISCPRERATIO(vp->id, vp->offset);
  312. shfactor = 10 - (sc->h_shift + sc->v_shift);
  313. cfg = shfactor << 28;
  314. cfg |= (sc->pre_h_ratio << 16) | sc->pre_v_ratio;
  315. camif_write(camif, addr, cfg);
  316. cfg = (sc->pre_dst_width << 16) | sc->pre_dst_height;
  317. camif_write(camif, S3C_CAMIF_REG_CISCPREDST(vp->id, vp->offset), cfg);
  318. }
  319. static void camif_s3c244x_hw_set_scaler(struct camif_vp *vp)
  320. {
  321. struct camif_dev *camif = vp->camif;
  322. struct camif_scaler *scaler = &vp->scaler;
  323. unsigned int color = vp->out_fmt->color;
  324. u32 cfg;
  325. camif_hw_set_prescaler(vp);
  326. cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
  327. cfg &= ~(CISCCTRL_SCALEUP_MASK | CISCCTRL_SCALERBYPASS |
  328. CISCCTRL_MAIN_RATIO_MASK | CIPRSCCTRL_RGB_FORMAT_24BIT);
  329. if (scaler->enable) {
  330. if (scaler->scaleup_h) {
  331. if (vp->id == VP_CODEC)
  332. cfg |= CISCCTRL_SCALEUP_H;
  333. else
  334. cfg |= CIPRSCCTRL_SCALEUP_H;
  335. }
  336. if (scaler->scaleup_v) {
  337. if (vp->id == VP_CODEC)
  338. cfg |= CISCCTRL_SCALEUP_V;
  339. else
  340. cfg |= CIPRSCCTRL_SCALEUP_V;
  341. }
  342. } else {
  343. if (vp->id == VP_CODEC)
  344. cfg |= CISCCTRL_SCALERBYPASS;
  345. }
  346. cfg |= ((scaler->main_h_ratio & 0x1ff) << 16);
  347. cfg |= scaler->main_v_ratio & 0x1ff;
  348. if (vp->id == VP_PREVIEW) {
  349. if (color == IMG_FMT_XRGB8888)
  350. cfg |= CIPRSCCTRL_RGB_FORMAT_24BIT;
  351. cfg |= CIPRSCCTRL_SAMPLE;
  352. }
  353. camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
  354. pr_debug("main: h_ratio: %#x, v_ratio: %#x",
  355. scaler->main_h_ratio, scaler->main_v_ratio);
  356. }
  357. static void camif_s3c64xx_hw_set_scaler(struct camif_vp *vp)
  358. {
  359. struct camif_dev *camif = vp->camif;
  360. struct camif_scaler *scaler = &vp->scaler;
  361. unsigned int color = vp->out_fmt->color;
  362. u32 cfg;
  363. camif_hw_set_prescaler(vp);
  364. cfg = camif_read(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset));
  365. cfg &= ~(CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE
  366. | CISCCTRL_SCALEUP_H | CISCCTRL_SCALEUP_V
  367. | CISCCTRL_SCALERBYPASS | CISCCTRL_ONE2ONE
  368. | CISCCTRL_INRGB_FMT_MASK | CISCCTRL_OUTRGB_FMT_MASK
  369. | CISCCTRL_INTERLACE | CISCCTRL_EXTRGB_EXTENSION
  370. | CISCCTRL_MAIN_RATIO_MASK);
  371. cfg |= (CISCCTRL_CSCR2Y_WIDE | CISCCTRL_CSCY2R_WIDE);
  372. if (!scaler->enable) {
  373. cfg |= CISCCTRL_SCALERBYPASS;
  374. } else {
  375. if (scaler->scaleup_h)
  376. cfg |= CISCCTRL_SCALEUP_H;
  377. if (scaler->scaleup_v)
  378. cfg |= CISCCTRL_SCALEUP_V;
  379. if (scaler->copy)
  380. cfg |= CISCCTRL_ONE2ONE;
  381. }
  382. switch (color) {
  383. case IMG_FMT_RGB666:
  384. cfg |= CISCCTRL_OUTRGB_FMT_RGB666;
  385. break;
  386. case IMG_FMT_XRGB8888:
  387. cfg |= CISCCTRL_OUTRGB_FMT_RGB888;
  388. break;
  389. }
  390. cfg |= (scaler->main_h_ratio & 0x1ff) << 16;
  391. cfg |= scaler->main_v_ratio & 0x1ff;
  392. camif_write(camif, S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset), cfg);
  393. pr_debug("main: h_ratio: %#x, v_ratio: %#x",
  394. scaler->main_h_ratio, scaler->main_v_ratio);
  395. }
  396. void camif_hw_set_scaler(struct camif_vp *vp)
  397. {
  398. unsigned int ip_rev = vp->camif->variant->ip_revision;
  399. if (ip_rev == S3C244X_CAMIF_IP_REV)
  400. camif_s3c244x_hw_set_scaler(vp);
  401. else
  402. camif_s3c64xx_hw_set_scaler(vp);
  403. }
  404. void camif_hw_enable_scaler(struct camif_vp *vp, bool on)
  405. {
  406. u32 addr = S3C_CAMIF_REG_CISCCTRL(vp->id, vp->offset);
  407. u32 cfg;
  408. cfg = camif_read(vp->camif, addr);
  409. if (on)
  410. cfg |= CISCCTRL_SCALERSTART;
  411. else
  412. cfg &= ~CISCCTRL_SCALERSTART;
  413. camif_write(vp->camif, addr, cfg);
  414. }
  415. void camif_hw_set_lastirq(struct camif_vp *vp, int enable)
  416. {
  417. u32 addr = S3C_CAMIF_REG_CICTRL(vp->id, vp->offset);
  418. u32 cfg;
  419. cfg = camif_read(vp->camif, addr);
  420. if (enable)
  421. cfg |= CICTRL_LASTIRQ_ENABLE;
  422. else
  423. cfg &= ~CICTRL_LASTIRQ_ENABLE;
  424. camif_write(vp->camif, addr, cfg);
  425. }
  426. void camif_hw_enable_capture(struct camif_vp *vp)
  427. {
  428. struct camif_dev *camif = vp->camif;
  429. u32 cfg;
  430. cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
  431. camif->stream_count++;
  432. if (camif->variant->ip_revision == S3C6410_CAMIF_IP_REV)
  433. cfg |= CIIMGCPT_CPT_FREN_ENABLE(vp->id);
  434. if (vp->scaler.enable)
  435. cfg |= CIIMGCPT_IMGCPTEN_SC(vp->id);
  436. if (camif->stream_count == 1)
  437. cfg |= CIIMGCPT_IMGCPTEN;
  438. camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
  439. pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
  440. cfg, camif->stream_count);
  441. }
  442. void camif_hw_disable_capture(struct camif_vp *vp)
  443. {
  444. struct camif_dev *camif = vp->camif;
  445. u32 cfg;
  446. cfg = camif_read(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset));
  447. cfg &= ~CIIMGCPT_IMGCPTEN_SC(vp->id);
  448. if (WARN_ON(--(camif->stream_count) < 0))
  449. camif->stream_count = 0;
  450. if (camif->stream_count == 0)
  451. cfg &= ~CIIMGCPT_IMGCPTEN;
  452. pr_debug("CIIMGCPT: %#x, camif->stream_count: %d\n",
  453. cfg, camif->stream_count);
  454. camif_write(camif, S3C_CAMIF_REG_CIIMGCPT(vp->offset), cfg);
  455. }
  456. void camif_hw_dump_regs(struct camif_dev *camif, const char *label)
  457. {
  458. struct {
  459. u32 offset;
  460. const char * const name;
  461. } registers[] = {
  462. { S3C_CAMIF_REG_CISRCFMT, "CISRCFMT" },
  463. { S3C_CAMIF_REG_CIWDOFST, "CIWDOFST" },
  464. { S3C_CAMIF_REG_CIGCTRL, "CIGCTRL" },
  465. { S3C_CAMIF_REG_CIWDOFST2, "CIWDOFST2" },
  466. { S3C_CAMIF_REG_CIYSA(0, 0), "CICOYSA0" },
  467. { S3C_CAMIF_REG_CICBSA(0, 0), "CICOCBSA0" },
  468. { S3C_CAMIF_REG_CICRSA(0, 0), "CICOCRSA0" },
  469. { S3C_CAMIF_REG_CIYSA(0, 1), "CICOYSA1" },
  470. { S3C_CAMIF_REG_CICBSA(0, 1), "CICOCBSA1" },
  471. { S3C_CAMIF_REG_CICRSA(0, 1), "CICOCRSA1" },
  472. { S3C_CAMIF_REG_CIYSA(0, 2), "CICOYSA2" },
  473. { S3C_CAMIF_REG_CICBSA(0, 2), "CICOCBSA2" },
  474. { S3C_CAMIF_REG_CICRSA(0, 2), "CICOCRSA2" },
  475. { S3C_CAMIF_REG_CIYSA(0, 3), "CICOYSA3" },
  476. { S3C_CAMIF_REG_CICBSA(0, 3), "CICOCBSA3" },
  477. { S3C_CAMIF_REG_CICRSA(0, 3), "CICOCRSA3" },
  478. { S3C_CAMIF_REG_CIYSA(1, 0), "CIPRYSA0" },
  479. { S3C_CAMIF_REG_CIYSA(1, 1), "CIPRYSA1" },
  480. { S3C_CAMIF_REG_CIYSA(1, 2), "CIPRYSA2" },
  481. { S3C_CAMIF_REG_CIYSA(1, 3), "CIPRYSA3" },
  482. { S3C_CAMIF_REG_CITRGFMT(0, 0), "CICOTRGFMT" },
  483. { S3C_CAMIF_REG_CITRGFMT(1, 0), "CIPRTRGFMT" },
  484. { S3C_CAMIF_REG_CICTRL(0, 0), "CICOCTRL" },
  485. { S3C_CAMIF_REG_CICTRL(1, 0), "CIPRCTRL" },
  486. { S3C_CAMIF_REG_CISCPREDST(0, 0), "CICOSCPREDST" },
  487. { S3C_CAMIF_REG_CISCPREDST(1, 0), "CIPRSCPREDST" },
  488. { S3C_CAMIF_REG_CISCPRERATIO(0, 0), "CICOSCPRERATIO" },
  489. { S3C_CAMIF_REG_CISCPRERATIO(1, 0), "CIPRSCPRERATIO" },
  490. { S3C_CAMIF_REG_CISCCTRL(0, 0), "CICOSCCTRL" },
  491. { S3C_CAMIF_REG_CISCCTRL(1, 0), "CIPRSCCTRL" },
  492. { S3C_CAMIF_REG_CITAREA(0, 0), "CICOTAREA" },
  493. { S3C_CAMIF_REG_CITAREA(1, 0), "CIPRTAREA" },
  494. { S3C_CAMIF_REG_CISTATUS(0, 0), "CICOSTATUS" },
  495. { S3C_CAMIF_REG_CISTATUS(1, 0), "CIPRSTATUS" },
  496. { S3C_CAMIF_REG_CIIMGCPT(0), "CIIMGCPT" },
  497. };
  498. u32 i;
  499. pr_info("--- %s ---\n", label);
  500. for (i = 0; i < ARRAY_SIZE(registers); i++) {
  501. u32 cfg = readl(camif->io_base + registers[i].offset);
  502. dev_info(camif->dev, "%s:\t0x%08x\n", registers[i].name, cfg);
  503. }
  504. }