fq1216me.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*
  2. * TVIN Tuner Bridge Driver
  3. *
  4. * Author: Bobby Yang <bo.yang@amlogic.com>
  5. *
  6. *
  7. * Copyright (C) 2010 Amlogic Inc.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. /* Standard Linux Headers */
  14. #include <linux/types.h>
  15. #include <linux/errno.h>
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/slab.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/fs.h>
  22. #include <linux/device.h>
  23. #include <linux/cdev.h>
  24. #include <linux/i2c.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/interrupt.h>
  27. #include <asm/uaccess.h>
  28. #include <linux/sysctl.h>
  29. /* Amlogic Headers */
  30. #include <media/amlogic/656in.h>
  31. /* Driver Headers */
  32. #include "fq1216me.h"
  33. #include "fq1216me_tuner.h"
  34. #include "fq1216me_demod.h"
  35. #define TUNER_DEVICE_NAME "tuner_fq1216me"
  36. typedef struct fq1216me_device_s {
  37. struct class *clsp;
  38. dev_t devno;
  39. struct cdev cdev;
  40. // struct i2c_adapter *adap;
  41. // struct i2c_client *tuner;
  42. // struct i2c_client *demod;
  43. /* reserved for futuer abstract */
  44. struct tvin_tuner_ops_s *tops;
  45. }fq1216me_device_t;
  46. static struct fq1216me_device_s *devp;
  47. static int fq1216me_open(struct inode *inode, struct file *file)
  48. {
  49. struct fq1216me_device_s *devp_o;
  50. // pr_info( "%s . \n", __FUNCTION__ );
  51. /* Get the per-device structure that contains this cdev */
  52. devp_o = container_of(inode->i_cdev, fq1216me_device_t, cdev);
  53. file->private_data = devp_o;
  54. return 0;
  55. }
  56. static int fq1216me_release(struct inode *inode, struct file *file)
  57. {
  58. file->private_data = NULL;
  59. // pr_info( "%s . \n", __FUNCTION__ );
  60. return 0;
  61. }
  62. static int fq1216me_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  63. {
  64. int ret = 0;
  65. struct fq1216me_device_s *devp_c;
  66. void __user *argp = (void __user *)arg;
  67. if (_IOC_TYPE(cmd) != TVIN_IOC_MAGIC) {
  68. return -EINVAL;
  69. }
  70. devp_c = container_of(inode->i_cdev, fq1216me_device_t, cdev);
  71. // pr_info("%s: \n",__FUNCTION__);
  72. switch (cmd)
  73. {
  74. case TVIN_IOC_G_TUNER_STD:
  75. {
  76. tuner_std_id std_id = 0;
  77. fq1216me_get_std(&std_id);
  78. if (copy_to_user((void __user *)arg, &std_id, sizeof(tuner_std_id)))
  79. {
  80. pr_err("%s: TVIN_IOC_G_TUNER_STD para is error. \n " ,__FUNCTION__);
  81. ret = -EFAULT;
  82. }
  83. // pr_info("TVIN_IOC_G_TUNER_STD: %lx, \n", std_id);
  84. }
  85. break;
  86. case TVIN_IOC_S_TUNER_STD:
  87. {
  88. tuner_std_id std_id = 0;
  89. if (copy_from_user(&std_id, argp, sizeof(tuner_std_id)))
  90. {
  91. pr_err("%s: TVIN_IOC_S_TUNER_STD para is error. \n ",__FUNCTION__);
  92. ret = -EFAULT;
  93. break;
  94. }
  95. fq1216me_set_tuner_std(std_id);
  96. fq1216me_set_demod_std(std_id);
  97. // fq1216me_set_tuner();
  98. fq1216me_set_demod();
  99. // pr_info("TVIN_IOC_S_TUNER_STD \n");
  100. }
  101. break;
  102. case TVIN_IOC_G_TUNER_FREQ:
  103. {
  104. struct tuner_freq_s tuner_freq = {0, 0};
  105. fq1216me_get_freq(&tuner_freq);
  106. if (copy_to_user((void __user *)arg, &tuner_freq, sizeof(struct tuner_freq_s)))
  107. {
  108. pr_err("%s: TVIN_IOC_G_TUNER_FREQ para is error. \n " ,__FUNCTION__);
  109. ret = -EFAULT;
  110. }
  111. // pr_info(" TVIN_IOC_G_TUNER_FREQ: %d, \n", tuner_freq.freq);
  112. }
  113. break;
  114. case TVIN_IOC_S_TUNER_FREQ:
  115. {
  116. struct tuner_freq_s tuner_freq = {0, 0};
  117. if (copy_from_user(&tuner_freq, argp, sizeof(struct tuner_freq_s)))
  118. {
  119. pr_err("%s: TVIN_IOC_S_TUNER_FREQ para is error. \n " ,__FUNCTION__);
  120. ret = -EFAULT;
  121. break;
  122. }
  123. fq1216me_set_freq(tuner_freq);
  124. fq1216me_set_tuner();
  125. // fq1216me_set_demod();
  126. // pr_info(" TVIN_IOC_S_TUNER_FREQ\n");
  127. }
  128. break;
  129. case TVIN_IOC_G_TUNER_PARM:
  130. {
  131. struct tuner_parm_s tuner_parm = {0, 0, 0, 0, 0};
  132. fq1216me_get_tuner(&tuner_parm);
  133. fq1216me_get_afc(&tuner_parm);
  134. if (copy_to_user((void __user *)arg, &tuner_parm, sizeof(struct tuner_parm_s)))
  135. {
  136. pr_err("%s: TVIN_IOC_G_TUNER_PARM para is error. \n " ,__FUNCTION__);
  137. ret = -EFAULT;
  138. }
  139. // pr_info(" TVIN_IOC_G_TUNER_PARM-- status: %d, \n", tuner_parm.if_status);
  140. }
  141. break;
  142. default:
  143. ret = -ENOIOCTLCMD;
  144. break;
  145. }
  146. return ret;
  147. }
  148. static struct file_operations fq1216me_fops = {
  149. .owner = THIS_MODULE,
  150. .open = fq1216me_open,
  151. .release = fq1216me_release,
  152. .ioctl = fq1216me_ioctl,
  153. };
  154. static int fq1216me_device_init(struct fq1216me_device_s *devp)
  155. {
  156. int ret;
  157. struct device *devp_;
  158. devp = kmalloc(sizeof(struct fq1216me_device_s), GFP_KERNEL);
  159. if (!devp)
  160. {
  161. printk(KERN_ERR "failed to allocate memory\n");
  162. return -ENOMEM;
  163. }
  164. ret = alloc_chrdev_region(&devp->devno, 0, 1, TUNER_DEVICE_NAME);
  165. if (ret < 0) {
  166. printk(KERN_ERR "failed to allocate major number\n");
  167. kfree(devp);
  168. return -1;
  169. }
  170. devp->clsp = class_create(THIS_MODULE, TUNER_DEVICE_NAME);
  171. if (IS_ERR(devp->clsp))
  172. {
  173. unregister_chrdev_region(devp->devno, 1);
  174. kfree(devp);
  175. ret = (int)PTR_ERR(devp->clsp);
  176. return -1;
  177. }
  178. cdev_init(&devp->cdev, &fq1216me_fops);
  179. devp->cdev.owner = THIS_MODULE;
  180. ret = cdev_add(&devp->cdev, devp->devno, 1);
  181. if (ret) {
  182. printk(KERN_ERR "failed to add device\n");
  183. class_destroy(devp->clsp);
  184. unregister_chrdev_region(devp->devno, 1);
  185. kfree(devp);
  186. return ret;
  187. }
  188. devp_ = device_create(devp->clsp, NULL, devp->devno , NULL, "tuner%d", 0);
  189. if (IS_ERR(devp_)) {
  190. pr_err("failed to create device node\n");
  191. class_destroy(devp->clsp);
  192. unregister_chrdev_region(devp->devno, 1);
  193. kfree(devp);
  194. /* @todo do with error */
  195. return PTR_ERR(devp);;
  196. }
  197. return 0;
  198. }
  199. static void fq1216me_device_release(struct fq1216me_device_s *devp)
  200. {
  201. cdev_del(&devp->cdev);
  202. device_destroy(devp->clsp, devp->devno );
  203. cdev_del(&devp->cdev);
  204. class_destroy(devp->clsp);
  205. unregister_chrdev_region(devp->devno, 1);
  206. kfree(devp);
  207. }
  208. static int fq1216me_probe(struct platform_device *pdev)
  209. {
  210. int ret;
  211. int i2c_nr = 0;
  212. pr_info("%s: \n", __FUNCTION__);
  213. ret = fq1216me_device_init(devp);
  214. if (ret)
  215. {
  216. pr_info(" device init failed\n");
  217. return ret;
  218. }
  219. printk("fq1216me_probe ok.\n");
  220. return 0;
  221. }
  222. static int fq1216me_remove(struct platform_device *pdev)
  223. {
  224. fq1216me_device_release(devp);
  225. printk(KERN_ERR "driver removed ok.\n");
  226. return 0;
  227. }
  228. static struct platform_driver fq1216me_driver = {
  229. .probe = fq1216me_probe,
  230. .remove = fq1216me_remove,
  231. .driver = {
  232. .name = TUNER_DEVICE_NAME,
  233. }
  234. };
  235. static int __init fq1216me_init(void)
  236. {
  237. int ret = 0;
  238. pr_info( "%s . \n", __FUNCTION__ );
  239. ret = platform_driver_register(&fq1216me_driver);
  240. if (ret != 0) {
  241. printk(KERN_ERR "failed to register module, error %d\n", ret);
  242. return -ENODEV;
  243. }
  244. return ret;
  245. }
  246. static void __exit fq1216me_exit(void)
  247. {
  248. pr_info( "%s . \n", __FUNCTION__ );
  249. platform_driver_unregister(&fq1216me_driver);
  250. }
  251. module_init(fq1216me_init);
  252. module_exit(fq1216me_exit);
  253. MODULE_DESCRIPTION("Amlogic FQ1216ME Driver");
  254. MODULE_LICENSE("GPL");
  255. MODULE_AUTHOR("Bo Yang <bo.yang@amlogic.com>");