zr36016.c 14 KB

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