zr36016.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. * Zoran ZR36016 basic configuration functions
  3. *
  4. * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
  5. *
  6. * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $
  7. *
  8. * ------------------------------------------------------------------------
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. *
  24. * ------------------------------------------------------------------------
  25. */
  26. #define ZR016_VERSION "v0.7"
  27. #include <linux/module.h>
  28. #include <linux/init.h>
  29. #include <linux/slab.h>
  30. #include <linux/delay.h>
  31. #include <linux/types.h>
  32. #include <linux/wait.h>
  33. /* I/O commands, error codes */
  34. #include <asm/io.h>
  35. /* v4l API */
  36. /* headerfile of this module */
  37. #include"zr36016.h"
  38. /* codec io API */
  39. #include"videocodec.h"
  40. /* it doesn't make sense to have more than 20 or so,
  41. just to prevent some unwanted loops */
  42. #define MAX_CODECS 20
  43. /* amount of chips attached via this driver */
  44. static int zr36016_codecs;
  45. /* debugging is available via module parameter */
  46. static int debug;
  47. module_param(debug, int, 0);
  48. MODULE_PARM_DESC(debug, "Debug level (0-4)");
  49. #define dprintk(num, format, args...) \
  50. do { \
  51. if (debug >= num) \
  52. printk(format, ##args); \
  53. } while (0)
  54. /* =========================================================================
  55. Local hardware I/O functions:
  56. read/write via codec layer (registers are located in the master device)
  57. ========================================================================= */
  58. /* read and write functions */
  59. static u8
  60. zr36016_read (struct zr36016 *ptr,
  61. u16 reg)
  62. {
  63. u8 value = 0;
  64. // just in case something is wrong...
  65. if (ptr->codec->master_data->readreg)
  66. value =
  67. (ptr->codec->master_data->
  68. readreg(ptr->codec, reg)) & 0xFF;
  69. else
  70. dprintk(1,
  71. KERN_ERR "%s: invalid I/O setup, nothing read!\n",
  72. ptr->name);
  73. dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
  74. value);
  75. return value;
  76. }
  77. static void
  78. zr36016_write (struct zr36016 *ptr,
  79. u16 reg,
  80. u8 value)
  81. {
  82. dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
  83. reg);
  84. // just in case something is wrong...
  85. if (ptr->codec->master_data->writereg) {
  86. ptr->codec->master_data->writereg(ptr->codec, reg, value);
  87. } else
  88. dprintk(1,
  89. KERN_ERR
  90. "%s: invalid I/O setup, nothing written!\n",
  91. ptr->name);
  92. }
  93. /* indirect read and write functions */
  94. /* the 016 supports auto-addr-increment, but
  95. * writing it all time cost not much and is safer... */
  96. static u8
  97. zr36016_readi (struct zr36016 *ptr,
  98. u16 reg)
  99. {
  100. u8 value = 0;
  101. // just in case something is wrong...
  102. if ((ptr->codec->master_data->writereg) &&
  103. (ptr->codec->master_data->readreg)) {
  104. ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
  105. value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF; // DATA
  106. } else
  107. dprintk(1,
  108. KERN_ERR
  109. "%s: invalid I/O setup, nothing read (i)!\n",
  110. ptr->name);
  111. dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
  112. reg, value);
  113. return value;
  114. }
  115. static void
  116. zr36016_writei (struct zr36016 *ptr,
  117. u16 reg,
  118. u8 value)
  119. {
  120. dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
  121. value, reg);
  122. // just in case something is wrong...
  123. if (ptr->codec->master_data->writereg) {
  124. ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
  125. ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF); // DATA
  126. } else
  127. dprintk(1,
  128. KERN_ERR
  129. "%s: invalid I/O setup, nothing written (i)!\n",
  130. ptr->name);
  131. }
  132. /* =========================================================================
  133. Local helper function:
  134. version read
  135. ========================================================================= */
  136. /* version kept in datastructure */
  137. static u8
  138. zr36016_read_version (struct zr36016 *ptr)
  139. {
  140. ptr->version = zr36016_read(ptr, 0) >> 4;
  141. return ptr->version;
  142. }
  143. /* =========================================================================
  144. Local helper function:
  145. basic test of "connectivity", writes/reads to/from PAX-Lo register
  146. ========================================================================= */
  147. static int
  148. zr36016_basic_test (struct zr36016 *ptr)
  149. {
  150. if (debug) {
  151. int i;
  152. zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
  153. dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
  154. for (i = 0; i <= 0x0b; i++)
  155. dprintk(1, "%02x ", zr36016_readi(ptr, i));
  156. dprintk(1, "\n");
  157. }
  158. // for testing just write 0, then the default value to a register and read
  159. // it back in both cases
  160. zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
  161. if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
  162. dprintk(1,
  163. KERN_ERR
  164. "%s: attach failed, can't connect to vfe processor!\n",
  165. ptr->name);
  166. return -ENXIO;
  167. }
  168. zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
  169. if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
  170. dprintk(1,
  171. KERN_ERR
  172. "%s: attach failed, can't connect to vfe processor!\n",
  173. ptr->name);
  174. return -ENXIO;
  175. }
  176. // we allow version numbers from 0-3, should be enough, though
  177. zr36016_read_version(ptr);
  178. if (ptr->version & 0x0c) {
  179. dprintk(1,
  180. KERN_ERR
  181. "%s: attach failed, suspicious version %d found...\n",
  182. ptr->name, ptr->version);
  183. return -ENXIO;
  184. }
  185. return 0; /* looks good! */
  186. }
  187. /* =========================================================================
  188. Local helper function:
  189. simple loop for pushing the init datasets - NO USE --
  190. ========================================================================= */
  191. #if 0
  192. static int zr36016_pushit (struct zr36016 *ptr,
  193. u16 startreg,
  194. u16 len,
  195. const char *data)
  196. {
  197. int i=0;
  198. dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
  199. ptr->name, startreg,len);
  200. while (i<len) {
  201. zr36016_writei(ptr, startreg++, data[i++]);
  202. }
  203. return i;
  204. }
  205. #endif
  206. /* =========================================================================
  207. Basic datasets & init:
  208. //TODO//
  209. ========================================================================= */
  210. // needed offset values PAL NTSC SECAM
  211. static const int zr016_xoff[] = { 20, 20, 20 };
  212. static const int zr016_yoff[] = { 8, 9, 7 };
  213. static void
  214. zr36016_init (struct zr36016 *ptr)
  215. {
  216. // stop any processing
  217. zr36016_write(ptr, ZR016_GOSTOP, 0);
  218. // mode setup (yuv422 in and out, compression/expansuon due to mode)
  219. zr36016_write(ptr, ZR016_MODE,
  220. ZR016_YUV422 | ZR016_YUV422_YUV422 |
  221. (ptr->mode == CODEC_DO_COMPRESSION ?
  222. ZR016_COMPRESSION : ZR016_EXPANSION));
  223. // misc setup
  224. zr36016_writei(ptr, ZR016I_SETUP1,
  225. (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
  226. (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
  227. zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
  228. // Window setup
  229. // (no extra offset for now, norm defines offset, default width height)
  230. zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
  231. zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
  232. zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
  233. zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
  234. zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
  235. zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
  236. zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
  237. zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
  238. /* shall we continue now, please? */
  239. zr36016_write(ptr, ZR016_GOSTOP, 1);
  240. }
  241. /* =========================================================================
  242. CODEC API FUNCTIONS
  243. this functions are accessed by the master via the API structure
  244. ========================================================================= */
  245. /* set compression/expansion mode and launches codec -
  246. this should be the last call from the master before starting processing */
  247. static int
  248. zr36016_set_mode (struct videocodec *codec,
  249. int mode)
  250. {
  251. struct zr36016 *ptr = (struct zr36016 *) codec->data;
  252. dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
  253. if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
  254. return -EINVAL;
  255. ptr->mode = mode;
  256. zr36016_init(ptr);
  257. return 0;
  258. }
  259. /* set picture size */
  260. static int
  261. zr36016_set_video (struct videocodec *codec,
  262. struct tvnorm *norm,
  263. struct vfe_settings *cap,
  264. struct vfe_polarity *pol)
  265. {
  266. struct zr36016 *ptr = (struct zr36016 *) codec->data;
  267. dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
  268. ptr->name, norm->HStart, norm->VStart,
  269. cap->x, cap->y, cap->width, cap->height,
  270. cap->decimation);
  271. /* if () return -EINVAL;
  272. * trust the master driver that it knows what it does - so
  273. * we allow invalid startx/y for now ... */
  274. ptr->width = cap->width;
  275. ptr->height = cap->height;
  276. /* (Ronald) This is ugly. zoran_device.c, line 387
  277. * already mentions what happens if HStart is even
  278. * (blue faces, etc., cr/cb inversed). There's probably
  279. * some good reason why HStart is 0 instead of 1, so I'm
  280. * leaving it to this for now, but really... This can be
  281. * done a lot simpler */
  282. ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
  283. /* Something to note here (I don't understand it), setting
  284. * VStart too high will cause the codec to 'not work'. I
  285. * really don't get it. values of 16 (VStart) already break
  286. * it here. Just '0' seems to work. More testing needed! */
  287. ptr->yoff = norm->VStart + cap->y;
  288. /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
  289. ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
  290. ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
  291. return 0;
  292. }
  293. /* additional control functions */
  294. static int
  295. zr36016_control (struct videocodec *codec,
  296. int type,
  297. int size,
  298. void *data)
  299. {
  300. struct zr36016 *ptr = (struct zr36016 *) codec->data;
  301. int *ival = (int *) data;
  302. dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
  303. size);
  304. switch (type) {
  305. case CODEC_G_STATUS: /* get last status - we don't know it ... */
  306. if (size != sizeof(int))
  307. return -EFAULT;
  308. *ival = 0;
  309. break;
  310. case CODEC_G_CODEC_MODE:
  311. if (size != sizeof(int))
  312. return -EFAULT;
  313. *ival = 0;
  314. break;
  315. case CODEC_S_CODEC_MODE:
  316. if (size != sizeof(int))
  317. return -EFAULT;
  318. if (*ival != 0)
  319. return -EINVAL;
  320. /* not needed, do nothing */
  321. return 0;
  322. case CODEC_G_VFE:
  323. case CODEC_S_VFE:
  324. return 0;
  325. case CODEC_S_MMAP:
  326. /* not available, give an error */
  327. return -ENXIO;
  328. default:
  329. return -EINVAL;
  330. }
  331. return size;
  332. }
  333. /* =========================================================================
  334. Exit and unregister function:
  335. Deinitializes Zoran's JPEG processor
  336. ========================================================================= */
  337. static int
  338. zr36016_unset (struct videocodec *codec)
  339. {
  340. struct zr36016 *ptr = codec->data;
  341. if (ptr) {
  342. /* do wee need some codec deinit here, too ???? */
  343. dprintk(1, "%s: finished codec #%d\n", ptr->name,
  344. ptr->num);
  345. kfree(ptr);
  346. codec->data = NULL;
  347. zr36016_codecs--;
  348. return 0;
  349. }
  350. return -EFAULT;
  351. }
  352. /* =========================================================================
  353. Setup and registry function:
  354. Initializes Zoran's JPEG processor
  355. Also sets pixel size, average code size, mode (compr./decompr.)
  356. (the given size is determined by the processor with the video interface)
  357. ========================================================================= */
  358. static int
  359. zr36016_setup (struct videocodec *codec)
  360. {
  361. struct zr36016 *ptr;
  362. int res;
  363. dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
  364. zr36016_codecs);
  365. if (zr36016_codecs == MAX_CODECS) {
  366. dprintk(1,
  367. KERN_ERR "zr36016: Can't attach more codecs!\n");
  368. return -ENOSPC;
  369. }
  370. //mem structure init
  371. codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
  372. if (NULL == ptr) {
  373. dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
  374. return -ENOMEM;
  375. }
  376. snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
  377. zr36016_codecs);
  378. ptr->num = zr36016_codecs++;
  379. ptr->codec = codec;
  380. //testing
  381. res = zr36016_basic_test(ptr);
  382. if (res < 0) {
  383. zr36016_unset(codec);
  384. return res;
  385. }
  386. //final setup
  387. ptr->mode = CODEC_DO_COMPRESSION;
  388. ptr->width = 768;
  389. ptr->height = 288;
  390. ptr->xdec = 1;
  391. ptr->ydec = 0;
  392. zr36016_init(ptr);
  393. dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
  394. ptr->name, ptr->version);
  395. return 0;
  396. }
  397. static const struct videocodec zr36016_codec = {
  398. .owner = THIS_MODULE,
  399. .name = "zr36016",
  400. .magic = 0L, // magic not used
  401. .flags =
  402. CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
  403. CODEC_FLAG_DECODER,
  404. .type = CODEC_TYPE_ZR36016,
  405. .setup = zr36016_setup, // functionality
  406. .unset = zr36016_unset,
  407. .set_mode = zr36016_set_mode,
  408. .set_video = zr36016_set_video,
  409. .control = zr36016_control,
  410. // others are not used
  411. };
  412. /* =========================================================================
  413. HOOK IN DRIVER AS KERNEL MODULE
  414. ========================================================================= */
  415. static int __init
  416. zr36016_init_module (void)
  417. {
  418. //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
  419. zr36016_codecs = 0;
  420. return videocodec_register(&zr36016_codec);
  421. }
  422. static void __exit
  423. zr36016_cleanup_module (void)
  424. {
  425. if (zr36016_codecs) {
  426. dprintk(1,
  427. "zr36016: something's wrong - %d codecs left somehow.\n",
  428. zr36016_codecs);
  429. }
  430. videocodec_unregister(&zr36016_codec);
  431. }
  432. module_init(zr36016_init_module);
  433. module_exit(zr36016_cleanup_module);
  434. MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
  435. MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
  436. ZR016_VERSION);
  437. MODULE_LICENSE("GPL");