tuner.c
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:7k
源码类别:

DVD

开发平台:

Unix_Linux

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/sched.h>
  4. #include <linux/string.h>
  5. #include <linux/timer.h>
  6. #include <linux/delay.h>
  7. #include <linux/errno.h>
  8. #include <linux/malloc.h>
  9. #include <linux/version.h>
  10. #include <linux/i2c.h>
  11. #include <linux/videodev.h>
  12. #include "tuner.h"
  13. static int debug =  0; /* insmod parameter */
  14. static int type  = -1; /* tuner type */
  15. #define dprintk     if (debug) printk
  16. #if LINUX_VERSION_CODE > 0x020100
  17. MODULE_PARM(debug,"i");
  18. MODULE_PARM(type,"i");
  19. #endif
  20. #if LINUX_VERSION_CODE < 0x02017f
  21. void schedule_timeout(int j)
  22. {
  23. current->state   = TASK_INTERRUPTIBLE;
  24. current->timeout = jiffies + j;
  25. schedule();
  26. }
  27. #endif
  28. struct tuner 
  29. {
  30. struct i2c_bus   *bus;     /* where is our chip */
  31. int               addr;
  32. int type;            /* chip type */
  33. int freq;            /* keep track of the current settings */
  34. int radio;
  35. };
  36. /* ---------------------------------------------------------------------- */
  37. struct tunertype 
  38. {
  39. char *name;
  40. unsigned char Vendor;
  41. unsigned char Type;
  42.   
  43. unsigned short thresh1; /* frequency Range for UHF,VHF-L, VHF_H */   
  44. unsigned short thresh2;  
  45. unsigned char VHF_L;
  46. unsigned char VHF_H;
  47. unsigned char UHF;
  48. unsigned char config; 
  49. unsigned char I2C;
  50. unsigned short IFPCoff;
  51. };
  52. /*
  53.  * The floats in the tuner struct are computed at compile time
  54.  * by gcc and cast back to integers. Thus we don't violate the
  55.  * "no float in kernel" rule.
  56.  */
  57. static struct tunertype tuners[] = {
  58.         {"Temic PAL", TEMIC, PAL,
  59.                 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,623},
  60. {"Philips PAL_I", Philips, PAL_I,
  61.         16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc0,623},
  62. {"Philips NTSC", Philips, NTSC,
  63.         16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,0xc0,732},
  64. {"Philips SECAM", Philips, SECAM,
  65.         16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,0xc0,623},
  66. {"NoTuner", NoTuner, NOTUNER,
  67.          0        ,0        ,0x00,0x00,0x00,0x00,0x00,000},
  68. {"Philips PAL", Philips, PAL,
  69.         16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,0xc0,623},
  70. {"Temic NTSC", TEMIC, NTSC,
  71.         16*157.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,732},
  72. {"TEMIC PAL_I", TEMIC, PAL_I,
  73.       //  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
  74.         16*170.00,16*450.00,0x02,0x04,0x01,0x8e,0xc2,623},
  75. {"Temic 4036 FY5 NTSC", TEMIC, NTSC,
  76.         16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
  77.         {"Alps HSBH1", TEMIC, NTSC,
  78.                 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,0xc2,732},
  79. };
  80. /* ---------------------------------------------------------------------- */
  81. static int tuner_getstatus (struct tuner *t)
  82. {
  83. return i2c_read(t->bus,t->addr+1);
  84. }
  85. #define TUNER_POR       0x80
  86. #define TUNER_FL        0x40
  87. #define TUNER_AFC       0x07
  88. static int tuner_islocked (struct tuner *t)
  89. {
  90.         return (tuner_getstatus (t) & TUNER_FL);
  91. }
  92. static int tuner_afcstatus (struct tuner *t)
  93. {
  94.         return (tuner_getstatus (t) & TUNER_AFC) - 2;
  95. }
  96. static void set_tv_freq(struct tuner *t, int freq)
  97. {
  98. u8 config;
  99. u16 div;
  100. struct tunertype *tun;
  101. LOCK_FLAGS;
  102. if (t->type == -1) {
  103. printk("tuner: tuner type not setn");
  104. return;
  105. }
  106. tun=&tuners[t->type];
  107. if (freq < tun->thresh1) 
  108. config = tun->VHF_L;
  109. else if (freq < tun->thresh2) 
  110. config = tun->VHF_H;
  111. else
  112. config = tun->UHF;
  113. div=freq + tun->IFPCoff;
  114.    div&=0x7fff;
  115. LOCK_I2C_BUS(t->bus);
  116. if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) {
  117.     printk("tuner: i2c i/o error #1n");
  118. } else {
  119.     if (i2c_write(t->bus, t->addr, tun->config, config, 1))
  120. printk("tuner: i2c i/o error #2n");
  121. }
  122. UNLOCK_I2C_BUS(t->bus);
  123. }
  124. static void set_radio_freq(struct tuner *t, int freq)
  125. {
  126. u8 config;
  127. u16 div;
  128. struct tunertype *tun;
  129.         LOCK_FLAGS;
  130. if (t->type == -1) {
  131. printk("tuner: tuner type not setn");
  132. return;
  133. }
  134. tun=&tuners[t->type];
  135. config = 0xa5;
  136. div=freq + (int)(16*10.7);
  137.    div&=0x7fff;
  138. LOCK_I2C_BUS(t->bus);
  139. if (i2c_write(t->bus, t->addr, (div>>8)&0x7f, div&0xff, 1)<0) {
  140.     printk("tuner: i2c i/o error #1n");
  141. } else {
  142.     if (i2c_write(t->bus, t->addr, tun->config, config, 1))
  143. printk("tuner: i2c i/o error #2n");
  144. }
  145. if (debug) {
  146. UNLOCK_I2C_BUS(t->bus);
  147. current->state   = TASK_INTERRUPTIBLE;
  148. schedule_timeout(HZ/10);
  149. LOCK_I2C_BUS(t->bus);
  150. if (tuner_islocked (t))
  151. printk ("tuner: PLL lockedn");
  152. else
  153. printk ("tuner: PLL not lockedn");
  154. printk ("tuner: AFC: %dn", tuner_afcstatus (t));
  155. }
  156. UNLOCK_I2C_BUS(t->bus);
  157. }
  158. /* ---------------------------------------------------------------------- */
  159. static int tuner_attach(struct i2c_device *device)
  160. {
  161. struct tuner *t;
  162. /*
  163.  * For now we only try and attach these tuners to the BT848
  164.  * bus. This same module will however work different species
  165.  * of card using these chips. Just change the constraints
  166.  * (i2c doesn't have a totally clash free 'address' space)
  167.  */
  168.  
  169. // if(device->bus->id!=I2C_BUSID_BT848)
  170. // return -EINVAL;
  171. device->data = t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
  172. if (NULL == t)
  173. return -ENOMEM;
  174. memset(t,0,sizeof(struct tuner));
  175. strcpy(device->name,"tuner");
  176. t->bus  = device->bus;
  177. t->addr = device->addr;
  178. t->type = type;
  179. dprintk("tuner: type is %d (%s)n",t->type,
  180. (t->type == -1 ) ? "autodetect" : tuners[t->type].name);
  181. MOD_INC_USE_COUNT;
  182. return 0;
  183. }
  184. static int tuner_detach(struct i2c_device *device)
  185. {
  186. struct tuner *t = (struct tuner*)device->data;
  187. kfree(t);
  188. MOD_DEC_USE_COUNT;
  189. return 0;
  190. }
  191. static int tuner_command(struct i2c_device *device,
  192.       unsigned int cmd, void *arg)
  193. {
  194. struct tuner *t = (struct tuner*)device->data;
  195. int *iarg = (int*)arg;
  196. switch (cmd) 
  197. {
  198. case TUNER_SET_TYPE:
  199. if (t->type != -1)
  200. return 0;
  201. t->type = *iarg;
  202. dprintk("tuner: type set to %d (%s)n",
  203. t->type,tuners[t->type].name);
  204. break;
  205. case TUNER_SET_TVFREQ:
  206. dprintk("tuner: tv freq set to %d.%02dn",
  207. (*iarg)/16,(*iarg)%16*100/16);
  208. set_tv_freq(t,*iarg);
  209. t->radio = 0;
  210. t->freq = *iarg;
  211. break;
  212.     
  213. case TUNER_SET_RADIOFREQ:
  214. dprintk("tuner: radio freq set to %d.%02dn",
  215. (*iarg)/16,(*iarg)%16*100/16);
  216. set_radio_freq(t,*iarg);
  217. t->radio = 1;
  218. t->freq = *iarg;
  219. break;
  220.                 case TUNER_GET_ADDRESS:
  221.                         *iarg = t->addr;
  222.                         break;
  223.     
  224. default:
  225. return -EINVAL;
  226. }
  227. return 0;
  228. }
  229. /* ----------------------------------------------------------------------- */
  230. struct i2c_driver i2c_driver_tuner = 
  231. {
  232. "tuner",                      /* name       */
  233. I2C_DRIVERID_TUNER,           /* ID         */
  234. 0xc0, 0xce,                   /* addr range */
  235. tuner_attach,
  236. tuner_detach,
  237. tuner_command
  238. };
  239. EXPORT_NO_SYMBOLS;
  240. #ifdef MODULE
  241. int init_module(void)
  242. #else
  243. int i2c_tuner_init(void)
  244. #endif
  245. {
  246. i2c_register_driver(&i2c_driver_tuner);
  247. return 0;
  248. }
  249. #ifdef MODULE
  250. void cleanup_module(void)
  251. {
  252. i2c_unregister_driver(&i2c_driver_tuner);
  253. }
  254. #endif
  255. /*
  256.  * Overrides for Emacs so that we follow Linus's tabbing style.
  257.  * ---------------------------------------------------------------------------
  258.  * Local variables:
  259.  * c-basic-offset: 8
  260.  * End:
  261.  */