vpbe_venc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*
  2. * Copyright (C) 2010 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 version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/module.h>
  14. #include <linux/mod_devicetable.h>
  15. #include <linux/kernel.h>
  16. #include <linux/init.h>
  17. #include <linux/ctype.h>
  18. #include <linux/delay.h>
  19. #include <linux/device.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/videodev2.h>
  23. #include <linux/slab.h>
  24. #ifdef CONFIG_ARCH_DAVINCI
  25. #include <mach/hardware.h>
  26. #include <mach/mux.h>
  27. #endif
  28. #include <linux/platform_data/i2c-davinci.h>
  29. #include <linux/io.h>
  30. #include <media/davinci/vpbe_types.h>
  31. #include <media/davinci/vpbe_venc.h>
  32. #include <media/davinci/vpss.h>
  33. #include <media/v4l2-device.h>
  34. #include "vpbe_venc_regs.h"
  35. #define MODULE_NAME "davinci-vpbe-venc"
  36. static const struct platform_device_id vpbe_venc_devtype[] = {
  37. {
  38. .name = DM644X_VPBE_VENC_SUBDEV_NAME,
  39. .driver_data = VPBE_VERSION_1,
  40. }, {
  41. .name = DM365_VPBE_VENC_SUBDEV_NAME,
  42. .driver_data = VPBE_VERSION_2,
  43. }, {
  44. .name = DM355_VPBE_VENC_SUBDEV_NAME,
  45. .driver_data = VPBE_VERSION_3,
  46. },
  47. {
  48. /* sentinel */
  49. }
  50. };
  51. MODULE_DEVICE_TABLE(platform, vpbe_venc_devtype);
  52. static int debug = 2;
  53. module_param(debug, int, 0644);
  54. MODULE_PARM_DESC(debug, "Debug level 0-2");
  55. struct venc_state {
  56. struct v4l2_subdev sd;
  57. struct venc_callback *callback;
  58. struct venc_platform_data *pdata;
  59. struct device *pdev;
  60. u32 output;
  61. v4l2_std_id std;
  62. spinlock_t lock;
  63. void __iomem *venc_base;
  64. void __iomem *vdaccfg_reg;
  65. enum vpbe_version venc_type;
  66. };
  67. static inline struct venc_state *to_state(struct v4l2_subdev *sd)
  68. {
  69. return container_of(sd, struct venc_state, sd);
  70. }
  71. static inline u32 venc_read(struct v4l2_subdev *sd, u32 offset)
  72. {
  73. struct venc_state *venc = to_state(sd);
  74. return readl(venc->venc_base + offset);
  75. }
  76. static inline u32 venc_write(struct v4l2_subdev *sd, u32 offset, u32 val)
  77. {
  78. struct venc_state *venc = to_state(sd);
  79. writel(val, (venc->venc_base + offset));
  80. return val;
  81. }
  82. static inline u32 venc_modify(struct v4l2_subdev *sd, u32 offset,
  83. u32 val, u32 mask)
  84. {
  85. u32 new_val = (venc_read(sd, offset) & ~mask) | (val & mask);
  86. venc_write(sd, offset, new_val);
  87. return new_val;
  88. }
  89. static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
  90. {
  91. struct venc_state *venc = to_state(sd);
  92. writel(val, venc->vdaccfg_reg);
  93. val = readl(venc->vdaccfg_reg);
  94. return val;
  95. }
  96. #define VDAC_COMPONENT 0x543
  97. #define VDAC_S_VIDEO 0x210
  98. /* This function sets the dac of the VPBE for various outputs
  99. */
  100. static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
  101. {
  102. switch (out_index) {
  103. case 0:
  104. v4l2_dbg(debug, 1, sd, "Setting output to Composite\n");
  105. venc_write(sd, VENC_DACSEL, 0);
  106. break;
  107. case 1:
  108. v4l2_dbg(debug, 1, sd, "Setting output to Component\n");
  109. venc_write(sd, VENC_DACSEL, VDAC_COMPONENT);
  110. break;
  111. case 2:
  112. v4l2_dbg(debug, 1, sd, "Setting output to S-video\n");
  113. venc_write(sd, VENC_DACSEL, VDAC_S_VIDEO);
  114. break;
  115. default:
  116. return -EINVAL;
  117. }
  118. return 0;
  119. }
  120. static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
  121. {
  122. struct venc_state *venc = to_state(sd);
  123. v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
  124. if (benable) {
  125. venc_write(sd, VENC_VMOD, 0);
  126. venc_write(sd, VENC_CVBS, 0);
  127. venc_write(sd, VENC_LCDOUT, 0);
  128. venc_write(sd, VENC_HSPLS, 0);
  129. venc_write(sd, VENC_HSTART, 0);
  130. venc_write(sd, VENC_HVALID, 0);
  131. venc_write(sd, VENC_HINT, 0);
  132. venc_write(sd, VENC_VSPLS, 0);
  133. venc_write(sd, VENC_VSTART, 0);
  134. venc_write(sd, VENC_VVALID, 0);
  135. venc_write(sd, VENC_VINT, 0);
  136. venc_write(sd, VENC_YCCCTL, 0);
  137. venc_write(sd, VENC_DACSEL, 0);
  138. } else {
  139. venc_write(sd, VENC_VMOD, 0);
  140. /* disable VCLK output pin enable */
  141. venc_write(sd, VENC_VIDCTL, 0x141);
  142. /* Disable output sync pins */
  143. venc_write(sd, VENC_SYNCCTL, 0);
  144. /* Disable DCLOCK */
  145. venc_write(sd, VENC_DCLKCTL, 0);
  146. venc_write(sd, VENC_DRGBX1, 0x0000057C);
  147. /* Disable LCD output control (accepting default polarity) */
  148. venc_write(sd, VENC_LCDOUT, 0);
  149. if (venc->venc_type != VPBE_VERSION_3)
  150. venc_write(sd, VENC_CMPNT, 0x100);
  151. venc_write(sd, VENC_HSPLS, 0);
  152. venc_write(sd, VENC_HINT, 0);
  153. venc_write(sd, VENC_HSTART, 0);
  154. venc_write(sd, VENC_HVALID, 0);
  155. venc_write(sd, VENC_VSPLS, 0);
  156. venc_write(sd, VENC_VINT, 0);
  157. venc_write(sd, VENC_VSTART, 0);
  158. venc_write(sd, VENC_VVALID, 0);
  159. venc_write(sd, VENC_HSDLY, 0);
  160. venc_write(sd, VENC_VSDLY, 0);
  161. venc_write(sd, VENC_YCCCTL, 0);
  162. venc_write(sd, VENC_VSTARTA, 0);
  163. /* Set OSD clock and OSD Sync Adavance registers */
  164. venc_write(sd, VENC_OSDCLK0, 1);
  165. venc_write(sd, VENC_OSDCLK1, 2);
  166. }
  167. }
  168. static void
  169. venc_enable_vpss_clock(int venc_type,
  170. enum vpbe_enc_timings_type type,
  171. unsigned int pclock)
  172. {
  173. if (venc_type == VPBE_VERSION_1)
  174. return;
  175. if (venc_type == VPBE_VERSION_2 && (type == VPBE_ENC_STD || (type ==
  176. VPBE_ENC_DV_TIMINGS && pclock <= 27000000))) {
  177. vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
  178. vpss_enable_clock(VPSS_VPBE_CLOCK, 1);
  179. return;
  180. }
  181. if (venc_type == VPBE_VERSION_3 && type == VPBE_ENC_STD)
  182. vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 0);
  183. }
  184. #define VDAC_CONFIG_SD_V3 0x0E21A6B6
  185. #define VDAC_CONFIG_SD_V2 0x081141CF
  186. /*
  187. * setting NTSC mode
  188. */
  189. static int venc_set_ntsc(struct v4l2_subdev *sd)
  190. {
  191. struct venc_state *venc = to_state(sd);
  192. struct venc_platform_data *pdata = venc->pdata;
  193. v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
  194. /* Setup clock at VPSS & VENC for SD */
  195. vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
  196. if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
  197. return -EINVAL;
  198. venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_525_60);
  199. venc_enabledigitaloutput(sd, 0);
  200. if (venc->venc_type == VPBE_VERSION_3) {
  201. venc_write(sd, VENC_CLKCTL, 0x01);
  202. venc_write(sd, VENC_VIDCTL, 0);
  203. vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
  204. } else if (venc->venc_type == VPBE_VERSION_2) {
  205. venc_write(sd, VENC_CLKCTL, 0x01);
  206. venc_write(sd, VENC_VIDCTL, 0);
  207. vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
  208. } else {
  209. /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
  210. venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
  211. /* Set REC656 Mode */
  212. venc_write(sd, VENC_YCCCTL, 0x1);
  213. venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
  214. venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
  215. }
  216. venc_write(sd, VENC_VMOD, 0);
  217. venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
  218. VENC_VMOD_VIE);
  219. venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
  220. venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
  221. VENC_VMOD_TVTYP);
  222. venc_write(sd, VENC_DACTST, 0x0);
  223. venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
  224. return 0;
  225. }
  226. /*
  227. * setting PAL mode
  228. */
  229. static int venc_set_pal(struct v4l2_subdev *sd)
  230. {
  231. struct venc_state *venc = to_state(sd);
  232. v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
  233. /* Setup clock at VPSS & VENC for SD */
  234. vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
  235. if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
  236. return -EINVAL;
  237. venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_625_50);
  238. venc_enabledigitaloutput(sd, 0);
  239. if (venc->venc_type == VPBE_VERSION_3) {
  240. venc_write(sd, VENC_CLKCTL, 0x1);
  241. venc_write(sd, VENC_VIDCTL, 0);
  242. vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
  243. } else if (venc->venc_type == VPBE_VERSION_2) {
  244. venc_write(sd, VENC_CLKCTL, 0x1);
  245. venc_write(sd, VENC_VIDCTL, 0);
  246. vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
  247. } else {
  248. /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
  249. venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
  250. /* Set REC656 Mode */
  251. venc_write(sd, VENC_YCCCTL, 0x1);
  252. }
  253. venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
  254. VENC_SYNCCTL_OVD);
  255. venc_write(sd, VENC_VMOD, 0);
  256. venc_modify(sd, VENC_VMOD,
  257. (1 << VENC_VMOD_VIE_SHIFT),
  258. VENC_VMOD_VIE);
  259. venc_modify(sd, VENC_VMOD,
  260. (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
  261. venc_modify(sd, VENC_VMOD,
  262. (1 << VENC_VMOD_TVTYP_SHIFT),
  263. VENC_VMOD_TVTYP);
  264. venc_write(sd, VENC_DACTST, 0x0);
  265. venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
  266. return 0;
  267. }
  268. #define VDAC_CONFIG_HD_V2 0x081141EF
  269. /*
  270. * venc_set_480p59_94
  271. *
  272. * This function configures the video encoder to EDTV(525p) component setting.
  273. */
  274. static int venc_set_480p59_94(struct v4l2_subdev *sd)
  275. {
  276. struct venc_state *venc = to_state(sd);
  277. struct venc_platform_data *pdata = venc->pdata;
  278. v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
  279. if (venc->venc_type != VPBE_VERSION_1 &&
  280. venc->venc_type != VPBE_VERSION_2)
  281. return -EINVAL;
  282. /* Setup clock at VPSS & VENC for SD */
  283. if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
  284. return -EINVAL;
  285. venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
  286. venc_enabledigitaloutput(sd, 0);
  287. if (venc->venc_type == VPBE_VERSION_2)
  288. vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
  289. venc_write(sd, VENC_OSDCLK0, 0);
  290. venc_write(sd, VENC_OSDCLK1, 1);
  291. if (venc->venc_type == VPBE_VERSION_1) {
  292. venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
  293. VENC_VDPRO_DAFRQ);
  294. venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
  295. VENC_VDPRO_DAUPS);
  296. }
  297. venc_write(sd, VENC_VMOD, 0);
  298. venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
  299. VENC_VMOD_VIE);
  300. venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
  301. venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
  302. VENC_VMOD_TVTYP);
  303. venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
  304. VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
  305. venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
  306. return 0;
  307. }
  308. /*
  309. * venc_set_625p
  310. *
  311. * This function configures the video encoder to HDTV(625p) component setting
  312. */
  313. static int venc_set_576p50(struct v4l2_subdev *sd)
  314. {
  315. struct venc_state *venc = to_state(sd);
  316. struct venc_platform_data *pdata = venc->pdata;
  317. v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
  318. if (venc->venc_type != VPBE_VERSION_1 &&
  319. venc->venc_type != VPBE_VERSION_2)
  320. return -EINVAL;
  321. /* Setup clock at VPSS & VENC for SD */
  322. if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
  323. return -EINVAL;
  324. venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
  325. venc_enabledigitaloutput(sd, 0);
  326. if (venc->venc_type == VPBE_VERSION_2)
  327. vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
  328. venc_write(sd, VENC_OSDCLK0, 0);
  329. venc_write(sd, VENC_OSDCLK1, 1);
  330. if (venc->venc_type == VPBE_VERSION_1) {
  331. venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
  332. VENC_VDPRO_DAFRQ);
  333. venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
  334. VENC_VDPRO_DAUPS);
  335. }
  336. venc_write(sd, VENC_VMOD, 0);
  337. venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
  338. VENC_VMOD_VIE);
  339. venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
  340. venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
  341. VENC_VMOD_TVTYP);
  342. venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
  343. VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
  344. venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
  345. return 0;
  346. }
  347. /*
  348. * venc_set_720p60_internal - Setup 720p60 in venc for dm365 only
  349. */
  350. static int venc_set_720p60_internal(struct v4l2_subdev *sd)
  351. {
  352. struct venc_state *venc = to_state(sd);
  353. struct venc_platform_data *pdata = venc->pdata;
  354. if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
  355. return -EINVAL;
  356. venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
  357. venc_enabledigitaloutput(sd, 0);
  358. venc_write(sd, VENC_OSDCLK0, 0);
  359. venc_write(sd, VENC_OSDCLK1, 1);
  360. venc_write(sd, VENC_VMOD, 0);
  361. /* DM365 component HD mode */
  362. venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
  363. VENC_VMOD_VIE);
  364. venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
  365. venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT),
  366. VENC_VMOD_TVTYP);
  367. venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
  368. venc_write(sd, VENC_XHINTVL, 0);
  369. return 0;
  370. }
  371. /*
  372. * venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only
  373. */
  374. static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
  375. {
  376. struct venc_state *venc = to_state(sd);
  377. struct venc_platform_data *pdata = venc->pdata;
  378. if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
  379. return -EINVAL;
  380. venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
  381. venc_enabledigitaloutput(sd, 0);
  382. venc_write(sd, VENC_OSDCLK0, 0);
  383. venc_write(sd, VENC_OSDCLK1, 1);
  384. venc_write(sd, VENC_VMOD, 0);
  385. /* DM365 component HD mode */
  386. venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
  387. VENC_VMOD_VIE);
  388. venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
  389. venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT),
  390. VENC_VMOD_TVTYP);
  391. venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
  392. venc_write(sd, VENC_XHINTVL, 0);
  393. return 0;
  394. }
  395. static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
  396. {
  397. v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
  398. if (norm & V4L2_STD_525_60)
  399. return venc_set_ntsc(sd);
  400. else if (norm & V4L2_STD_625_50)
  401. return venc_set_pal(sd);
  402. return -EINVAL;
  403. }
  404. static int venc_s_dv_timings(struct v4l2_subdev *sd,
  405. struct v4l2_dv_timings *dv_timings)
  406. {
  407. struct venc_state *venc = to_state(sd);
  408. u32 height = dv_timings->bt.height;
  409. int ret;
  410. v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
  411. if (height == 576)
  412. return venc_set_576p50(sd);
  413. else if (height == 480)
  414. return venc_set_480p59_94(sd);
  415. else if ((height == 720) &&
  416. (venc->venc_type == VPBE_VERSION_2)) {
  417. /* TBD setup internal 720p mode here */
  418. ret = venc_set_720p60_internal(sd);
  419. /* for DM365 VPBE, there is DAC inside */
  420. vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
  421. return ret;
  422. } else if ((height == 1080) &&
  423. (venc->venc_type == VPBE_VERSION_2)) {
  424. /* TBD setup internal 1080i mode here */
  425. ret = venc_set_1080i30_internal(sd);
  426. /* for DM365 VPBE, there is DAC inside */
  427. vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
  428. return ret;
  429. }
  430. return -EINVAL;
  431. }
  432. static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
  433. u32 config)
  434. {
  435. struct venc_state *venc = to_state(sd);
  436. int ret;
  437. v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
  438. ret = venc_set_dac(sd, output);
  439. if (!ret)
  440. venc->output = output;
  441. return ret;
  442. }
  443. static long venc_ioctl(struct v4l2_subdev *sd,
  444. unsigned int cmd,
  445. void *arg)
  446. {
  447. u32 val;
  448. switch (cmd) {
  449. case VENC_GET_FLD:
  450. val = venc_read(sd, VENC_VSTAT);
  451. *((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
  452. VENC_VSTAT_FIDST);
  453. break;
  454. default:
  455. v4l2_err(sd, "Wrong IOCTL cmd\n");
  456. break;
  457. }
  458. return 0;
  459. }
  460. static const struct v4l2_subdev_core_ops venc_core_ops = {
  461. .ioctl = venc_ioctl,
  462. };
  463. static const struct v4l2_subdev_video_ops venc_video_ops = {
  464. .s_routing = venc_s_routing,
  465. .s_std_output = venc_s_std_output,
  466. .s_dv_timings = venc_s_dv_timings,
  467. };
  468. static const struct v4l2_subdev_ops venc_ops = {
  469. .core = &venc_core_ops,
  470. .video = &venc_video_ops,
  471. };
  472. static int venc_initialize(struct v4l2_subdev *sd)
  473. {
  474. struct venc_state *venc = to_state(sd);
  475. int ret;
  476. /* Set default to output to composite and std to NTSC */
  477. venc->output = 0;
  478. venc->std = V4L2_STD_525_60;
  479. ret = venc_s_routing(sd, 0, venc->output, 0);
  480. if (ret < 0) {
  481. v4l2_err(sd, "Error setting output during init\n");
  482. return -EINVAL;
  483. }
  484. ret = venc_s_std_output(sd, venc->std);
  485. if (ret < 0) {
  486. v4l2_err(sd, "Error setting std during init\n");
  487. return -EINVAL;
  488. }
  489. return ret;
  490. }
  491. static int venc_device_get(struct device *dev, void *data)
  492. {
  493. struct platform_device *pdev = to_platform_device(dev);
  494. struct venc_state **venc = data;
  495. if (strstr(pdev->name, "vpbe-venc") != NULL)
  496. *venc = platform_get_drvdata(pdev);
  497. return 0;
  498. }
  499. struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
  500. const char *venc_name)
  501. {
  502. struct venc_state *venc = NULL;
  503. bus_for_each_dev(&platform_bus_type, NULL, &venc,
  504. venc_device_get);
  505. if (venc == NULL)
  506. return NULL;
  507. v4l2_subdev_init(&venc->sd, &venc_ops);
  508. strcpy(venc->sd.name, venc_name);
  509. if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
  510. v4l2_err(v4l2_dev,
  511. "vpbe unable to register venc sub device\n");
  512. return NULL;
  513. }
  514. if (venc_initialize(&venc->sd)) {
  515. v4l2_err(v4l2_dev,
  516. "vpbe venc initialization failed\n");
  517. return NULL;
  518. }
  519. return &venc->sd;
  520. }
  521. EXPORT_SYMBOL(venc_sub_dev_init);
  522. static int venc_probe(struct platform_device *pdev)
  523. {
  524. const struct platform_device_id *pdev_id;
  525. struct venc_state *venc;
  526. struct resource *res;
  527. if (!pdev->dev.platform_data) {
  528. dev_err(&pdev->dev, "No platform data for VENC sub device");
  529. return -EINVAL;
  530. }
  531. pdev_id = platform_get_device_id(pdev);
  532. if (!pdev_id)
  533. return -EINVAL;
  534. venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL);
  535. if (venc == NULL)
  536. return -ENOMEM;
  537. venc->venc_type = pdev_id->driver_data;
  538. venc->pdev = &pdev->dev;
  539. venc->pdata = pdev->dev.platform_data;
  540. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  541. venc->venc_base = devm_ioremap_resource(&pdev->dev, res);
  542. if (IS_ERR(venc->venc_base))
  543. return PTR_ERR(venc->venc_base);
  544. if (venc->venc_type != VPBE_VERSION_1) {
  545. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  546. venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res);
  547. if (IS_ERR(venc->vdaccfg_reg))
  548. return PTR_ERR(venc->vdaccfg_reg);
  549. }
  550. spin_lock_init(&venc->lock);
  551. platform_set_drvdata(pdev, venc);
  552. dev_notice(venc->pdev, "VENC sub device probe success\n");
  553. return 0;
  554. }
  555. static int venc_remove(struct platform_device *pdev)
  556. {
  557. return 0;
  558. }
  559. static struct platform_driver venc_driver = {
  560. .probe = venc_probe,
  561. .remove = venc_remove,
  562. .driver = {
  563. .name = MODULE_NAME,
  564. },
  565. .id_table = vpbe_venc_devtype
  566. };
  567. module_platform_driver(venc_driver);
  568. MODULE_LICENSE("GPL");
  569. MODULE_DESCRIPTION("VPBE VENC Driver");
  570. MODULE_AUTHOR("Texas Instruments");