Advertisement
Guest User

Untitled

a guest
Jun 28th, 2017
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.86 KB | None | 0 0
  1. #include <linux/miscdevice.h>
  2. #include <linux/sysfs.h>
  3. #include <linux/fs.h>
  4. #include <linux/uaccess.h>
  5. #include <linux/delay.h>
  6. #include <linux/ioctl.h>
  7. #include <linux/err.h>
  8. #include <linux/errno.h>
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <asm/io.h>
  12. #include "sr2351_fm_ctrl.h"
  13.  
  14. #ifdef CONFIG_OF
  15. #include <linux/device.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/of.h>
  18. #include <linux/of_address.h>
  19. #include <linux/of_irq.h>
  20. #endif
  21.  
  22. #define SR2351_FM_VERSION "v0.9"
  23. static u32 g_volume = 0;
  24.  
  25. int sr2351_fm_set_volume(u32 iarg)
  26. {
  27. SR2351_PRINT("FM set volume : %i.", iarg);
  28.  
  29. g_volume = iarg;
  30. if(0 == iarg)
  31. {
  32. sr2351_fm_mute();
  33. }
  34. else
  35. {
  36. sr2351_fm_unmute();
  37. }
  38.  
  39. return 0;
  40. }
  41.  
  42. u32 sr2351_fm_get_volume(void)
  43. {
  44. SR2351_PRINT("FM get volume.");
  45. return g_volume;
  46. }
  47.  
  48.  
  49.  
  50. int sr2351_fm_open(struct inode *inode, struct file *filep)
  51. {
  52. int ret = -EINVAL;
  53. int status;
  54.  
  55. SR2351_PRINT("start open shark fm module...");
  56. /*
  57. if (get_suspend_state() != PM_SUSPEND_ON)
  58. {
  59. SR2351_PRINT("The system is suspending!");
  60. return -2;
  61. }
  62. */
  63. /*
  64. ret = nonseekable_open(inode, filep);
  65. if (ret < 0) {
  66. SR2351_PRINT("open misc device failed.");
  67. return ret;
  68. }
  69. */
  70.  
  71. ret = sr2351_fm_init();
  72. if (ret < 0) {
  73. SR2351_PRINT("sr2351_fm_init failed!");
  74. return ret;
  75. }
  76.  
  77. ret = sr2351_fm_get_status(&status);
  78. if (ret < 0) {
  79. SR2351_PRINT("sr2351_read_fm_en failed!");
  80. return ret;
  81. }
  82. if (status) {
  83. SR2351_PRINT("sr2351 fm have been opened.");
  84. } else {
  85. ret = sr2351_fm_en();
  86. if (ret < 0) {
  87. SR2351_PRINT("sr2351_fm_en failed!");
  88. return ret;
  89. }
  90. }
  91.  
  92. SR2351_PRINT("Open shark fm module success.");
  93.  
  94. return 0;
  95. }
  96.  
  97. long sr2351_fm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  98. {
  99. void __user *argp = (void __user *)arg;
  100. long ret = 0;
  101. u32 iarg = 0;
  102. u32 buf[4] = { 0 };
  103.  
  104. SR2351_PRINT("FM IOCTL: 0x%x.", cmd);
  105.  
  106. switch (cmd) {
  107. case FM_IOCTL_ENABLE:
  108. if (copy_from_user(&iarg, argp, sizeof(iarg)) || iarg > 1)
  109. ret = -EFAULT;
  110.  
  111. if (iarg == 1)
  112. ret = sr2351_fm_en();
  113. else
  114. ret = sr2351_fm_dis();
  115.  
  116. break;
  117.  
  118. case FM_IOCTL_GET_ENABLE:
  119. ret = sr2351_fm_get_status(&iarg);
  120. if (copy_to_user(argp, &iarg, sizeof(iarg)))
  121. ret = -EFAULT;
  122.  
  123. break;
  124.  
  125. case FM_IOCTL_SET_TUNE:
  126. if (copy_from_user(&iarg, argp, sizeof(iarg)))
  127. return -EFAULT;
  128. sr2351_fm_mute();
  129. ret = sr2351_fm_set_tune(iarg);
  130. sr2351_fm_unmute();
  131. break;
  132.  
  133. case FM_IOCTL_GET_FREQ:
  134. ret = sr2351_fm_get_frequency(&iarg);
  135. if (copy_to_user(argp, &iarg, sizeof(iarg)))
  136. ret = -EFAULT;
  137. break;
  138.  
  139. case FM_IOCTL_SEARCH:
  140. if (copy_from_user(buf, argp, sizeof(buf)))
  141. ret = -EFAULT;
  142. sr2351_fm_mute();
  143. ret = sr2351_fm_seek(buf[0], /* start frequency */
  144. buf[1], /* seek direction */
  145. buf[2], /* time out */
  146. &buf[3]); /* frequency found */
  147.  
  148. if (copy_to_user(argp, buf, sizeof(buf)))
  149. ret = -EFAULT;
  150.  
  151. break;
  152.  
  153. case FM_IOCTL_STOP_SEARCH:
  154. ret = sr2351_fm_stop_seek();
  155. break;
  156.  
  157. case FM_IOCTL_MUTE:
  158. break;
  159.  
  160. case FM_IOCTL_SET_VOLUME:
  161. if (copy_from_user(&iarg, argp, sizeof(iarg)))
  162. ret = -EFAULT;
  163.  
  164. ret = sr2351_fm_set_volume(iarg);
  165. break;
  166.  
  167. case FM_IOCTL_GET_VOLUME:
  168. iarg = sr2351_fm_get_volume();
  169. if (copy_to_user(argp, &iarg, sizeof(iarg)))
  170. ret = -EFAULT;
  171.  
  172. break;
  173.  
  174. case FM_IOCTL_CONFIG:
  175. if (copy_from_user(&iarg, argp, sizeof(iarg)))
  176. ret = -EFAULT;
  177.  
  178. SR2351_PRINT("\n\nFM FM_IOCTL_CONFIG set %d\n\n", iarg);
  179.  
  180. break;
  181.  
  182. case FM_IOCTL_GET_RSSI:
  183. ret = sr2351_fm_get_rssi(&iarg);
  184. if(copy_to_user(argp,&iarg,sizeof(iarg)))
  185. ret = -EFAULT;
  186. break;
  187.  
  188. case FM_IOCTL_SET_BAND:
  189. if (copy_from_user(buf, argp, sizeof(buf)))
  190. ret = -EFAULT;
  191. ret = sr2351_fm_set_band(buf[0],//min freq
  192. buf[1]);//max freq
  193. break;
  194.  
  195. default:
  196. SR2351_PRINT("Unknown FM IOCTL!");
  197. return -EINVAL;
  198. }
  199.  
  200. return ret;
  201. }
  202.  
  203. int sr2351_fm_release(struct inode *inode, struct file *filep)
  204. {
  205. SR2351_PRINT("sr2351_fm_misc_release");
  206.  
  207. sr2351_fm_deinit();
  208.  
  209. return 0;
  210. }
  211.  
  212. const struct file_operations sr2351_fm_misc_fops = {
  213. .owner = THIS_MODULE,
  214. .open = sr2351_fm_open,
  215. .unlocked_ioctl = sr2351_fm_ioctl,
  216. .release = sr2351_fm_release,
  217. };
  218.  
  219. struct miscdevice sr2351_fm_misc_device = {
  220. .minor = MISC_DYNAMIC_MINOR,
  221. .name = SR2351_FM_DEV_NAME,
  222. .fops = &sr2351_fm_misc_fops,
  223. };
  224.  
  225. #ifdef CONFIG_OF
  226. static struct sr2351_fm_addr
  227. {
  228. unsigned long fm_base;
  229. unsigned long apb_base;
  230. unsigned long pmu_base;
  231. unsigned long aonckg_base;
  232. unsigned long pin_base;
  233. }sr2351_fm_base;
  234.  
  235. unsigned long rf2351_fm_get_fm_base(void)
  236. {
  237. return sr2351_fm_base.fm_base;
  238. }
  239. unsigned long rf2351_fm_get_apb_base(void)
  240. {
  241. return sr2351_fm_base.apb_base;
  242. }
  243.  
  244. unsigned long rf2351_fm_get_pmu_base(void)
  245. {
  246. return sr2351_fm_base.pmu_base;
  247. }
  248.  
  249. unsigned long rf2351_fm_get_aonckg_base(void)
  250. {
  251. return sr2351_fm_base.aonckg_base;
  252. }
  253.  
  254. unsigned long rf2351_fm_get_pin_base(void)
  255. {
  256. return sr2351_fm_base.pin_base;
  257. }
  258.  
  259. static int sr2351_fm_parse_dts(struct device_node *np)
  260. {
  261. int ret;
  262. struct resource res;
  263.  
  264. //np = of_find_node_by_name(NULL, "sprd_fm");
  265. if (NULL == np)
  266. {
  267. SR2351_PRINT("Can't get the sprd_fm node!\n");
  268. return -ENODEV;
  269. }
  270. SR2351_PRINT(" find the fm_sr2351 node!\n");
  271.  
  272. ret = of_address_to_resource(np, 0, &res);
  273. if (ret < 0)
  274. {
  275. SR2351_PRINT("Can't get the fm reg base!\n");
  276. return -EIO;
  277. }
  278. sr2351_fm_base.fm_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
  279. if(!sr2351_fm_base.fm_base)
  280. {
  281. BUG();
  282. }
  283. SR2351_PRINT("fm reg base is 0x%x\n", sr2351_fm_base.fm_base);
  284.  
  285. ret = of_address_to_resource(np, 1, &res);
  286. if (ret < 0)
  287. {
  288. SR2351_PRINT("Can't get the apb reg base!\n");
  289. return -EIO;
  290. }
  291. sr2351_fm_base.apb_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
  292. if(!sr2351_fm_base.apb_base)
  293. {
  294. BUG();
  295. }
  296. SR2351_PRINT("apb reg base is 0x%x\n", sr2351_fm_base.apb_base);
  297.  
  298. ret = of_address_to_resource(np, 2, &res);
  299. if (ret < 0)
  300. {
  301. SR2351_PRINT("Can't get the pmu reg base!\n");
  302. return -EIO;
  303. }
  304. sr2351_fm_base.pmu_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
  305. if(!sr2351_fm_base.pmu_base)
  306. {
  307. BUG();
  308. }
  309. SR2351_PRINT("pmu reg base is 0x%x\n", sr2351_fm_base.pmu_base);
  310.  
  311. ret = of_address_to_resource(np, 3, &res);
  312. if (ret < 0)
  313. {
  314. SR2351_PRINT("Can't get the aonckg reg base!\n");
  315. return -EIO;
  316. }
  317. sr2351_fm_base.aonckg_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
  318. if(!sr2351_fm_base.aonckg_base)
  319. {
  320. BUG();
  321. }
  322. SR2351_PRINT("pmu reg base is 0x%x\n", sr2351_fm_base.aonckg_base);
  323.  
  324. ret = of_address_to_resource(np, 4, &res);
  325. if (ret < 0)
  326. {
  327. SR2351_PRINT("Can't get the pin reg base!\n");
  328. return -EIO;
  329. }
  330. sr2351_fm_base.pin_base = (unsigned long)ioremap_nocache(res.start, resource_size(&res));
  331. if(!sr2351_fm_base.pin_base)
  332. {
  333. BUG();
  334. }
  335. SR2351_PRINT("pin reg base is 0x%x\n", sr2351_fm_base.pin_base);
  336.  
  337.  
  338. return 0;
  339. }
  340.  
  341. static const struct of_device_id of_match_table_fm[] = {
  342. { .compatible = "sprd,sprd_fm", },
  343. { },
  344. };
  345. MODULE_DEVICE_TABLE(of, of_match_table_fm);
  346. #endif
  347.  
  348. static int sr2351_fm_probe(struct platform_device *pdev)
  349. {
  350. int ret = -EINVAL;
  351. char *ver_str = SR2351_FM_VERSION;
  352.  
  353. #ifdef CONFIG_OF
  354. struct device_node *np;
  355. np = pdev->dev.of_node;
  356.  
  357. ret = sr2351_fm_parse_dts(np);
  358. if (ret < 0)
  359. {
  360. SR2351_PRINT("sr2351_fm_parse_dts failed!");
  361. return ret;
  362. }
  363. #endif
  364.  
  365. SR2351_PRINT("**********************************************");
  366. SR2351_PRINT(" SR2351 FM driver ");
  367. SR2351_PRINT(" Version: %s", ver_str);
  368. SR2351_PRINT(" Build date: %s %s", __DATE__, __TIME__);
  369. SR2351_PRINT("**********************************************");
  370.  
  371. ret = misc_register(&sr2351_fm_misc_device);
  372. if (ret < 0)
  373. {
  374. SR2351_PRINT("misc_register failed!");
  375. return ret;
  376. }
  377.  
  378. SR2351_PRINT("sr2351_fm_init success.\n");
  379.  
  380. return 0;
  381. }
  382.  
  383. static int sr2351_fm_remove(struct platform_device *pdev)
  384. {
  385.  
  386. SR2351_PRINT("exit_fm_driver!\n");
  387. misc_deregister(&sr2351_fm_misc_device);
  388.  
  389. return 0;
  390. }
  391.  
  392. #ifdef CONFIG_PM
  393. static int sr2351_fm_suspend(struct platform_device *dev, pm_message_t state)
  394. {
  395. sr2351_fm_enter_sleep();
  396. return 0;
  397. }
  398.  
  399. static int sr2351_fm_resume(struct platform_device *dev)
  400. {
  401. sr2351_fm_exit_sleep();
  402. return 0;
  403. }
  404. #else
  405. #define sr2351_fmt_suspend NULL
  406. #define sr2351_fm_resume NULL
  407. #endif
  408.  
  409.  
  410. static struct platform_driver sr2351_fm_driver = {
  411. .driver = {
  412. .name = "sprd_fm",
  413. .owner = THIS_MODULE,
  414. #ifdef CONFIG_OF
  415. .of_match_table = of_match_ptr(of_match_table_fm) ,
  416. #endif
  417. },
  418. .probe = sr2351_fm_probe,
  419. .remove = sr2351_fm_remove,
  420. .suspend = sr2351_fm_suspend,
  421. .resume = sr2351_fm_resume,
  422. };
  423.  
  424. #ifndef CONFIG_OF
  425. struct platform_device sr2351_fm_device = {
  426. .name = "sprd_fm",
  427. .id = -1,
  428. };
  429. #endif
  430.  
  431. int __init init_fm_driver(void)
  432. {
  433. int ret;
  434. #ifndef CONFIG_OF
  435. ret = platform_device_register(&sr2351_fm_device);
  436. if (ret)
  437. {
  438. SR2351_PRINT("sr2351_fm: platform_device_register failed: %d\n", ret);
  439. return ret;
  440. }
  441. #endif
  442. ret = platform_driver_register(&sr2351_fm_driver);
  443. if (ret)
  444. {
  445. #ifndef CONFIG_OF
  446. platform_device_unregister(&sr2351_fm_device);
  447. #endif
  448. SR2351_PRINT("sr2351_fm: probe failed: %d\n", ret);
  449. }
  450. SR2351_PRINT("sr2351_fm: probe sucess: %d\n", ret);
  451.  
  452. return ret;
  453. }
  454.  
  455. void __exit exit_fm_driver(void)
  456. {
  457. platform_driver_unregister(&sr2351_fm_driver);
  458. }
  459.  
  460. module_init(init_fm_driver);
  461. module_exit(exit_fm_driver);
  462.  
  463. MODULE_DESCRIPTION("SR2351 FM radio driver");
  464. MODULE_AUTHOR("Spreadtrum Inc.");
  465. MODULE_LICENSE("GPL");
  466. MODULE_VERSION(SR2351_FM_VERSION);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement