almk_drv.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. #include <linux/kernel.h>
  2. #include <linux/mm.h>
  3. #include <linux/mm_types.h>
  4. #include <linux/module.h>
  5. #include <generated/autoconf.h>
  6. #include <linux/init.h>
  7. #include <linux/types.h>
  8. #include <linux/cdev.h>
  9. #include <linux/kdev_t.h>
  10. #include <linux/delay.h>
  11. #include <linux/ioport.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/dma-mapping.h>
  14. #include <linux/device.h>
  15. #include <linux/fs.h>
  16. #include <linux/interrupt.h>
  17. #include <linux/wait.h>
  18. #include <linux/spinlock.h>
  19. #include <linux/param.h>
  20. #include <linux/uaccess.h>
  21. #include <linux/sched.h>
  22. #include <linux/slab.h>
  23. #include <linux/xlog.h>
  24. #include <linux/io.h>
  25. #include "almk_drv.h"
  26. /* #define USE_SYSRAM */
  27. #define ALMK_MSG pr_debug
  28. #define ALMK_WRN pr_debug
  29. #define ALMK_ERR pr_err
  30. #define ALMK_DEVNAME "mtk_almk"
  31. #define ALMK_PROCESS 0x2
  32. /* -------------------------------------------------------------------------- */
  33. /* */
  34. /* -------------------------------------------------------------------------- */
  35. /* global function */
  36. static unsigned int _almk_int_status;
  37. /* device and driver */
  38. static dev_t almk_devno;
  39. static struct cdev *almk_cdev;
  40. static struct class *almk_class;
  41. /* static wait_queue_head_t enc_wait_queue; */
  42. static spinlock_t almk_lock;
  43. static int almk_status;
  44. #if 0
  45. static int check_all_minfree(void *param, void *param2)
  46. {
  47. #if 1
  48. struct task_struct *p = 0;
  49. int n = 4096 * 170000;
  50. int nr_pages = (n / PAGE_SIZE) + ((n % PAGE_SIZE) ? 1 : 0);
  51. int free_pages = global_page_state(NR_FREE_PAGES) +
  52. global_page_state(NR_FILE_PAGES) + global_page_state(NR_FILE_DIRTY);
  53. ALMK_MSG(KERN_ALERT "%s\n", __func__);
  54. ALMK_MSG(KERN_ALERT "=====================================\n");
  55. for_each_process(p) {
  56. /* get_min_free_pages(p->pid); */
  57. ALMK_MSG(KERN_ALERT "trying to alloc %d bytes (%d pages)\n"
  58. "(NR_FREE_PAGES) + (NR_FILE_PAGES) + (NR_FILE_DIRTY) - nr_pages = (%d + %d + %d - %d) = %d\n"
  59. "target_min_free_pages = %d\n",
  60. n, nr_pages,
  61. global_page_state(NR_FREE_PAGES),
  62. global_page_state(NR_FILE_PAGES),
  63. global_page_state(NR_FILE_DIRTY),
  64. nr_pages, free_pages - nr_pages, get_min_free_pages(p->pid));
  65. ALMK_MSG(KERN_ALERT "allocation is %s\n",
  66. (free_pages - nr_pages >= get_min_free_pages(p->pid)) ? "safe" : "not safe");
  67. }
  68. #endif
  69. }
  70. #endif
  71. static unsigned int get_max_safe_size(pid_t pid)
  72. {
  73. unsigned int all_free_pages;
  74. unsigned int lmk_pages;
  75. unsigned int lowBoundPages = get_min_free_pages(pid);
  76. unsigned int max_safe_size;
  77. lmk_pages = query_lmk_minfree(0);
  78. all_free_pages = global_page_state(NR_FREE_PAGES) +
  79. global_page_state(NR_FILE_PAGES) + global_page_state(NR_FILE_DIRTY);
  80. if (all_free_pages >= (lowBoundPages + lmk_pages))
  81. max_safe_size = (all_free_pages - lowBoundPages - lmk_pages) * PAGE_SIZE;
  82. else if (all_free_pages >= (lowBoundPages))
  83. max_safe_size = (all_free_pages - lowBoundPages) * PAGE_SIZE;
  84. else
  85. return 0;
  86. return max_safe_size;
  87. }
  88. static int almk_ioctl(unsigned int cmd, unsigned long arg, struct file *file)
  89. {
  90. ALMK_DRV_DATA drv_data;
  91. unsigned int max_safe_size;
  92. unsigned int *pStatus;
  93. pStatus = (unsigned int *)file->private_data;
  94. if (NULL == pStatus) {
  95. ALMK_WRN("Private data is null in flush operation. HOW COULD THIS HAPPEN ??\n");
  96. return -EFAULT;
  97. }
  98. switch (cmd) {
  99. /* initial and reset ALMK */
  100. case ALMK_IOCTL_CMD_INIT:
  101. ALMK_MSG("ALMK Driver Initial and Lock\n");
  102. *pStatus = ALMK_PROCESS;
  103. break;
  104. case ALMK_IOCTL_CMD_GET_MAX_SIZE:
  105. ALMK_MSG("ALMK Driver GET_MAX_SIZE!!\n");
  106. if (*pStatus != ALMK_PROCESS) {
  107. ALMK_WRN("Permission Denied! This process can not access ALMK Driver");
  108. return -EFAULT;
  109. }
  110. if (copy_from_user(&drv_data, (void *)arg, sizeof(ALMK_DRV_DATA))) {
  111. ALMK_WRN("ALMK Driver : Copy from user error\n");
  112. return -EFAULT;
  113. }
  114. max_safe_size = get_max_safe_size(drv_data.pid);
  115. if (copy_to_user(drv_data.maxSafeSize, &max_safe_size, sizeof(unsigned int))) {
  116. ALMK_WRN("ALMK Driver : Copy to user error (result)\n");
  117. return -EFAULT;
  118. }
  119. break;
  120. case ALMK_IOCTL_CMD_DEINIT:
  121. /* copy input parameters */
  122. ALMK_MSG("ALMK Driver Deinit!!\n");
  123. if (*pStatus != ALMK_PROCESS) {
  124. ALMK_WRN("Permission Denied! This process can not access ALMK Driver");
  125. return -EFAULT;
  126. }
  127. *pStatus = 0;
  128. return 0;
  129. }
  130. return 0;
  131. }
  132. /* -------------------------------------------------------------------------- */
  133. /* */
  134. /* -------------------------------------------------------------------------- */
  135. /* static int almk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) */
  136. static long almk_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  137. {
  138. switch (cmd) {
  139. case ALMK_IOCTL_CMD_INIT:
  140. case ALMK_IOCTL_CMD_GET_MAX_SIZE:
  141. case ALMK_IOCTL_CMD_DEINIT:
  142. return almk_ioctl(cmd, arg, file);
  143. default:
  144. break;
  145. }
  146. return -EINVAL;
  147. }
  148. static int almk_open(struct inode *inode, struct file *file)
  149. {
  150. unsigned int *pStatus;
  151. /* Allocate and initialize private data */
  152. file->private_data = kmalloc(sizeof(unsigned int), GFP_ATOMIC);
  153. if (NULL == file->private_data) {
  154. ALMK_WRN("Not enough entry for ALMK open operation\n");
  155. return -ENOMEM;
  156. }
  157. pStatus = (unsigned int *)file->private_data;
  158. *pStatus = 0;
  159. return 0;
  160. }
  161. static ssize_t almk_read(struct file *file, char __user *data, size_t len, loff_t *ppos)
  162. {
  163. ALMK_MSG("almk driver read\n");
  164. return 0;
  165. }
  166. static int almk_release(struct inode *inode, struct file *file)
  167. {
  168. if (NULL != file->private_data) {
  169. kfree(file->private_data);
  170. file->private_data = NULL;
  171. }
  172. return 0;
  173. }
  174. static int almk_flush(struct file *a_pstFile, fl_owner_t a_id)
  175. {
  176. unsigned int *pStatus;
  177. pStatus = (unsigned int *)a_pstFile->private_data;
  178. if (NULL == pStatus) {
  179. ALMK_WRN("Private data is null in flush operation. HOW COULD THIS HAPPEN ??\n");
  180. return -EFAULT;
  181. }
  182. return 0;
  183. }
  184. /* Kernel interface */
  185. static struct file_operations const almk_fops = {
  186. .owner = THIS_MODULE,
  187. /* .ioctl = almk_ioctl, */
  188. .unlocked_ioctl = almk_unlocked_ioctl,
  189. .open = almk_open,
  190. .release = almk_release,
  191. .flush = almk_flush,
  192. .read = almk_read,
  193. };
  194. static int almk_probe(struct platform_device *pdev)
  195. {
  196. struct class_device;
  197. int ret;
  198. struct class_device *class_dev = NULL;
  199. ALMK_MSG("-------------almk driver probe-------\n");
  200. ret = alloc_chrdev_region(&almk_devno, 0, 1, ALMK_DEVNAME);
  201. if (ret)
  202. ALMK_ERR("Error: Can't Get Major number for ALMK Device\n");
  203. else
  204. ALMK_MSG("Get ALMK Device Major number (%d)\n", almk_devno);
  205. almk_cdev = cdev_alloc();
  206. almk_cdev->owner = THIS_MODULE;
  207. almk_cdev->ops = &almk_fops;
  208. ret = cdev_add(almk_cdev, almk_devno, 1);
  209. almk_class = class_create(THIS_MODULE, ALMK_DEVNAME);
  210. class_dev =
  211. (struct class_device *)device_create(almk_class, NULL, almk_devno, NULL, ALMK_DEVNAME);
  212. spin_lock_init(&almk_lock);
  213. /* initial driver, register driver ISR */
  214. almk_status = 0;
  215. _almk_int_status = 0;
  216. ALMK_MSG("ALMK Probe Done\n");
  217. /* NOT_REFERENCED(class_dev); */
  218. return 0;
  219. }
  220. static int almk_remove(struct platform_device *pdev)
  221. {
  222. ALMK_MSG("ALMK driver remove\n");
  223. ALMK_MSG("Done\n");
  224. return 0;
  225. }
  226. static void almk_shutdown(struct platform_device *pdev)
  227. {
  228. ALMK_MSG("ALMK driver shutdown\n");
  229. /* Nothing yet */
  230. }
  231. /* PM suspend */
  232. static int almk_suspend(struct platform_device *pdev, pm_message_t mesg)
  233. {
  234. /* almk_drv_dec_deinit(); */
  235. /* almk_drv_enc_deinit(); */
  236. return 0;
  237. }
  238. /* PM resume */
  239. static int almk_resume(struct platform_device *pdev)
  240. {
  241. return 0;
  242. }
  243. static struct platform_driver almk_driver = {
  244. .probe = almk_probe,
  245. .remove = almk_remove,
  246. .shutdown = almk_shutdown,
  247. .suspend = almk_suspend,
  248. .resume = almk_resume,
  249. .driver = {
  250. .name = ALMK_DEVNAME,
  251. },
  252. };
  253. static void almk_device_release(struct device *dev)
  254. {
  255. /* Nothing to release? */
  256. }
  257. static u64 jpegdec_dmamask = ~(u32) 0;
  258. static struct platform_device almk_device = {
  259. .name = ALMK_DEVNAME,
  260. .id = 0,
  261. .dev = {
  262. .release = almk_device_release,
  263. .dma_mask = &jpegdec_dmamask,
  264. .coherent_dma_mask = 0xffffffff,
  265. },
  266. .num_resources = 0,
  267. };
  268. static int __init almk_init(void)
  269. {
  270. int ret;
  271. ALMK_MSG("ALMK driver initialize\n");
  272. ALMK_MSG("Register the ALMK driver device\n");
  273. if (platform_device_register(&almk_device)) {
  274. ALMK_ERR("failed to register jpeg driver device\n");
  275. ret = -ENODEV;
  276. return ret;
  277. }
  278. ALMK_MSG("Register the ALMK driver\n");
  279. if (platform_driver_register(&almk_driver)) {
  280. ALMK_ERR("failed to register jpeg driver\n");
  281. platform_device_unregister(&almk_device);
  282. ret = -ENODEV;
  283. return ret;
  284. }
  285. return 0;
  286. }
  287. static void __exit almk_exit(void)
  288. {
  289. cdev_del(almk_cdev);
  290. unregister_chrdev_region(almk_devno, 1);
  291. platform_driver_unregister(&almk_driver);
  292. platform_device_unregister(&almk_device);
  293. device_destroy(almk_class, almk_devno);
  294. class_destroy(almk_class);
  295. ALMK_MSG("Done\n");
  296. }
  297. module_init(almk_init);
  298. module_exit(almk_exit);
  299. MODULE_AUTHOR("Otis, Huang <otis.huang@mediatek.com>");
  300. MODULE_DESCRIPTION("ALMK driver");
  301. MODULE_LICENSE("GPL");