zr36016.c 14 KB

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