Commit | Line | Data |
---|---|---|
6fa3eb70 S |
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 | ||
23 | #include <linux/workqueue.h> | |
24 | #include <linux/semaphore.h> | |
25 | #include <linux/slab.h> | |
26 | ||
27 | #include "mtkfb_vsync.h" | |
28 | ||
29 | #include <linux/xlog.h> | |
30 | ||
31 | #define VSYNC_DBG(...) xlog_printk(ANDROID_LOG_DEBUG, MTKFB_VSYNC_DEVNAME, __VA_ARGS__) | |
32 | ||
33 | #define VSYNC_INF(...) xlog_printk(ANDROID_LOG_INFO, MTKFB_VSYNC_DEVNAME, __VA_ARGS__) | |
34 | #define VSYNC_WRN(...) xlog_printk(ANDROID_LOG_WARN, MTKFB_VSYNC_DEVNAME, __VA_ARGS__) | |
35 | #define VSYNC_ERR(...) xlog_printk(ANDROID_LOG_ERROR, MTKFB_VSYNC_DEVNAME, __VA_ARGS__) | |
36 | ||
37 | static size_t mtkfb_vsync_on = false; | |
38 | #define MTKFB_VSYNC_LOG(fmt, arg...) \ | |
39 | do { \ | |
40 | if (mtkfb_vsync_on) VSYNC_WRN(fmt, ##arg); \ | |
41 | }while (0) | |
42 | ||
43 | #define MTKFB_VSYNC_FUNC() \ | |
44 | do { \ | |
45 | if(mtkfb_vsync_on) VSYNC_WRN("[Func]%s\n", __func__); \ | |
46 | }while (0) | |
47 | ||
48 | static dev_t mtkfb_vsync_devno; | |
49 | static struct cdev *mtkfb_vsync_cdev; | |
50 | static struct class *mtkfb_vsync_class = NULL; | |
51 | ||
52 | DEFINE_SEMAPHORE(mtkfb_vsync_sem); | |
53 | ||
54 | extern void mtkfb_waitVsync(void); | |
55 | extern void mtkfb_disable_non_fb_layer(void); | |
56 | ||
57 | void mtkfb_vsync_log_enable(int enable) | |
58 | { | |
59 | mtkfb_vsync_on = enable; | |
60 | MTKFB_VSYNC_LOG("mtkfb_vsync log %s\n", enable?"enabled":"disabled"); | |
61 | } | |
62 | ||
63 | static int mtkfb_vsync_open(struct inode *inode, struct file *file) | |
64 | { | |
65 | VSYNC_DBG("driver open\n"); | |
66 | return 0; | |
67 | } | |
68 | ||
69 | static ssize_t mtkfb_vsync_read(struct file *file, char __user *data, size_t len, loff_t *ppos) | |
70 | { | |
71 | VSYNC_DBG("driver read\n"); | |
72 | return 0; | |
73 | } | |
74 | ||
75 | static int mtkfb_vsync_release(struct inode *inode, struct file *file) | |
76 | { | |
77 | VSYNC_DBG("driver release\n"); | |
78 | VSYNC_DBG("reset overlay engine\n"); | |
79 | //mtkfb_disable_non_fb_layer(); //[mo] | |
80 | return 0; | |
81 | } | |
82 | ||
83 | static int mtkfb_vsync_flush(struct file * a_pstFile , fl_owner_t a_id) | |
84 | { | |
85 | // To Do : error handling here | |
86 | return 0; | |
87 | } | |
88 | ||
89 | static long mtkfb_vsync_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |
90 | { | |
91 | int ret = 0; | |
92 | MTKFB_VSYNC_FUNC(); | |
93 | switch (cmd) | |
94 | { | |
95 | case MTKFB_VSYNC_IOCTL: | |
96 | { | |
97 | MTKFB_VSYNC_LOG("[MTKFB_VSYNC]: enter MTKFB_VSYNC_IOCTL\n"); | |
98 | if (down_interruptible(&mtkfb_vsync_sem)) { | |
99 | pr_info("[mtkfb_vsync_ioctl] can't get semaphore,%d\n", __LINE__); | |
100 | msleep(20); | |
101 | return ret; | |
102 | } | |
103 | mtkfb_waitVsync(); | |
104 | up(&mtkfb_vsync_sem); | |
105 | MTKFB_VSYNC_LOG("[MTKFB_VSYNC]: leave MTKFB_VSYNC_IOCTL\n"); | |
106 | } | |
107 | break; | |
108 | } | |
109 | return ret; | |
110 | } | |
111 | ||
112 | ||
113 | static struct file_operations mtkfb_vsync_fops = { | |
114 | .owner = THIS_MODULE, | |
115 | .unlocked_ioctl = mtkfb_vsync_unlocked_ioctl, | |
116 | .open = mtkfb_vsync_open, | |
117 | .release = mtkfb_vsync_release, | |
118 | .flush = mtkfb_vsync_flush, | |
119 | .read = mtkfb_vsync_read, | |
120 | }; | |
121 | ||
122 | static int mtkfb_vsync_probe(struct platform_device *pdev) | |
123 | { | |
124 | struct class_device; | |
125 | struct class_device *class_dev = NULL; | |
126 | ||
127 | pr_info("\n=== MTKFB_VSYNC probe ===\n"); | |
128 | ||
129 | if (alloc_chrdev_region(&mtkfb_vsync_devno, 0, 1, MTKFB_VSYNC_DEVNAME)) | |
130 | { | |
131 | VSYNC_ERR("can't get device major number...\n"); | |
132 | return -EFAULT; | |
133 | } | |
134 | ||
135 | pr_info("get device major number (%d)\n", mtkfb_vsync_devno); | |
136 | ||
137 | mtkfb_vsync_cdev = cdev_alloc(); | |
138 | mtkfb_vsync_cdev->owner = THIS_MODULE; | |
139 | mtkfb_vsync_cdev->ops = &mtkfb_vsync_fops; | |
140 | ||
141 | cdev_add(mtkfb_vsync_cdev, mtkfb_vsync_devno, 1); | |
142 | ||
143 | mtkfb_vsync_class = class_create(THIS_MODULE, MTKFB_VSYNC_DEVNAME); | |
144 | class_dev = (struct class_device *)device_create(mtkfb_vsync_class, NULL, mtkfb_vsync_devno, NULL, MTKFB_VSYNC_DEVNAME); | |
145 | ||
146 | VSYNC_INF("probe is done\n"); | |
147 | return 0; | |
148 | } | |
149 | ||
150 | static int mtkfb_vsync_remove(struct platform_device *pdev) | |
151 | { | |
152 | VSYNC_INF("device remove\n"); | |
153 | return 0; | |
154 | } | |
155 | ||
156 | static void mtkfb_vsync_shutdown(struct platform_device *pdev) | |
157 | { | |
158 | pr_info("mtkfb_vsync device shutdown\n"); | |
159 | } | |
160 | ||
161 | static int mtkfb_vsync_suspend(struct platform_device *pdev, pm_message_t mesg) | |
162 | { | |
163 | return 0; | |
164 | } | |
165 | ||
166 | static int mtkfb_vsync_resume(struct platform_device *pdev) | |
167 | { | |
168 | return 0; | |
169 | } | |
170 | ||
171 | static struct platform_driver mtkfb_vsync_driver = { | |
172 | .probe = mtkfb_vsync_probe, | |
173 | .remove = mtkfb_vsync_remove, | |
174 | .shutdown = mtkfb_vsync_shutdown, | |
175 | .suspend = mtkfb_vsync_suspend, | |
176 | .resume = mtkfb_vsync_resume, | |
177 | .driver = { | |
178 | .name = MTKFB_VSYNC_DEVNAME, | |
179 | }, | |
180 | }; | |
181 | ||
182 | static void mtkfb_vsync_device_release(struct device *dev) | |
183 | { | |
184 | } | |
185 | ||
186 | static u64 mtkfb_vsync_dmamask = ~(u32)0; | |
187 | ||
188 | static struct platform_device mtkfb_vsync_device = { | |
189 | .name = MTKFB_VSYNC_DEVNAME, | |
190 | .id = 0, | |
191 | .dev = { | |
192 | .release = mtkfb_vsync_device_release, | |
193 | .dma_mask = &mtkfb_vsync_dmamask, | |
194 | .coherent_dma_mask = 0xffffffff, | |
195 | }, | |
196 | .num_resources = 0, | |
197 | }; | |
198 | ||
199 | static int __init mtkfb_vsync_init(void) | |
200 | { | |
201 | VSYNC_INF("initializeing driver...\n"); | |
202 | ||
203 | if (platform_device_register(&mtkfb_vsync_device)) | |
204 | { | |
205 | VSYNC_ERR("failed to register device\n"); | |
206 | return -ENODEV; | |
207 | } | |
208 | ||
209 | if (platform_driver_register(&mtkfb_vsync_driver)) | |
210 | { | |
211 | VSYNC_ERR("failed to register driver\n"); | |
212 | platform_device_unregister(&mtkfb_vsync_device); | |
213 | return -ENODEV; | |
214 | } | |
215 | ||
216 | return 0; | |
217 | } | |
218 | ||
219 | static void __exit mtkfb_vsync_exit(void) | |
220 | { | |
221 | cdev_del(mtkfb_vsync_cdev); | |
222 | unregister_chrdev_region(mtkfb_vsync_devno, 1); | |
223 | ||
224 | platform_driver_unregister(&mtkfb_vsync_driver); | |
225 | platform_device_unregister(&mtkfb_vsync_device); | |
226 | ||
227 | device_destroy(mtkfb_vsync_class, mtkfb_vsync_devno); | |
228 | class_destroy(mtkfb_vsync_class); | |
229 | ||
230 | VSYNC_INF("exit driver...\n"); | |
231 | } | |
232 | ||
233 | module_init(mtkfb_vsync_init); | |
234 | module_exit(mtkfb_vsync_exit); | |
235 | ||
236 | MODULE_DESCRIPTION("MediaTek FB VSYNC Driver"); | |
237 | MODULE_AUTHOR("Zaikuo Wang <Zaikuo.Wang@mediatek.com>"); |