saa7111.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.     saa7111 - Philips SAA7111A video decoder driver version 0.0.3
  3.     Copyright (C) 1998 Dave Perks <dperks@ibm.net>
  4.     Slight changes for video timing and attachment output by
  5.     Wolfgang Scherr <scherr@net4you.net>
  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 as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <linux/module.h>
  20. #include <linux/init.h>
  21. #include <linux/delay.h>
  22. #include <linux/errno.h>
  23. #include <linux/fs.h>
  24. #include <linux/kernel.h>
  25. #include <linux/major.h>
  26. #include <linux/slab.h>
  27. #include <linux/mm.h>
  28. #include <linux/sched.h>
  29. #include <linux/videodev.h>
  30. #include <linux/version.h>
  31. #include <linux/i2c-old.h>
  32. #include <linux/video_decoder.h>
  33. #define DEBUG(x) /* Debug driver */
  34. /* ----------------------------------------------------------------------- */
  35. struct saa7111 {
  36. struct i2c_bus *bus;
  37. int addr;
  38. unsigned char reg[32];
  39. int norm;
  40. int input;
  41. int enable;
  42. int bright;
  43. int contrast;
  44. int hue;
  45. int sat;
  46. };
  47. #define   I2C_SAA7111        0x48
  48. #define   I2C_DELAY   10
  49. /* ----------------------------------------------------------------------- */
  50. static int saa7111_write(struct saa7111 *dev, unsigned char subaddr,
  51.  unsigned char data)
  52. {
  53. int ack;
  54. LOCK_I2C_BUS(dev->bus);
  55. i2c_start(dev->bus);
  56. i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
  57. i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
  58. ack = i2c_sendbyte(dev->bus, data, I2C_DELAY);
  59. dev->reg[subaddr] = data;
  60. i2c_stop(dev->bus);
  61. UNLOCK_I2C_BUS(dev->bus);
  62. return ack;
  63. }
  64. static int saa7111_write_block(struct saa7111 *dev,
  65.        unsigned const char *data, unsigned int len)
  66. {
  67. int ack = -1;
  68. unsigned subaddr;
  69. while (len > 1) {
  70. LOCK_I2C_BUS(dev->bus);
  71. i2c_start(dev->bus);
  72. i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
  73. ack = i2c_sendbyte(dev->bus, (subaddr = *data++), I2C_DELAY);
  74. ack = i2c_sendbyte(dev->bus, (dev->reg[subaddr] = *data++), I2C_DELAY);
  75. len -= 2;
  76. while (len > 1 && *data == ++subaddr) {
  77. data++;
  78. ack =
  79.     i2c_sendbyte(dev->bus,
  80.  (dev->reg[subaddr] =
  81.   *data++), I2C_DELAY);
  82. len -= 2;
  83. }
  84. i2c_stop(dev->bus);
  85. UNLOCK_I2C_BUS(dev->bus);
  86. }
  87. return ack;
  88. }
  89. static int saa7111_read(struct saa7111 *dev, unsigned char subaddr)
  90. {
  91. int data;
  92. LOCK_I2C_BUS(dev->bus);
  93. i2c_start(dev->bus);
  94. i2c_sendbyte(dev->bus, dev->addr, I2C_DELAY);
  95. i2c_sendbyte(dev->bus, subaddr, I2C_DELAY);
  96. i2c_start(dev->bus);
  97. i2c_sendbyte(dev->bus, dev->addr | 1, I2C_DELAY);
  98. data = i2c_readbyte(dev->bus, 1);
  99. i2c_stop(dev->bus);
  100. UNLOCK_I2C_BUS(dev->bus);
  101. return data;
  102. }
  103. /* ----------------------------------------------------------------------- */
  104. static int saa7111_attach(struct i2c_device *device)
  105. {
  106. int i;
  107. struct saa7111 *decoder;
  108. static const unsigned char init[] = {
  109. 0x00, 0x00, /* 00 - ID byte */
  110. 0x01, 0x00, /* 01 - reserved */
  111. /*front end */
  112. 0x02, 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */
  113. 0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
  114. 0x04, 0x00, /* 04 - GAI1=256 */
  115. 0x05, 0x00, /* 05 - GAI2=256 */
  116. /* decoder */
  117. 0x06, 0xf3, /* 06 - HSB at  13(50Hz) /  17(60Hz) pixels after end of last line */
  118. 0x07, 0x13, /* 07 - HSS at 113(50Hz) / 117(60Hz) pixels after end of last line */
  119. 0x08, 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1, HPLL=0, VNOI=0 */
  120. 0x09, 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0, UPTCV=0, APER=1 */
  121. 0x0a, 0x80, /* 0a - BRIG=128 */
  122. 0x0b, 0x47, /* 0b - CONT=1.109 */
  123. 0x0c, 0x40, /* 0c - SATN=1.0 */
  124. 0x0d, 0x00, /* 0d - HUE=0 */
  125. 0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0, FCTC=0, CHBW=1 */
  126. 0x0f, 0x00, /* 0f - reserved */
  127. 0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
  128. 0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1, OEYC=1, OEHV=1, VIPB=0, COLO=0 */
  129. 0x12, 0x00, /* 12 - output control 2 */
  130. 0x13, 0x00, /* 13 - output control 3 */
  131. 0x14, 0x00, /* 14 - reserved */
  132. 0x15, 0x00, /* 15 - VBI */
  133. 0x16, 0x00, /* 16 - VBI */
  134. 0x17, 0x00, /* 17 - VBI */
  135. };
  136. MOD_INC_USE_COUNT;
  137. device->data = decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
  138. if (decoder == NULL)
  139. {
  140. MOD_DEC_USE_COUNT;
  141. return -ENOMEM;
  142. }
  143. memset(decoder, 0, sizeof(struct saa7111));
  144. strcpy(device->name, "saa7111");
  145. decoder->bus = device->bus;
  146. decoder->addr = device->addr;
  147. decoder->norm = VIDEO_MODE_NTSC;
  148. decoder->input = 0;
  149. decoder->enable = 1;
  150. decoder->bright = 32768;
  151. decoder->contrast = 32768;
  152. decoder->hue = 32768;
  153. decoder->sat = 32768;
  154. i = saa7111_write_block(decoder, init, sizeof(init));
  155. if (i < 0) {
  156. printk(KERN_ERR "%s_attach: init status %dn",
  157.        device->name, i);
  158. } else {
  159. printk(KERN_INFO "%s_attach: chip version %xn",
  160.        device->name, saa7111_read(decoder, 0x00) >> 4);
  161. }
  162. return 0;
  163. }
  164. static int saa7111_detach(struct i2c_device *device)
  165. {
  166. kfree(device->data);
  167. MOD_DEC_USE_COUNT;
  168. return 0;
  169. }
  170. static int saa7111_command(struct i2c_device *device, unsigned int cmd,
  171.    void *arg)
  172. {
  173. struct saa7111 *decoder = device->data;
  174. switch (cmd) {
  175. #if defined(DECODER_DUMP)
  176. case DECODER_DUMP:
  177. {
  178. int i;
  179. for (i = 0; i < 32; i += 16) {
  180. int j;
  181. printk("KERN_DEBUG %s: %03x", device->name,
  182.        i);
  183. for (j = 0; j < 16; ++j) {
  184. printk(" %02x",
  185.        saa7111_read(decoder,
  186.     i + j));
  187. }
  188. printk("n");
  189. }
  190. }
  191. break;
  192. #endif /* defined(DECODER_DUMP) */
  193. case DECODER_GET_CAPABILITIES:
  194. {
  195. struct video_decoder_capability *cap = arg;
  196. cap->flags
  197.     = VIDEO_DECODER_PAL
  198.     | VIDEO_DECODER_NTSC
  199.     | VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR;
  200. cap->inputs = 8;
  201. cap->outputs = 1;
  202. }
  203. break;
  204. case DECODER_GET_STATUS:
  205. {
  206. int *iarg = arg;
  207. int status;
  208. int res;
  209. status = saa7111_read(decoder, 0x1f);
  210. res = 0;
  211. if ((status & (1 << 6)) == 0) {
  212. res |= DECODER_STATUS_GOOD;
  213. }
  214. switch (decoder->norm) {
  215. case VIDEO_MODE_NTSC:
  216. res |= DECODER_STATUS_NTSC;
  217. break;
  218. case VIDEO_MODE_PAL:
  219. res |= DECODER_STATUS_PAL;
  220. break;
  221. default:
  222. case VIDEO_MODE_AUTO:
  223. if ((status & (1 << 5)) != 0) {
  224. res |= DECODER_STATUS_NTSC;
  225. } else {
  226. res |= DECODER_STATUS_PAL;
  227. }
  228. break;
  229. }
  230. if ((status & (1 << 0)) != 0) {
  231. res |= DECODER_STATUS_COLOR;
  232. }
  233. *iarg = res;
  234. }
  235. break;
  236. case DECODER_SET_NORM:
  237. {
  238. int *iarg = arg;
  239. switch (*iarg) {
  240. case VIDEO_MODE_NTSC:
  241. saa7111_write(decoder, 0x08,
  242.       (decoder->
  243.        reg[0x08] & 0x3f) | 0x40);
  244. break;
  245. case VIDEO_MODE_PAL:
  246. saa7111_write(decoder, 0x08,
  247.       (decoder->
  248.        reg[0x08] & 0x3f) | 0x00);
  249. break;
  250. case VIDEO_MODE_AUTO:
  251. saa7111_write(decoder, 0x08,
  252.       (decoder->
  253.        reg[0x08] & 0x3f) | 0x80);
  254. break;
  255. default:
  256. return -EINVAL;
  257. }
  258. decoder->norm = *iarg;
  259. }
  260. break;
  261. case DECODER_SET_INPUT:
  262. {
  263. int *iarg = arg;
  264. if (*iarg < 0 || *iarg > 7) {
  265. return -EINVAL;
  266. }
  267. if (decoder->input != *iarg) {
  268. decoder->input = *iarg;
  269. /* select mode */
  270. saa7111_write(decoder, 0x02,
  271.       (decoder->
  272.        reg[0x02] & 0xf8) |
  273.       decoder->input);
  274. /* bypass chrominance trap for modes 4..7 */
  275. saa7111_write(decoder, 0x09,
  276.       (decoder->
  277.        reg[0x09] & 0x7f) |
  278.       ((decoder->input >
  279. 3) ? 0x80 : 0));
  280. }
  281. }
  282. break;
  283. case DECODER_SET_OUTPUT:
  284. {
  285. int *iarg = arg;
  286. /* not much choice of outputs */
  287. if (*iarg != 0) {
  288. return -EINVAL;
  289. }
  290. }
  291. break;
  292. case DECODER_ENABLE_OUTPUT:
  293. {
  294. int *iarg = arg;
  295. int enable = (*iarg != 0);
  296. if (decoder->enable != enable) {
  297. decoder->enable = enable;
  298. // RJ: If output should be disabled (for playing videos), we also need a open PLL.
  299. //     The input is set to 0 (where no input source is connected), although this
  300. //     is not necessary.
  301. //
  302. //     If output should be enabled, we have to reverse the above.
  303. if (decoder->enable) {
  304. saa7111_write(decoder, 0x02,
  305.       (decoder->
  306.        reg[0x02] & 0xf8) |
  307.       decoder->input);
  308. saa7111_write(decoder, 0x08,
  309.       (decoder->
  310.        reg[0x08] & 0xfb));
  311. saa7111_write(decoder, 0x11,
  312.       (decoder->
  313.        reg[0x11] & 0xf3) |
  314.       0x0c);
  315. } else {
  316. saa7111_write(decoder, 0x02,
  317.       (decoder->
  318.        reg[0x02] & 0xf8));
  319. saa7111_write(decoder, 0x08,
  320.       (decoder->
  321.        reg[0x08] & 0xfb) |
  322.       0x04);
  323. saa7111_write(decoder, 0x11,
  324.       (decoder->
  325.        reg[0x11] & 0xf3));
  326. }
  327. }
  328. }
  329. break;
  330. case DECODER_SET_PICTURE:
  331. {
  332. struct video_picture *pic = arg;
  333. if (decoder->bright != pic->brightness) {
  334. /* We want 0 to 255 we get 0-65535 */
  335. decoder->bright = pic->brightness;
  336. saa7111_write(decoder, 0x0a,
  337.       decoder->bright >> 8);
  338. }
  339. if (decoder->contrast != pic->contrast) {
  340. /* We want 0 to 127 we get 0-65535 */
  341. decoder->contrast = pic->contrast;
  342. saa7111_write(decoder, 0x0b,
  343.       decoder->contrast >> 9);
  344. }
  345. if (decoder->sat != pic->colour) {
  346. /* We want 0 to 127 we get 0-65535 */
  347. decoder->sat = pic->colour;
  348. saa7111_write(decoder, 0x0c,
  349.       decoder->sat >> 9);
  350. }
  351. if (decoder->hue != pic->hue) {
  352. /* We want -128 to 127 we get 0-65535 */
  353. decoder->hue = pic->hue;
  354. saa7111_write(decoder, 0x0d,
  355.       (decoder->hue - 32768) >> 8);
  356. }
  357. }
  358. break;
  359. default:
  360. return -EINVAL;
  361. }
  362. return 0;
  363. }
  364. /* ----------------------------------------------------------------------- */
  365. static struct i2c_driver i2c_driver_saa7111 = {
  366. "saa7111", /* name */
  367. I2C_DRIVERID_VIDEODECODER, /* ID */
  368. I2C_SAA7111, I2C_SAA7111 + 1,
  369. saa7111_attach,
  370. saa7111_detach,
  371. saa7111_command
  372. };
  373. EXPORT_NO_SYMBOLS;
  374. static int saa7111_init(void)
  375. {
  376. return i2c_register_driver(&i2c_driver_saa7111);
  377. }
  378. static void saa7111_exit(void)
  379. {
  380. i2c_unregister_driver(&i2c_driver_saa7111);
  381. }
  382. module_init(saa7111_init);
  383. module_exit(saa7111_exit);
  384. MODULE_LICENSE("GPL");