rk3368 lcdc: overlay mode depend on screen color mode
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / iep / iep_drv.c
1 /* 
2  * Copyright (C) 2013 ROCKCHIP, Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  * 
13  */
14
15 #include <linux/clk.h>
16 #include <linux/delay.h>
17 #include <linux/slab.h>
18 #include <linux/fs.h>
19 #include <linux/sched.h>
20 #include <linux/uaccess.h>
21 #include <linux/platform_device.h>
22 #include <linux/interrupt.h>
23 #include <linux/kthread.h>
24 #include <linux/poll.h>
25 #include <linux/dma-mapping.h>
26 #include <linux/fb.h>
27 #include <linux/rk_fb.h>
28 #include <linux/wakelock.h>
29 #include <linux/of.h>
30 #include <linux/of_platform.h>
31 #include <linux/io.h>
32 #include <linux/module.h>
33 #include <linux/rockchip/cpu.h>
34 #include <linux/rockchip/cru.h>
35 #include <asm/cacheflush.h>
36 #include "iep_drv.h"
37 #if defined(CONFIG_IEP_MMU)
38 #include "iep_mmu.h"
39 #endif
40 #include "hw_iep_reg.h"
41
42 #define IEP_MAJOR               255
43 #define IEP_CLK_ENABLE
44 /*#define IEP_TEST_CASE*/
45
46 static int debug;
47 module_param(debug, int, S_IRUGO | S_IWUSR);
48 MODULE_PARM_DESC(debug,
49                  "Debug level - higher value produces more verbose messages");
50
51 #define RK_IEP_SIZE             0x1000
52 #define IEP_TIMEOUT_DELAY       2*HZ
53 #define IEP_POWER_OFF_DELAY     4*HZ
54
55 struct iep_drvdata {
56         struct miscdevice miscdev;
57         struct device dev;
58         void *iep_base;
59         int irq0;
60
61         struct clk *aclk_iep;
62         struct clk *hclk_iep;
63         struct clk *pd_iep;
64         struct clk *aclk_vio1;
65
66         struct mutex mutex;
67
68         /* direct path interface mode. true: enable, false: disable */
69         bool dpi_mode;
70
71         struct delayed_work power_off_work;
72
73         /* clk enable or disable */
74         bool enable;
75         struct wake_lock wake_lock;
76
77         atomic_t iep_int;
78         atomic_t mmu_page_fault;
79         atomic_t mmu_bus_error;
80 };
81
82 struct iep_drvdata *iep_drvdata1 = NULL;
83 iep_service_info iep_service;
84
85 static void iep_reg_deinit(struct iep_reg *reg)
86 {
87 #if defined(CONFIG_IEP_IOMMU)
88         struct iep_mem_region *mem_region = NULL, *n;
89         /* release memory region attach to this registers table.*/
90         if (iep_service.iommu_dev) {
91                 list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {
92                         /*ion_unmap_iommu(iep_service.iommu_dev, iep_service.ion_client, mem_region->hdl);*/
93                         ion_free(iep_service.ion_client, mem_region->hdl);
94                         list_del_init(&mem_region->reg_lnk);
95                         kfree(mem_region);
96                 }
97         }
98 #endif
99         list_del_init(&reg->session_link);
100         list_del_init(&reg->status_link);
101         kfree(reg);
102 }
103
104 static void iep_reg_from_wait_to_ready(struct iep_reg *reg)
105 {
106         list_del_init(&reg->status_link);
107         list_add_tail(&reg->status_link, &iep_service.ready);
108
109         list_del_init(&reg->session_link);
110         list_add_tail(&reg->session_link, &reg->session->ready);
111 }
112
113 static void iep_reg_from_ready_to_running(struct iep_reg *reg)
114 {
115         list_del_init(&reg->status_link);
116         list_add_tail(&reg->status_link, &iep_service.running);
117
118         list_del_init(&reg->session_link);
119         list_add_tail(&reg->session_link, &reg->session->running);
120 }
121
122 static void iep_del_running_list(void)
123 {
124         struct iep_reg *reg;
125         int cnt = 0;
126
127         mutex_lock(&iep_service.lock);
128
129         while (!list_empty(&iep_service.running)) {
130                 BUG_ON(cnt != 0);
131                 reg = list_entry(iep_service.running.next, struct iep_reg, status_link);
132
133                 atomic_dec(&reg->session->task_running);
134                 atomic_dec(&iep_service.total_running);
135
136                 if (list_empty(&reg->session->waiting)) {
137                         atomic_set(&reg->session->done, 1);
138                         atomic_inc(&reg->session->num_done);
139                         wake_up(&reg->session->wait);
140                 }
141
142                 iep_reg_deinit(reg);
143                 cnt++;
144         }
145
146         mutex_unlock(&iep_service.lock);
147 }
148
149 static void iep_dump(void)
150 {
151         struct iep_status sts;
152
153         sts = iep_get_status(iep_drvdata1->iep_base);
154
155         IEP_INFO("scl_sts: %u, dil_sts %u, wyuv_sts %u, ryuv_sts %u, wrgb_sts %u, rrgb_sts %u, voi_sts %u\n",
156                 sts.scl_sts, sts.dil_sts, sts.wyuv_sts, sts.ryuv_sts, sts.wrgb_sts, sts.rrgb_sts, sts.voi_sts); {
157                 int *reg = (int *)iep_drvdata1->iep_base;
158                 int i;
159
160                 /* could not read validate data from address after base+0x40 */
161                 for (i = 0; i < 0x40; i++) {
162                         IEP_INFO("%08x ", reg[i]);
163
164                         if ((i + 1) % 4 == 0) {
165                                 IEP_INFO("\n");
166                         }
167                 }
168
169                 IEP_INFO("\n");
170         }
171 }
172
173 /* Caller must hold iep_service.lock */
174 static void iep_del_running_list_timeout(void)
175 {
176         struct iep_reg *reg;
177
178         mutex_lock(&iep_service.lock);
179
180         while (!list_empty(&iep_service.running)) {
181                 reg = list_entry(iep_service.running.next, struct iep_reg, status_link);
182
183                 atomic_dec(&reg->session->task_running);
184                 atomic_dec(&iep_service.total_running);
185
186                 /* iep_soft_rst(iep_drvdata1->iep_base); */
187
188                 iep_dump();
189
190                 if (list_empty(&reg->session->waiting)) {
191                         atomic_set(&reg->session->done, 1);
192                         wake_up(&reg->session->wait);
193                 }
194
195                 iep_reg_deinit(reg);
196         }
197
198         mutex_unlock(&iep_service.lock);
199 }
200
201 static inline void iep_queue_power_off_work(void)
202 {
203         queue_delayed_work(system_nrt_wq, &iep_drvdata1->power_off_work, IEP_POWER_OFF_DELAY);
204 }
205
206 static void iep_power_on(void)
207 {
208         static ktime_t last;
209         ktime_t now = ktime_get();
210         if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) {
211                 cancel_delayed_work_sync(&iep_drvdata1->power_off_work);
212                 iep_queue_power_off_work();
213                 last = now;
214         }
215
216         if (iep_service.enable)
217                 return;
218
219         IEP_INFO("IEP Power ON\n");
220
221         /* iep_soft_rst(iep_drvdata1->iep_base); */
222
223 #ifdef IEP_CLK_ENABLE
224         if (iep_drvdata1->pd_iep)
225                 clk_prepare_enable(iep_drvdata1->pd_iep);
226         clk_prepare_enable(iep_drvdata1->aclk_iep);
227         clk_prepare_enable(iep_drvdata1->hclk_iep);
228 #endif
229
230         wake_lock(&iep_drvdata1->wake_lock);
231
232 #if defined(CONFIG_IEP_IOMMU)
233         if (iep_service.iommu_dev) {
234                 rockchip_iovmm_activate(iep_service.iommu_dev);
235         }
236 #endif
237
238         iep_service.enable = true;
239 }
240
241 static void iep_power_off(void)
242 {
243         int total_running;
244
245         if (!iep_service.enable) {
246                 return;
247         }
248
249         IEP_INFO("IEP Power OFF\n");
250
251         total_running = atomic_read(&iep_service.total_running);
252         if (total_running) {
253                 IEP_WARNING("power off when %d task running!!\n", total_running);
254                 mdelay(50);
255                 IEP_WARNING("delay 50 ms for running task\n");
256                 iep_dump();
257         }
258
259 #if defined(CONFIG_IEP_IOMMU)
260         if (iep_service.iommu_dev) {
261                 rockchip_iovmm_deactivate(iep_service.iommu_dev);
262         }
263 #endif
264
265 #ifdef IEP_CLK_ENABLE
266         clk_disable_unprepare(iep_drvdata1->aclk_iep);
267         clk_disable_unprepare(iep_drvdata1->hclk_iep);
268         if (iep_drvdata1->pd_iep)
269                 clk_disable_unprepare(iep_drvdata1->pd_iep);
270 #endif
271
272         wake_unlock(&iep_drvdata1->wake_lock);
273         iep_service.enable = false;
274 }
275
276 static void iep_power_off_work(struct work_struct *work)
277 {
278         if (mutex_trylock(&iep_service.lock) && !iep_drvdata1->dpi_mode) {
279                 IEP_INFO("iep dpi mode inactivity\n");
280                 iep_power_off();
281                 mutex_unlock(&iep_service.lock);
282         } else {
283                 /* Come back later if the device is busy... */
284                 iep_queue_power_off_work();
285         }
286 }
287
288 extern void rk_direct_fb_show(struct fb_info *fbi);
289 extern struct fb_info* rk_get_fb(int fb_id);
290 extern bool rk_fb_poll_wait_frame_complete(void);
291 extern int rk_fb_dpi_open(bool open);
292 extern int rk_fb_dpi_win_sel(int layer_id);
293
294 static void iep_config_lcdc(struct iep_reg *reg)
295 {
296         struct fb_info *fb;
297         int fbi = 0;
298         int fmt = 0;
299
300         fbi = reg->layer == 0 ? 0 : 1;
301
302         rk_fb_dpi_win_sel(fbi);
303
304         fb = rk_get_fb(fbi);
305 #if 1
306         switch (reg->format) {
307         case IEP_FORMAT_ARGB_8888:
308         case IEP_FORMAT_ABGR_8888:
309                 fmt = HAL_PIXEL_FORMAT_RGBA_8888;
310                 fb->var.bits_per_pixel = 32;
311
312                 fb->var.red.length = 8;
313                 fb->var.red.offset = 16;
314                 fb->var.red.msb_right = 0;
315
316                 fb->var.green.length = 8;
317                 fb->var.green.offset = 8;
318                 fb->var.green.msb_right = 0;
319
320                 fb->var.blue.length = 8;
321                 fb->var.blue.offset = 0;
322                 fb->var.blue.msb_right = 0;
323
324                 fb->var.transp.length = 8;
325                 fb->var.transp.offset = 24;
326                 fb->var.transp.msb_right = 0;
327
328                 break;
329         case IEP_FORMAT_BGRA_8888:
330                 fmt = HAL_PIXEL_FORMAT_BGRA_8888;
331                 fb->var.bits_per_pixel = 32;
332                 break;
333         case IEP_FORMAT_RGB_565:
334                 fmt = HAL_PIXEL_FORMAT_RGB_565;
335                 fb->var.bits_per_pixel = 16;
336
337                 fb->var.red.length = 5;
338                 fb->var.red.offset = 11;
339                 fb->var.red.msb_right = 0;
340
341                 fb->var.green.length = 6;
342                 fb->var.green.offset = 5;
343                 fb->var.green.msb_right = 0;
344
345                 fb->var.blue.length = 5;
346                 fb->var.blue.offset = 0;
347                 fb->var.blue.msb_right = 0;
348
349                 break;
350         case IEP_FORMAT_YCbCr_422_SP:
351                 fmt = HAL_PIXEL_FORMAT_YCbCr_422_SP;
352                 fb->var.bits_per_pixel = 16;
353                 break;
354         case IEP_FORMAT_YCbCr_420_SP:
355                 fmt = HAL_PIXEL_FORMAT_YCrCb_NV12;
356                 fb->var.bits_per_pixel = 16;
357                 break;
358         case IEP_FORMAT_YCbCr_422_P:
359         case IEP_FORMAT_YCrCb_422_SP:
360         case IEP_FORMAT_YCrCb_422_P:
361         case IEP_FORMAT_YCrCb_420_SP:
362         case IEP_FORMAT_YCbCr_420_P:
363         case IEP_FORMAT_YCrCb_420_P:
364         case IEP_FORMAT_RGBA_8888:
365         case IEP_FORMAT_BGR_565:
366                 /* unsupported format */
367                 IEP_ERR("unsupported format %d\n", reg->format);
368                 break;
369         default:
370                 ;
371         }
372
373         fb->var.xoffset = 0;
374         fb->var.yoffset = 0;
375         fb->var.xres = reg->act_width;
376         fb->var.yres = reg->act_height;
377         fb->var.xres_virtual = reg->act_width;
378         fb->var.yres_virtual = reg->act_height;
379         fb->var.nonstd = ((reg->off_y & 0xFFF) << 20) +
380                 ((reg->off_x & 0xFFF) << 8) + (fmt & 0xFF);
381         fb->var.grayscale =
382                 ((reg->vir_height & 0xFFF) << 20) +
383                 ((reg->vir_width & 0xFFF) << 8) + 0;/*win0 xsize & ysize*/
384 #endif
385         rk_direct_fb_show(fb);
386 }
387
388 static int iep_switch_dpi(struct iep_reg *reg)
389 {
390         if (reg->dpi_en) {
391                 if (!iep_drvdata1->dpi_mode) {
392                         /* Turn on dpi */
393                         rk_fb_dpi_open(true);
394                         iep_drvdata1->dpi_mode = true;
395                 }
396                 iep_config_lcdc(reg);
397         } else {
398                 if (iep_drvdata1->dpi_mode) {
399                         /* Turn off dpi */
400                         /* wait_lcdc_dpi_close(); */
401                         bool status;
402                         rk_fb_dpi_open(false);
403                         status = rk_fb_poll_wait_frame_complete();
404
405                         iep_drvdata1->dpi_mode = false;
406                         IEP_INFO("%s %d, iep dpi inactivated\n",
407                                  __func__, __LINE__);
408                 }
409         }
410
411         return 0;
412 }
413
414 static void iep_reg_copy_to_hw(struct iep_reg *reg)
415 {
416         int i;
417
418         u32 *pbase = (u32 *)iep_drvdata1->iep_base;
419
420         /* config registers */
421         for (i = 0; i < IEP_CNF_REG_LEN; i++)
422                 pbase[IEP_CNF_REG_BASE + i] = reg->reg[IEP_CNF_REG_BASE + i];
423
424         /* command registers */
425         for (i = 0; i < IEP_CMD_REG_LEN; i++)
426                 pbase[IEP_CMD_REG_BASE + i] = reg->reg[IEP_CMD_REG_BASE + i];
427
428         /* address registers */
429         for (i = 0; i < IEP_ADD_REG_LEN; i++)
430                 pbase[IEP_ADD_REG_BASE + i] = reg->reg[IEP_ADD_REG_BASE + i];
431
432 #if defined(CONFIG_IEP_MMU)
433         /* mmu registers */
434         for (i = 0; i < IEP_MMU_REG_LEN; i++)
435                 pbase[IEP_MMU_REG_BASE + i] = reg->reg[IEP_MMU_REG_BASE + i];
436 #endif
437
438         /* dmac_flush_range(&pbase[0], &pbase[IEP_REG_LEN]); */
439         /* outer_flush_range(virt_to_phys(&pbase[0]),virt_to_phys(&pbase[IEP_REG_LEN])); */
440
441         dsb(sy);
442 }
443
444 /** switch fields order before the next lcdc frame start
445  *  coming */
446 static void iep_switch_fields_order(void)
447 {
448         void *pbase = (void *)iep_drvdata1->iep_base;
449         int mode = iep_get_deinterlace_mode(pbase);
450         struct fb_info *fb;
451
452         switch (mode) {
453         case dein_mode_I4O1B:
454                 iep_set_deinterlace_mode(dein_mode_I4O1T, pbase);
455                 break;
456         case dein_mode_I4O1T:
457                 iep_set_deinterlace_mode(dein_mode_I4O1B, pbase);
458                 break;
459         case dein_mode_I2O1B:
460                 iep_set_deinterlace_mode(dein_mode_I2O1T, pbase);
461                 break;
462         case dein_mode_I2O1T:
463                 iep_set_deinterlace_mode(dein_mode_I2O1B, pbase);
464                 break;
465         default:
466                 ;
467         }
468
469         fb = rk_get_fb(1);
470         rk_direct_fb_show(fb);
471
472         /*iep_switch_input_address(pbase);*/
473 }
474
475 /* Caller must hold iep_service.lock */
476 static void iep_try_set_reg(void)
477 {
478         struct iep_reg *reg;
479
480         mutex_lock(&iep_service.lock);
481
482         if (list_empty(&iep_service.ready)) {
483                 if (!list_empty(&iep_service.waiting)) {
484                         reg = list_entry(iep_service.waiting.next, struct iep_reg, status_link);
485
486                         iep_power_on();
487                         udelay(1);
488
489                         iep_reg_from_wait_to_ready(reg);
490                         atomic_dec(&iep_service.waitcnt);
491
492                         /*iep_soft_rst(iep_drvdata1->iep_base);*/
493
494                         iep_reg_copy_to_hw(reg);
495                 }
496         } else {
497                 if (iep_drvdata1->dpi_mode)
498                         iep_switch_fields_order();
499         }
500
501         mutex_unlock(&iep_service.lock);
502 }
503
504 static void iep_try_start_frm(void)
505 {
506         struct iep_reg *reg;
507
508         mutex_lock(&iep_service.lock);
509
510         if (list_empty(&iep_service.running)) {
511                 if (!list_empty(&iep_service.ready)) {
512                         reg = list_entry(iep_service.ready.next, struct iep_reg, status_link);
513
514                         iep_switch_dpi(reg);
515
516                         iep_reg_from_ready_to_running(reg);
517                         iep_config_frame_end_int_en(iep_drvdata1->iep_base);
518                         iep_config_done(iep_drvdata1->iep_base);
519
520                         /* Start proc */
521                         atomic_inc(&reg->session->task_running);
522                         atomic_inc(&iep_service.total_running);
523                         iep_config_frm_start(iep_drvdata1->iep_base);
524                 }
525         }
526
527         mutex_unlock(&iep_service.lock);
528 }
529
530 static irqreturn_t iep_isr(int irq, void *dev_id)
531 {
532         if (atomic_read(&iep_drvdata1->iep_int) > 0) {
533                 if (iep_service.enable) {
534                         if (list_empty(&iep_service.waiting)) {
535                                 if (iep_drvdata1->dpi_mode) {
536                                         iep_switch_fields_order();
537                                 }
538                         }
539                         iep_del_running_list();
540                 }
541
542                 iep_try_set_reg();
543                 iep_try_start_frm();
544
545                 atomic_dec(&iep_drvdata1->iep_int);
546         }
547
548 #if defined(CONFIG_IEP_MMU)
549         if (atomic_read(&iep_drvdata1->mmu_page_fault) > 0) {
550
551                 if (!list_empty(&iep_service.running)) {
552                         uint32_t va = iep_probe_mmu_page_fault_addr(iep_drvdata1->iep_base);
553                         struct iep_reg *reg = list_entry(iep_service.running.next, struct iep_reg, status_link);
554                         if (0 > rk_mmu_generate_pte_from_va(reg->session, va)) {
555                                 IEP_ERR("Generate PTE from Virtual Address 0x%08x failed\n", va);
556                         } else {
557                                 iep_config_mmu_cmd(iep_drvdata1->iep_base, MMU_ZAP_CACHE);
558                                 iep_config_mmu_cmd(iep_drvdata1->iep_base, MMU_PAGE_FAULT_DONE);
559                         }
560                 } else {
561                         IEP_ERR("Page Fault occur when IEP IDLE\n");
562                 }
563
564                 atomic_dec(&iep_drvdata1->mmu_page_fault);
565         }
566
567         if (atomic_read(&iep_drvdata1->mmu_bus_error) > 0) {
568                 /* reset iep mmu module */
569                 IEP_ERR("Bus Error!!!\n");
570                 iep_config_mmu_cmd(iep_drvdata1->iep_base, MMU_FORCE_RESET);
571                 atomic_dec(&iep_drvdata1->mmu_bus_error);
572         }
573 #endif
574
575         return IRQ_HANDLED;
576 }
577
578 static irqreturn_t iep_irq(int irq,  void *dev_id)
579 {
580         /*clear INT */
581         void *pbase = (void *)iep_drvdata1->iep_base;
582
583 #if defined(CONFIG_IEP_MMU)
584         struct iep_mmu_int_status mmu_int_status;
585
586         mmu_int_status = iep_probe_mmu_int_status(pbase);
587         if (mmu_int_status.page_fault) {
588                 iep_config_mmu_page_fault_int_clr(pbase);
589                 atomic_inc(&iep_drvdata1->mmu_page_fault);
590         }
591
592         if (mmu_int_status.read_bus_error) {
593                 iep_config_mmu_read_bus_error_int_clr(pbase);
594                 atomic_inc(&iep_drvdata1->mmu_bus_error);
595         }
596 #endif
597
598         if (iep_probe_int(pbase)) {
599                 iep_config_frame_end_int_clr(pbase);
600                 atomic_inc(&iep_drvdata1->iep_int);
601         }
602
603         return IRQ_WAKE_THREAD;
604 }
605
606 static void iep_service_session_clear(iep_session *session)
607 {
608         struct iep_reg *reg, *n;
609
610         list_for_each_entry_safe(reg, n, &session->waiting, session_link) {
611                 iep_reg_deinit(reg);
612         }
613
614         list_for_each_entry_safe(reg, n, &session->ready, session_link) {
615                 iep_reg_deinit(reg);
616         }
617
618         list_for_each_entry_safe(reg, n, &session->running, session_link) {
619                 iep_reg_deinit(reg);
620         }
621 }
622
623 static int iep_open(struct inode *inode, struct file *filp)
624 {
625         //DECLARE_WAITQUEUE(wait, current);
626         iep_session *session = (iep_session *)kzalloc(sizeof(iep_session),
627                 GFP_KERNEL);
628         if (NULL == session) {
629                 IEP_ERR("unable to allocate memory for iep_session.\n");
630                 return -ENOMEM;
631         }
632
633         session->pid = current->pid;
634         INIT_LIST_HEAD(&session->waiting);
635         INIT_LIST_HEAD(&session->ready);
636         INIT_LIST_HEAD(&session->running);
637         INIT_LIST_HEAD(&session->list_session);
638         init_waitqueue_head(&session->wait);
639         /*add_wait_queue(&session->wait, wait);*/
640         /* no need to protect */
641         mutex_lock(&iep_service.lock);
642         list_add_tail(&session->list_session, &iep_service.session);
643         mutex_unlock(&iep_service.lock);
644         atomic_set(&session->task_running, 0);
645         atomic_set(&session->num_done, 0);
646
647 #if defined(CONFIG_IEP_MMU)
648         rk_mmu_init_dte_table(session);
649         INIT_LIST_HEAD(&session->pte_list);
650 #endif
651
652         filp->private_data = (void *)session;
653
654         return nonseekable_open(inode, filp);
655 }
656
657 static int iep_release(struct inode *inode, struct file *filp)
658 {
659         int task_running;
660         iep_session *session = (iep_session *)filp->private_data;
661
662         if (NULL == session)
663                 return -EINVAL;
664
665         task_running = atomic_read(&session->task_running);
666
667         if (task_running) {
668                 IEP_ERR("iep_service session %d still "
669                         "has %d task running when closing\n",
670                         session->pid, task_running);
671                 msleep(100);
672                 /*synchronization*/
673         }
674
675         wake_up(&session->wait);
676         mutex_lock(&iep_service.lock);
677         list_del(&session->list_session);
678         iep_service_session_clear(session);
679         kfree(session);
680         mutex_unlock(&iep_service.lock);
681
682         return 0;
683 }
684
685 static unsigned int iep_poll(struct file *filp, poll_table *wait)
686 {
687         int mask = 0;
688         iep_session *session = (iep_session *)filp->private_data;
689         if (NULL == session)
690                 return POLL_ERR;
691         poll_wait(filp, &session->wait, wait);
692         if (atomic_read(&session->done))
693                 mask |= POLL_IN | POLLRDNORM;
694
695         return mask;
696 }
697
698 static int iep_get_result_sync(iep_session *session)
699 {
700         int ret = 0;
701
702         iep_try_start_frm();
703
704         ret = wait_event_timeout(session->wait,
705                 atomic_read(&session->done), IEP_TIMEOUT_DELAY);
706
707         if (unlikely(ret < 0)) {
708                 IEP_ERR("sync pid %d wait task ret %d\n", session->pid, ret);
709                 iep_del_running_list();
710                 ret = ret;
711         } else if (0 == ret) {
712                 IEP_ERR("sync pid %d wait %d task done timeout\n",
713                         session->pid, atomic_read(&session->task_running));
714                 iep_del_running_list_timeout();
715                 iep_try_set_reg();
716                 iep_try_start_frm();
717                 ret = -ETIMEDOUT;
718         }
719
720         return ret;
721 }
722
723 static void iep_get_result_async(iep_session *session)
724 {
725         iep_try_start_frm();
726         return;
727 }
728
729 static long iep_ioctl(struct file *filp, uint32_t cmd, unsigned long arg)
730 {
731         int ret = 0;
732         iep_session *session = (iep_session *)filp->private_data;
733
734         if (NULL == session) {
735                 IEP_ERR("%s [%d] iep thread session is null\n",
736                         __FUNCTION__, __LINE__);
737                 return -EINVAL;
738         }
739
740         mutex_lock(&iep_service.mutex);
741
742         switch (cmd) {
743         case IEP_SET_PARAMETER:
744                 {
745                         struct IEP_MSG *msg;
746                         msg = (struct IEP_MSG *)kzalloc(sizeof(struct IEP_MSG),
747                                 GFP_KERNEL);
748                         if (msg) {
749                                 if (copy_from_user(msg, (struct IEP_MSG *)arg,
750                                                 sizeof(struct IEP_MSG))) {
751                                         IEP_ERR("copy_from_user failure\n");
752                                         ret = -EFAULT;
753                                 }
754                         }
755
756                         if (ret == 0) {
757                                 if (atomic_read(&iep_service.waitcnt) < 10) {
758 #if defined(CONFIG_IEP_IOMMU)
759                                         iep_power_on();
760 #endif
761                                         iep_config(session, msg);
762                                         atomic_inc(&iep_service.waitcnt);
763                                 } else {
764                                         IEP_ERR("iep task queue full\n");
765                                         ret = -EFAULT;
766                                 }
767                         }
768
769                         /** REGISTER CONFIG must accord to Timing When DPI mode
770                          *  enable */
771                         if (!iep_drvdata1->dpi_mode)
772                                 iep_try_set_reg();
773                         kfree(msg);
774                 }
775                 break;
776         case IEP_GET_RESULT_SYNC:
777                 if (0 > iep_get_result_sync(session)) {
778                         ret = -ETIMEDOUT;
779                 }
780                 break;
781         case IEP_GET_RESULT_ASYNC:
782                 iep_get_result_async(session);
783                 break;
784         case IEP_RELEASE_CURRENT_TASK:
785                 iep_del_running_list_timeout();
786                 iep_try_set_reg();
787                 iep_try_start_frm();
788                 break;
789         default:
790                 IEP_ERR("unknown ioctl cmd!\n");
791                 ret = -EINVAL;
792         }
793         mutex_unlock(&iep_service.mutex);
794
795         return ret;
796 }
797
798 #ifdef CONFIG_COMPAT
799 static long compat_iep_ioctl(struct file *filp, uint32_t cmd,
800                              unsigned long arg)
801 {
802         int ret = 0;
803         iep_session *session = (iep_session *)filp->private_data;
804
805         if (NULL == session) {
806                 IEP_ERR("%s [%d] iep thread session is null\n",
807                         __func__, __LINE__);
808                 return -EINVAL;
809         }
810
811         mutex_lock(&iep_service.mutex);
812
813         switch (cmd) {
814         case COMPAT_IEP_SET_PARAMETER:
815                 {
816                         struct IEP_MSG *msg;
817
818                         msg = kzalloc(sizeof(*msg), GFP_KERNEL);
819
820                         if (msg) {
821                                 if (copy_from_user
822                                     (msg, compat_ptr((compat_uptr_t)arg),
823                                      sizeof(struct IEP_MSG))) {
824                                         IEP_ERR("copy_from_user failure\n");
825                                         ret = -EFAULT;
826                                 }
827                         }
828
829                         if (ret == 0) {
830                                 if (atomic_read(&iep_service.waitcnt) < 10) {
831 #if defined(CONFIG_IEP_IOMMU)
832                                         iep_power_on();
833 #endif
834                                         iep_config(session, msg);
835                                         atomic_inc(&iep_service.waitcnt);
836                                 } else {
837                                         IEP_ERR("iep task queue full\n");
838                                         ret = -EFAULT;
839                                 }
840                         }
841
842                         /** REGISTER CONFIG must accord to Timing When DPI mode
843                          *  enable */
844                         if (!iep_drvdata1->dpi_mode)
845                                 iep_try_set_reg();
846                         kfree(msg);
847                 }
848                 break;
849         case COMPAT_IEP_GET_RESULT_SYNC:
850                 if (0 > iep_get_result_sync(session))
851                         ret = -ETIMEDOUT;
852                 break;
853         case COMPAT_IEP_GET_RESULT_ASYNC:
854                 iep_get_result_async(session);
855                 break;
856         case COMPAT_IEP_RELEASE_CURRENT_TASK:
857                 iep_del_running_list_timeout();
858                 iep_try_set_reg();
859                 iep_try_start_frm();
860                 break;
861         default:
862                 IEP_ERR("unknown ioctl cmd!\n");
863                 ret = -EINVAL;
864         }
865         mutex_unlock(&iep_service.mutex);
866
867         return ret;
868 }
869 #endif
870
871 struct file_operations iep_fops = {
872         .owner          = THIS_MODULE,
873         .open           = iep_open,
874         .release        = iep_release,
875         .poll           = iep_poll,
876         .unlocked_ioctl = iep_ioctl,
877 #ifdef CONFIG_COMPAT
878         .compat_ioctl   = compat_iep_ioctl,
879 #endif
880 };
881
882 static struct miscdevice iep_dev = {
883         .minor = IEP_MAJOR,
884         .name  = "iep",
885         .fops  = &iep_fops,
886 };
887
888 #ifdef CONFIG_IEP_IOMMU
889 static struct device* rockchip_get_sysmmu_device_by_compatible(
890         const char *compt)
891 {
892         struct device_node *dn = NULL;
893         struct platform_device *pd = NULL;
894         struct device *ret = NULL;
895
896         dn = of_find_compatible_node(NULL, NULL, compt);
897         if (!dn) {
898                 printk("can't find device node %s \r\n", compt);
899                 return NULL;
900         }
901
902         pd = of_find_device_by_node(dn);
903         if (!pd) {
904                 printk("can't find platform device in device node %s \r\n",
905                         compt);
906                 return  NULL;
907         }
908         ret = &pd->dev;
909
910         return ret;
911
912 }
913 #ifdef CONFIG_IOMMU_API
914 static inline void platform_set_sysmmu(struct device *iommu,
915         struct device *dev)
916 {
917         dev->archdata.iommu = iommu;
918 }
919 #else
920 static inline void platform_set_sysmmu(struct device *iommu,
921         struct device *dev)
922 {
923 }
924 #endif
925
926 static int iep_sysmmu_fault_handler(struct device *dev,
927         enum rk_iommu_inttype itype,
928         unsigned long pgtable_base,
929         unsigned long fault_addr, unsigned int status)
930 {
931         struct iep_reg *reg = list_entry(iep_service.running.next,
932                 struct iep_reg, status_link);
933         if (reg != NULL) {
934                 struct iep_mem_region *mem, *n;
935                 int i = 0;
936                 pr_info("iep, fault addr 0x%08x\n", (u32)fault_addr);
937                 list_for_each_entry_safe(mem, n,
938                         &reg->mem_region_list,
939                         reg_lnk) {
940                         pr_info("iep, mem region [%02d] 0x%08x %ld\n",
941                                 i, (u32)mem->iova, mem->len);
942                         i++;
943                 }
944
945                 pr_alert("iep, page fault occur\n");
946
947                 iep_del_running_list();
948         }
949
950         return 0;
951 }
952 #endif
953
954 #if defined(CONFIG_IEP_IOMMU)
955 extern struct ion_client* rockchip_ion_client_create(const char *name);
956 #endif
957 static int iep_drv_probe(struct platform_device *pdev)
958 {
959         struct iep_drvdata *data;
960         int ret = 0;
961         struct resource *res = NULL;
962 #if defined(CONFIG_IEP_IOMMU)
963         u32 iommu_en = 0;
964         struct device *mmu_dev = NULL;
965         struct device_node *np = pdev->dev.of_node;
966         of_property_read_u32(np, "iommu_enabled", &iommu_en);
967 #endif
968
969         data = (struct iep_drvdata *)devm_kzalloc(&pdev->dev,
970                 sizeof(struct iep_drvdata), GFP_KERNEL);
971         if (NULL == data) {
972                 IEP_ERR("failed to allocate driver data.\n");
973                 return  -ENOMEM;
974         }
975
976         iep_drvdata1 = data;
977
978         INIT_LIST_HEAD(&iep_service.waiting);
979         INIT_LIST_HEAD(&iep_service.ready);
980         INIT_LIST_HEAD(&iep_service.running);
981         INIT_LIST_HEAD(&iep_service.done);
982         INIT_LIST_HEAD(&iep_service.session);
983         atomic_set(&iep_service.waitcnt, 0);
984         mutex_init(&iep_service.lock);
985         atomic_set(&iep_service.total_running, 0);
986         iep_service.enable = false;
987
988 #ifdef IEP_CLK_ENABLE
989         data->pd_iep = devm_clk_get(&pdev->dev, "pd_iep");
990         if (IS_ERR(data->pd_iep)) {
991                 IEP_ERR("failed to find iep power down clock source.\n");
992                 data->pd_iep = NULL;
993         }
994
995         data->aclk_iep = devm_clk_get(&pdev->dev, "aclk_iep");
996         if (IS_ERR(data->aclk_iep)) {
997                 IEP_ERR("failed to find iep axi clock source.\n");
998                 ret = -ENOENT;
999                 goto err_clock;
1000         }
1001
1002         data->hclk_iep = devm_clk_get(&pdev->dev, "hclk_iep");
1003         if (IS_ERR(data->hclk_iep)) {
1004                 IEP_ERR("failed to find iep ahb clock source.\n");
1005                 ret = -ENOENT;
1006                 goto err_clock;
1007         }
1008 #endif
1009
1010         iep_service.enable = false;
1011         INIT_DELAYED_WORK(&data->power_off_work, iep_power_off_work);
1012         wake_lock_init(&data->wake_lock, WAKE_LOCK_SUSPEND, "iep");
1013
1014         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1015
1016         data->iep_base = (void *)devm_ioremap_resource(&pdev->dev, res);
1017         if (data->iep_base == NULL) {
1018                 IEP_ERR("iep ioremap failed\n");
1019                 ret = -ENOENT;
1020                 goto err_ioremap;
1021         }
1022
1023         atomic_set(&data->iep_int, 0);
1024         atomic_set(&data->mmu_page_fault, 0);
1025         atomic_set(&data->mmu_bus_error, 0);
1026
1027         /* get the IRQ */
1028         data->irq0 = platform_get_irq(pdev, 0);
1029         if (data->irq0 <= 0) {
1030                 IEP_ERR("failed to get iep irq resource (%d).\n", data->irq0);
1031                 ret = data->irq0;
1032                 goto err_irq;
1033         }
1034
1035         /* request the IRQ */
1036         ret = devm_request_threaded_irq(&pdev->dev, data->irq0, iep_irq,
1037                 iep_isr, IRQF_SHARED, dev_name(&pdev->dev), pdev);
1038         if (ret) {
1039                 IEP_ERR("iep request_irq failed (%d).\n", ret);
1040                 goto err_irq;
1041         }
1042
1043         mutex_init(&iep_service.mutex);
1044
1045         platform_set_drvdata(pdev, data);
1046
1047         ret = misc_register(&iep_dev);
1048         if (ret) {
1049                 IEP_ERR("cannot register miscdev (%d)\n", ret);
1050                 goto err_misc_register;
1051         }
1052
1053 #if defined(CONFIG_IEP_IOMMU)
1054         iep_service.iommu_dev = NULL;
1055         if (iommu_en) {
1056                 iep_power_on();
1057                 iep_service.ion_client = rockchip_ion_client_create("iep");
1058                 if (IS_ERR(iep_service.ion_client)) {
1059                         IEP_ERR("failed to create ion client for vcodec");
1060                         return PTR_ERR(iep_service.ion_client);
1061                 } else {
1062                         IEP_INFO("iep ion client create success!\n");
1063                 }
1064
1065                 mmu_dev = rockchip_get_sysmmu_device_by_compatible(
1066                         IEP_IOMMU_COMPATIBLE_NAME);
1067
1068                 if (mmu_dev) {
1069                         platform_set_sysmmu(mmu_dev, &pdev->dev);
1070                         rockchip_iovmm_activate(&pdev->dev);
1071                 }
1072
1073                 rockchip_iovmm_set_fault_handler(&pdev->dev,
1074                         iep_sysmmu_fault_handler);
1075
1076                 iep_service.iommu_dev = &pdev->dev;
1077                 iep_power_off();
1078         }
1079 #endif
1080
1081         IEP_INFO("IEP Driver loaded succesfully\n");
1082
1083         return 0;
1084
1085 err_misc_register:
1086         free_irq(data->irq0, pdev);
1087 err_irq:
1088         if (res) {
1089                 if (data->iep_base) {
1090                         devm_ioremap_release(&pdev->dev, res);
1091                 }
1092                 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
1093         }
1094 err_ioremap:
1095         wake_lock_destroy(&data->wake_lock);
1096 #ifdef IEP_CLK_ENABLE
1097 err_clock:
1098 #endif
1099         return ret;
1100 }
1101
1102 static int iep_drv_remove(struct platform_device *pdev)
1103 {
1104         struct iep_drvdata *data = platform_get_drvdata(pdev);
1105         struct resource *res;
1106
1107         wake_lock_destroy(&data->wake_lock);
1108
1109         misc_deregister(&(data->miscdev));
1110         free_irq(data->irq0, &data->miscdev);
1111         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1112         devm_ioremap_release(&pdev->dev, res);
1113         devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
1114
1115 #ifdef IEP_CLK_ENABLE
1116         if (data->aclk_iep)
1117                 devm_clk_put(&pdev->dev, data->aclk_iep);
1118
1119         if (data->hclk_iep)
1120                 devm_clk_put(&pdev->dev, data->hclk_iep);
1121
1122         if (data->pd_iep)
1123                 devm_clk_put(&pdev->dev, data->pd_iep);
1124 #endif
1125
1126         return 0;
1127 }
1128
1129 #if defined(CONFIG_OF)
1130 static const struct of_device_id iep_dt_ids[] = {
1131         { .compatible = "rockchip,iep", },
1132         { },
1133 };
1134 #endif
1135
1136 static struct platform_driver iep_driver = {
1137         .probe          = iep_drv_probe,
1138         .remove         = iep_drv_remove,
1139         .driver         = {
1140                 .owner  = THIS_MODULE,
1141                 .name   = "iep",
1142 #if defined(CONFIG_OF)
1143                 .of_match_table = of_match_ptr(iep_dt_ids),
1144 #endif
1145         },
1146 };
1147
1148 #ifdef CONFIG_PROC_FS
1149 #include <linux/proc_fs.h>
1150 #include <linux/seq_file.h>
1151
1152 static int proc_iep_show(struct seq_file *s, void *v)
1153 {
1154         struct iep_status sts;
1155         //mutex_lock(&iep_service.mutex);
1156         iep_power_on();
1157         seq_printf(s, "\nIEP Modules Status:\n");
1158         sts = iep_get_status(iep_drvdata1->iep_base);
1159         seq_printf(s, "scl_sts: %u, dil_sts %u, wyuv_sts %u, "
1160                       "ryuv_sts %u, wrgb_sts %u, rrgb_sts %u, voi_sts %u\n",
1161                 sts.scl_sts, sts.dil_sts, sts.wyuv_sts, sts.ryuv_sts,
1162                 sts.wrgb_sts, sts.rrgb_sts, sts.voi_sts); {
1163                 int *reg = (int *)iep_drvdata1->iep_base;
1164                 int i;
1165
1166                 /* could not read validate data from address after base+0x40 */
1167                 for (i = 0; i < 0x40; i++) {
1168                         seq_printf(s, "%08x ", reg[i]);
1169
1170                         if ((i + 1) % 4 == 0)
1171                                 seq_printf(s, "\n");
1172                 }
1173
1174                 seq_printf(s, "\n");
1175         }
1176
1177         //mutex_unlock(&iep_service.mutex);
1178
1179         return 0;
1180 }
1181
1182 static int proc_iep_open(struct inode *inode, struct file *file)
1183 {
1184         return single_open(file, proc_iep_show, NULL);
1185 }
1186
1187 static const struct file_operations proc_iep_fops = {
1188         .open           = proc_iep_open,
1189         .read           = seq_read,
1190         .llseek         = seq_lseek,
1191         .release        = single_release,
1192 };
1193
1194 static int __init iep_proc_init(void)
1195 {
1196         proc_create("iep", 0, NULL, &proc_iep_fops);
1197         return 0;
1198 }
1199
1200 static void __exit iep_proc_release(void)
1201 {
1202         remove_proc_entry("iep", NULL);
1203 }
1204 #endif
1205
1206 #ifdef IEP_TEST_CASE
1207 void iep_test_case0(void);
1208 #endif
1209
1210 static int __init iep_init(void)
1211 {
1212         int ret;
1213
1214         if ((ret = platform_driver_register(&iep_driver)) != 0) {
1215                 IEP_ERR("Platform device register failed (%d).\n", ret);
1216                 return ret;
1217         }
1218
1219 #ifdef CONFIG_PROC_FS
1220         iep_proc_init();
1221 #endif
1222
1223         IEP_INFO("Module initialized.\n");
1224
1225 #ifdef IEP_TEST_CASE
1226         iep_test_case0();
1227 #endif
1228
1229         return 0;
1230 }
1231
1232 static void __exit iep_exit(void)
1233 {
1234         IEP_ERR("%s IN\n", __func__);
1235 #ifdef CONFIG_PROC_FS
1236         iep_proc_release();
1237 #endif
1238
1239         iep_power_off();
1240         platform_driver_unregister(&iep_driver);
1241 }
1242
1243 module_init(iep_init);
1244 module_exit(iep_exit);
1245
1246 /* Module information */
1247 MODULE_AUTHOR("ljf@rock-chips.com");
1248 MODULE_DESCRIPTION("Driver for iep device");
1249 MODULE_LICENSE("GPL");
1250
1251 #ifdef IEP_TEST_CASE
1252
1253 #include "yuv420sp_480x480_interlaced.h"
1254 #include "yuv420sp_480x480_deinterlaced_i2o1.h"
1255
1256 //unsigned char tmp_buf[480*480*3/2];
1257
1258 void iep_test_case0(void)
1259 {
1260         struct IEP_MSG msg;
1261         iep_session session;
1262         unsigned int phy_src, phy_dst, phy_tmp;
1263         int i;
1264         int ret = 0;
1265         unsigned char *tmp_buf;
1266
1267         tmp_buf = kmalloc(480 * 480 * 3 / 2, GFP_KERNEL);
1268
1269         session.pid     = current->pid;
1270         INIT_LIST_HEAD(&session.waiting);
1271         INIT_LIST_HEAD(&session.ready);
1272         INIT_LIST_HEAD(&session.running);
1273         INIT_LIST_HEAD(&session.list_session);
1274         init_waitqueue_head(&session.wait);
1275         list_add_tail(&session.list_session, &iep_service.session);
1276         atomic_set(&session.task_running, 0);
1277         atomic_set(&session.num_done, 0);
1278
1279         memset(&msg, 0, sizeof(struct IEP_MSG));
1280         memset(tmp_buf, 0xCC, 480 * 480 * 3 / 2);
1281
1282         dmac_flush_range(&tmp_buf[0], &tmp_buf[480 * 480 * 3 / 2]);
1283         outer_flush_range(virt_to_phys(&tmp_buf[0]), virt_to_phys(&tmp_buf[480 * 480 * 3 / 2]));
1284
1285         phy_src = virt_to_phys(&yuv420sp_480x480_interlaced[0]);
1286         phy_tmp = virt_to_phys(&tmp_buf[0]);
1287         phy_dst = virt_to_phys(&yuv420sp_480x480_deinterlaced_i2o1[0]);
1288
1289         dmac_flush_range(&yuv420sp_480x480_interlaced[0], &yuv420sp_480x480_interlaced[480 * 480 * 3 / 2]);
1290         outer_flush_range(virt_to_phys(&yuv420sp_480x480_interlaced[0]), virt_to_phys(&yuv420sp_480x480_interlaced[480 * 480 * 3 / 2]));
1291
1292         IEP_INFO("*********** IEP MSG GENARATE ************\n");
1293
1294         msg.src.act_w = 480;
1295         msg.src.act_h = 480;
1296         msg.src.x_off = 0;
1297         msg.src.y_off = 0;
1298         msg.src.vir_w = 480;
1299         msg.src.vir_h = 480;
1300         msg.src.format = IEP_FORMAT_YCbCr_420_SP;
1301         msg.src.mem_addr = (uint32_t *)phy_src;
1302         msg.src.uv_addr  = (uint32_t *)(phy_src + 480 * 480);
1303         msg.src.v_addr = 0;
1304
1305         msg.dst.act_w = 480;
1306         msg.dst.act_h = 480;
1307         msg.dst.x_off = 0;
1308         msg.dst.y_off = 0;
1309         msg.dst.vir_w = 480;
1310         msg.dst.vir_h = 480;
1311         msg.dst.format = IEP_FORMAT_YCbCr_420_SP;
1312         msg.dst.mem_addr = (uint32_t *)phy_tmp;
1313         msg.dst.uv_addr = (uint32_t *)(phy_tmp + 480 * 480);
1314         msg.dst.v_addr = 0;
1315
1316         msg.dein_mode = IEP_DEINTERLACE_MODE_I2O1;
1317         msg.field_order = FIELD_ORDER_BOTTOM_FIRST;
1318
1319         IEP_INFO("*********** IEP TEST CASE 0  ************\n");
1320
1321         iep_config(&session, &msg);
1322         iep_try_set_reg();
1323         if (0 > iep_get_result_sync(&session)) {
1324                 IEP_INFO("%s failed, timeout\n", __func__);
1325                 ret = -ETIMEDOUT;
1326         }
1327
1328         mdelay(10);
1329
1330         dmac_flush_range(&tmp_buf[0], &tmp_buf[480 * 480 * 3 / 2]);
1331         outer_flush_range(virt_to_phys(&tmp_buf[0]), virt_to_phys(&tmp_buf[480 * 480 * 3 / 2]));
1332
1333         IEP_INFO("*********** RESULT CHECKING  ************\n");
1334
1335         for (i = 0; i < 480 * 480 * 3 / 2; i++) {
1336                 if (tmp_buf[i] != yuv420sp_480x480_deinterlaced_i2o1[i]) {
1337                         IEP_INFO("diff occur position %d, 0x%02x 0x%02x\n", i, tmp_buf[i], yuv420sp_480x480_deinterlaced_i2o1[i]);
1338
1339                         if (i > 10) {
1340                                 iep_dump();
1341                                 break;
1342                         }
1343                 }
1344         }
1345
1346         if (i == 480 * 480 * 3 / 2)
1347                 IEP_INFO("IEP pass the checking\n");
1348 }
1349
1350 #endif