1 /*
2  * g2d_rcq/g2d_driver/g2d.c
3  *
4  * Copyright (c) 2007-2019 Allwinnertech Co., Ltd.
5  * Author: zhengxiaobin <zhengxiaobin@allwinnertech.com>
6  *
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18 #include <hal_mem.h>
19 #include <hal_cache.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <hal_interrupt.h>
23 #include <init.h>
24 #include <hal_clk.h>
25 #include <hal_reset.h>
26 #include <hal_timer.h>
27 /* #include <melis/standby/standby.h> */
28 
29 #include "g2d_driver_i.h"
30 #include "g2d_top.h"
31 #include "g2d_mixer.h"
32 #include "g2d_rotate.h"
33 
34 #define SUNXI_GIC_START 32
35 
36 #if defined(CONFIG_ARCH_SUN8IW19)
37 #define SUNXI_IRQ_G2D               (SUNXI_GIC_START + 21)
38 #define SUNXI_G2D_START             0x01480000
39 #define SUNXI_G2D_RESET_ID          0
40 #define SUNXI_G2D_CLK_ID            HAL_CLK_PERIPH_G2D
41 #define SUNXI_G2D_CLK_BUS_ID            (hal_clk_id_t)(-1)
42 #define SUNXI_G2D_CLK_MBUS_ID           (hal_clk_id_t)(-1)
43 #define SUNXI_G2D_CLK_PARENT            HAL_CLK_PLL_PERI1
44 
45 #elif defined(CONFIG_SOC_SUN20IW1)
46 #define SUNXI_IRQ_G2D               105
47 #define SUNXI_G2D_START             0x05410000
48 #define RESET_IOMMU
49 #define G2D_IOMMU_MASTER_ID         3
50 #define IOMMU_RESET_REG                         0x02010010
51 #define IOMMU_BGR_REG                           0x020017bc
52 #endif
53 
54 #ifndef SUNXI_G2D_CLK_ID
55 #define SUNXI_G2D_CLK_ID            CLK_G2D
56 #endif
57 #ifndef SUNXI_G2D_RESET_ID
58 #define SUNXI_G2D_RESET_ID          RST_BUS_G2D
59 #endif
60 #ifndef SUNXI_G2D_CLK_BUS_ID
61 #define SUNXI_G2D_CLK_BUS_ID            CLK_BUS_G2D
62 #endif
63 #ifndef SUNXI_G2D_CLK_MBUS_ID
64 #define SUNXI_G2D_CLK_MBUS_ID           CLK_MBUS_G2D
65 #endif
66 #ifndef SUNXI_G2D_CLK_PARENT
67 #define SUNXI_G2D_CLK_PARENT            CLK_PLL_PERIPH0_2X
68 #endif
69 
70 enum g2d_scan_order scan_order;
71 hal_sem_t global_lock;
72 u32 g_time_info;
73 u32 g_func_runtime;
74 __g2d_drv_t g2d_ext_hd;
75 __g2d_info_t para;
76 
77 __u32 dbg_info;
78 
g2d_malloc(__u32 bytes_num,__u32 * phy_addr)79 void *g2d_malloc(__u32 bytes_num, __u32 *phy_addr)
80 {
81 
82     char* vir_addr;
83 
84     if (bytes_num != 0)
85     {
86         vir_addr = hal_malloc_align(bytes_num, CACHELINE_LEN);
87         if(vir_addr!=NULL)
88         {
89             *phy_addr = __va_to_pa((unsigned long)vir_addr);
90             memset((void *)vir_addr, 0, bytes_num);
91             hal_dcache_clean((unsigned long)vir_addr, bytes_num);
92             return vir_addr;
93         }
94         G2D_ERR_MSG("hal_malloc fail!\n");
95         return NULL;
96     }
97     G2D_ERR_MSG("size is zero\n");
98 
99     return NULL;
100 }
101 
g2d_free(void * virt_addr,void * phy_addr,unsigned int size)102 void g2d_free(void *virt_addr, void *phy_addr, unsigned int size)
103 {
104 
105     if (virt_addr == NULL)
106         return;
107     hal_free_align(virt_addr);
108 }
109 
g2d_mutex_lock(hal_sem_t sem)110 int g2d_mutex_lock(hal_sem_t sem)
111 {
112     return hal_sem_wait(sem);
113 }
114 
g2d_mutex_unlock(hal_sem_t sem)115 int g2d_mutex_unlock(hal_sem_t sem)
116 {
117     return hal_sem_post(sem);
118 }
119 
g2d_byte_cal(__u32 format,__u32 * ycnt,__u32 * ucnt,__u32 * vcnt)120 __s32 g2d_byte_cal(__u32 format, __u32 *ycnt, __u32 *ucnt, __u32 *vcnt)
121 {
122     *ycnt = 0;
123     *ucnt = 0;
124     *vcnt = 0;
125     if (format <= G2D_FORMAT_BGRX8888)
126         *ycnt = 4;
127 
128     else if (format <= G2D_FORMAT_BGR888)
129         *ycnt = 3;
130 
131     else if (format <= G2D_FORMAT_BGRA5551)
132         *ycnt = 2;
133 
134     else if (format <= G2D_FORMAT_BGRA1010102)
135         *ycnt = 4;
136 
137     else if (format <= 0x23)
138     {
139         *ycnt = 2;
140     }
141 
142     else if (format <= 0x25)
143     {
144         *ycnt = 1;
145         *ucnt = 2;
146     }
147 
148     else if (format == 0x26)
149     {
150         *ycnt = 1;
151         *ucnt = 1;
152         *vcnt = 1;
153     }
154 
155     else if (format <= 0x29)
156     {
157         *ycnt = 1;
158         *ucnt = 2;
159     }
160 
161     else if (format == 0x2a)
162     {
163         *ycnt = 1;
164         *ucnt = 1;
165         *vcnt = 1;
166     }
167 
168     else if (format <= 0x2d)
169     {
170         *ycnt = 1;
171         *ucnt = 2;
172     }
173 
174     else if (format == 0x2e)
175     {
176         *ycnt = 1;
177         *ucnt = 1;
178         *vcnt = 1;
179     }
180 
181     else if (format == 0x30)
182         *ycnt = 1;
183 
184     else if (format <= 0x36)
185     {
186         *ycnt = 2;
187         *ucnt = 4;
188     }
189 
190     else if (format <= 0x39)
191         *ycnt = 6;
192     return 0;
193 }
194 
195 
196 /**
197  */
cal_align(__u32 width,__u32 align)198 __u32 cal_align(__u32 width, __u32 align)
199 {
200     switch (align)
201     {
202     case 0:
203         return width;
204     case 4:
205         return (width + 3) >> 2 << 2;
206     case 8:
207         return (width + 7) >> 3 << 3;
208     case 16:
209         return (width + 15) >> 4 << 4;
210     case 32:
211         return (width + 31) >> 5 << 5;
212     case 64:
213         return (width + 63) >> 6 << 6;
214     case 128:
215         return (width + 127) >> 7 << 7;
216     default:
217         return (width + 31) >> 5 << 5;
218     }
219 }
220 
221 
g2d_image_check(g2d_image_enh * p_image)222 __s32 g2d_image_check(g2d_image_enh *p_image)
223 {
224     __s32 ret = -EINVAL;
225 
226     if (!p_image)
227     {
228         G2D_ERR_MSG("NUll pointer!\n");
229         goto OUT;
230     }
231 
232     if (((p_image->clip_rect.x < 0) &&
233          ((-p_image->clip_rect.x) > p_image->clip_rect.w)) ||
234         ((p_image->clip_rect.y < 0) &&
235          ((-p_image->clip_rect.y) > p_image->clip_rect.h)) ||
236         ((p_image->clip_rect.x > 0) &&
237          (p_image->clip_rect.x > p_image->width - 1)) ||
238         ((p_image->clip_rect.y > 0) &&
239          (p_image->clip_rect.y > p_image->height - 1)))
240          {
241         G2D_ERR_MSG("Invalid imager parameter setting\n");
242         goto OUT;
243     }
244 
245     if (((p_image->clip_rect.x < 0) &&
246                 ((-p_image->clip_rect.x) <
247                  p_image->clip_rect.w)))
248                  {
249         p_image->clip_rect.w =
250             p_image->clip_rect.w +
251             p_image->clip_rect.x;
252         p_image->clip_rect.x = 0;
253     } else if ((p_image->clip_rect.x +
254                 p_image->clip_rect.w)
255             > p_image->width)
256             {
257         p_image->clip_rect.w =
258             p_image->width -
259             p_image->clip_rect.x;
260     }
261     if (((p_image->clip_rect.y < 0) &&
262                 ((-p_image->clip_rect.y) <
263                  p_image->clip_rect.h)))
264                  {
265         p_image->clip_rect.h =
266             p_image->clip_rect.h +
267             p_image->clip_rect.y;
268         p_image->clip_rect.y = 0;
269     } else if ((p_image->clip_rect.y +
270                 p_image->clip_rect.h)
271             > p_image->height)
272             {
273         p_image->clip_rect.h =
274             p_image->height -
275             p_image->clip_rect.y;
276     }
277 
278     p_image->bpremul = 0;
279     p_image->bbuff = 1;
280     p_image->gamut = G2D_BT709;
281     ret = 0;
282 OUT:
283     return ret;
284 
285 }
286 
g2d_blit_h(g2d_blt_h * para)287 int g2d_blit_h(g2d_blt_h *para)
288 {
289     int ret = -1;
290 
291     ret = g2d_rotate_set_para(&para->src_image_h,
292                 &para->dst_image_h,
293                 para->flag_h);
294 
295     return ret;
296 }
297 
298 #ifdef RESET_IOMMU
299 /**
300  * g2d could cause iommu stop, when iommu stop, g2d could not work, we should reset iommu.
301  */
reset_iommu(void)302 static void reset_iommu(void)
303 {
304     int tmp;
305     int ret;
306     uint32_t regval;
307     *(volatile uint32_t *)(IOMMU_BGR_REG) = 0x1;
308     regval = (*(volatile uint32_t *)(IOMMU_RESET_REG));
309 
310     *(volatile uint32_t *)(IOMMU_RESET_REG) = regval & (~(1 << G2D_IOMMU_MASTER_ID));
311     regval = (*(volatile uint32_t *)(IOMMU_RESET_REG));
312     if (!(regval & ((1 << G2D_IOMMU_MASTER_ID))))
313     {
314         *(volatile uint32_t *)(IOMMU_RESET_REG) = regval | ((1 << G2D_IOMMU_MASTER_ID));
315     }
316     regval = (*(volatile uint32_t *)(IOMMU_RESET_REG));
317 
318     *(volatile uint32_t *)(IOMMU_BGR_REG) = 0;
319     return;
320 }
321 #else
reset_iommu(void)322 static void reset_iommu(void)
323 {
324 }
325 #endif
326 
g2d_wait_cmd_finish(unsigned int timeout)327 int g2d_wait_cmd_finish(unsigned int timeout)
328 {
329     int ret;
330     ret = hal_sem_timedwait(g2d_ext_hd.queue_sem,timeout* 10);
331     if (ret < 0)
332     {
333         reset_iommu();
334         g2d_bsp_reset();
335         G2D_ERR_MSG("G2D irq pending flag timeout\n");
336         g2d_ext_hd.finish_flag = 1;
337         /* wake_up(&g2d_ext_hd.queue); */
338         return -1;
339     }
340     g2d_ext_hd.finish_flag = 0;
341 
342     return 0;
343 }
344 
g2d_handle_irq(int irq,void * dev_id)345 irqreturn_t g2d_handle_irq(int irq, void *dev_id)
346 {
347 #if G2D_MIXER_RCQ_USED == 1
348     if (g2d_top_rcq_task_irq_query())
349     {
350         /* g2d_top_mixer_reset(); */
351         g2d_ext_hd.finish_flag = 1;
352         hal_sem_post(g2d_ext_hd.queue_sem);
353         return IRQ_HANDLED;
354     }
355 #else
356     if (g2d_mixer_irq_query())
357     {
358         /* g2d_top_mixer_reset(); */
359         g2d_ext_hd.finish_flag = 1;
360         hal_sem_post(g2d_ext_hd.queue_sem);
361         return IRQ_HANDLED;
362     }
363 #endif
364     if (g2d_rot_irq_query())
365     {
366         /* g2d_top_rot_reset(); */
367         g2d_ext_hd.finish_flag = 1;
368         hal_sem_post(g2d_ext_hd.queue_sem);
369         return IRQ_HANDLED;
370     }
371 
372     return IRQ_HANDLED;
373 }
374 
g2d_clk_init(__g2d_info_t * info)375 int g2d_clk_init(__g2d_info_t *info)
376 {
377     int i;
378     int ret;
379     hal_reset_id_t rst_id;
380     hal_reset_type_t reset_type = HAL_SUNXI_RESET;
381     hal_clk_type_t clk_type = HAL_SUNXI_CCU;
382     hal_clk_id_t clk_id[G2D_CLK_NUM] = {
383             SUNXI_G2D_CLK_ID,/*note SUNXI_G2D_CLK_ID must be here, please see g2d_clock_enable*/
384             SUNXI_G2D_CLK_BUS_ID,
385             SUNXI_G2D_CLK_MBUS_ID,
386     };
387     info->clk_rate = 300000000; /*300Mhz*/
388     info->reset = hal_reset_control_get(reset_type, SUNXI_G2D_RESET_ID);
389     hal_reset_control_deassert(info->reset);
390     info->clk_parent= hal_clock_get(clk_type,SUNXI_G2D_CLK_PARENT);
391     for(i = 0; i < G2D_CLK_NUM; i++)
392     {
393         if (clk_id[i] != (hal_clk_id_t)-1)
394         {
395             info->clk[i] = hal_clock_get(clk_type, clk_id[i]);
396         }
397     }
398     ret = hal_clk_set_parent(info->clk[0], info->clk_parent);
399     if (ret)
400         G2D_ERR_MSG("set clk:%d's parent:%d fail!\n", info->clk, info->clk_parent);
401     return ret;
402 }
403 
g2d_clk_exit(__g2d_info_t * info)404 int g2d_clk_exit(__g2d_info_t *info)
405 {
406     int i = 0;
407     for(i = 0; i < G2D_CLK_NUM; i++)
408     {
409         hal_clock_put(info->clk[i]);
410     }
411 
412     hal_reset_control_put(info->reset);
413 
414     return 0;
415 }
416 
g2d_clock_enable(__g2d_info_t * info)417 int g2d_clock_enable(__g2d_info_t *info)
418 {
419     int ret = -1;
420     int i = 0;
421     ret = hal_reset_control_deassert(info->reset);
422     if (ret)
423     {
424         G2D_ERR_MSG("deassert rst fail:%d\n", ret);
425         goto OUT;
426     }
427 
428     ret = hal_clock_enable(info->clk_parent);
429     if (ret)
430     {
431         G2D_ERR_MSG("Enable clk parent fail:%d\n", ret);
432         goto OUT;
433     }
434 
435     ret = hal_clk_set_rate(info->clk[0], info->clk_rate);
436     if (ret)
437     {
438         G2D_ERR_MSG("Set clk rate fail:%d:%u!\n", info->clk[0], (unsigned int)info->clk_rate);
439         goto OUT;
440     }
441 
442     for(i = 0; i < G2D_CLK_NUM; i++)
443     {
444         ret = hal_clock_enable(info->clk[i]);
445         if (ret)
446         {
447             G2D_ERR_MSG("Enable clk %d fail:%d\n", i, ret);
448             goto OUT;
449         }
450     }
451 
452 OUT:
453     return ret;
454 }
455 
g2d_clock_disable(__g2d_info_t * info)456 static int g2d_clock_disable(__g2d_info_t *info)
457 {
458     int ret = -1;
459     int i;
460     for(i = 0; i < G2D_CLK_NUM; i++)
461     {
462         ret = hal_clock_disable(info->clk[i]);
463         if (ret)
464         {
465             G2D_ERR_MSG("Disable clk %d fail:%d\n", i, ret);
466             goto OUT;
467         }
468     }
469 
470     ret = hal_reset_control_assert(info->reset);
471     if (ret)
472     {
473         G2D_ERR_MSG("assert rst fail:%d\n", ret);
474         goto OUT;
475     }
476 OUT:
477     return  ret;
478 }
479 
drv_g2d_init(__g2d_info_t * info)480 __s32 drv_g2d_init(__g2d_info_t *info)
481 {
482     int ret;
483     memset(&g2d_ext_hd, 0, sizeof(__g2d_drv_t));
484 
485     g2d_ext_hd.queue_sem = hal_sem_create(0);
486     if (g2d_ext_hd.queue_sem == NULL)
487     {
488         G2D_ERR_MSG("create g2d_ext_hd.queue_sem failed\n");
489         return -1;
490     }
491 
492 
493     g2d_top_set_base((__u32)info->io);
494     g2d_rot_set_base((__u32)info->io);
495     g2d_mixer_idr_init();
496     return 0;
497 }
498 
499 #ifdef CONFIG_STANDBY
500 /**
501  * @desc      This function suspend the g2d
502  * @param     null
503  */
g2d_suspend(void)504 int g2d_suspend(void)
505 {
506     g2d_mutex_lock(para.mutex);
507     if (para.opened)
508     {
509         g2d_clock_disable(&para);
510         g2d_bsp_close();
511     }
512     g2d_mutex_unlock(para.mutex);
513 
514     return 0;
515 }
516 
517 /**
518  * @desc     This function resume the g2d
519  * @param    null
520  */
g2d_resume(void)521 int g2d_resume(void)
522 {
523     g2d_mutex_lock(para.mutex);
524     if (para.opened)
525     {
526         g2d_clock_enable(&para);
527         g2d_bsp_open();
528     }
529     g2d_mutex_unlock(para.mutex);
530 
531     return 0;
532 }
533 
g2d_register_pm_dev_notify(void)534 static void g2d_register_pm_dev_notify(void)
535 {
536     register_pm_dev_notify(g2d_suspend, g2d_resume, NULL);
537 }
538 #else
g2d_register_pm_dev_notify(void)539 static void g2d_register_pm_dev_notify(void)
540 {
541 }
542 #endif
543 
g2d_probe(void)544 int g2d_probe(void)
545 {
546     int ret = 0;
547     __g2d_info_t *info = NULL;
548 
549     info = &para;
550     memset(info, 0, sizeof(__g2d_info_t));
551     info->io = SUNXI_G2D_START;
552 
553     if (request_irq(SUNXI_IRQ_G2D, g2d_handle_irq, 0, "g2d", NULL))
554         {
555         G2D_ERR_MSG("g2d request irq error\n");
556         return -1;
557         }
558     enable_irq(SUNXI_IRQ_G2D);
559 
560     g2d_clk_init(info);
561     drv_g2d_init(info);
562     info->mutex = hal_sem_create(1);
563     global_lock = hal_sem_create(1);
564     if ((info->mutex == NULL) || (global_lock == NULL))
565     {
566         G2D_ERR_MSG("sysfs_create_file fail!\n");
567         ret = -1;
568     }
569 
570     g2d_register_pm_dev_notify();
571 
572     G2D_INFO_MSG("g2d probe finished\n");
573     return ret;
574 }
575 
g2d_remove(void)576 static int g2d_remove(void)
577 {
578     __g2d_info_t *info = &para;
579 
580     g2d_clk_exit(info);
581     g2d_mixer_idr_remove();
582     INFO("Driver unloaded succesfully.\n");
583     return 0;
584 }
585 
g2d_ioctl_mutex_lock(void)586 void g2d_ioctl_mutex_lock(void)
587 {
588 
589     g2d_mutex_lock(para.mutex);
590 
591 }
592 
593 
g2d_ioctl_mutex_unlock(void)594 void g2d_ioctl_mutex_unlock(void)
595 {
596     g2d_mutex_unlock(para.mutex);
597 }
598 
sunxi_g2d_open(void)599 int sunxi_g2d_open(void)
600 {
601     g2d_mutex_lock(para.mutex);
602     g2d_clock_enable(&para);
603     para.user_cnt++;
604     if (para.user_cnt == 1)
605     {
606         para.opened = true;
607         g2d_bsp_open();
608     }
609     g2d_mutex_unlock(para.mutex);
610     return 0;
611 
612 }
613 
sunxi_g2d_close(void)614 int sunxi_g2d_close(void)
615 {
616     g2d_mutex_lock(para.mutex);
617     para.user_cnt--;
618     if (para.user_cnt == 0)
619     {
620         para.opened = false;
621         g2d_bsp_close();
622     }
623     g2d_clock_disable(&para);
624     g2d_mutex_unlock(para.mutex);
625 
626     g2d_mutex_lock(global_lock);
627     scan_order = G2D_SM_TDLR;
628     g2d_mutex_unlock(global_lock);
629 
630     return 0;
631 
632 }
633 
sunxi_g2d_control(int cmd,void * arg)634 int sunxi_g2d_control(int cmd, void *arg)
635 {
636     int ret = -1;
637 
638     g2d_ioctl_mutex_lock();
639 
640     g2d_ext_hd.finish_flag = 0;
641     switch (cmd)
642     {
643     case G2D_CMD_MIXER_TASK:
644         {
645 
646         unsigned long *karg;
647         karg = arg;
648         ret  = mixer_task_process(&para, (struct mixer_para *)karg[0], karg[1]);
649         break;
650         }
651     case G2D_CMD_CREATE_TASK:
652         {
653 
654         unsigned long *karg;
655         karg = arg;
656         ret = create_mixer_task(&para, (struct mixer_para *)karg[0], karg[1]);
657             break;
658         }
659     case G2D_CMD_TASK_APPLY:
660         {
661 
662 
663         unsigned long *karg;
664         karg = arg;
665 
666 
667         struct g2d_mixer_task *p_task = NULL;
668         p_task = g2d_mixer_get_inst((int)karg[0]);
669         ret = p_task->apply(p_task, (struct mixer_para *)karg[1]);
670 
671 
672 
673             break;
674         }
675     case G2D_CMD_TASK_DESTROY:
676         {
677 
678             struct g2d_mixer_task *p_task = NULL;
679             p_task = g2d_mixer_get_inst((int)(unsigned long)arg);
680             ret = p_task->destory(p_task);
681             break;
682         }
683     case G2D_CMD_TASK_GET_PARA:
684         {
685 
686             unsigned long *karg;
687             karg = arg;
688             struct g2d_mixer_task *p_task = NULL;
689 
690             p_task = g2d_mixer_get_inst((int)karg[0]);
691             if(!p_task)
692             {
693                 ret = -EFAULT;
694                 goto err_noput;
695             }
696 
697             karg[1] = (unsigned long)(p_task->p_para);
698             ret = 0;
699             break;
700         }
701     case G2D_CMD_BITBLT_H:
702         {
703         g2d_blt_h blit_para;
704 
705 
706         memcpy(&blit_para, arg, sizeof(g2d_blt_h));
707         if (blit_para.flag_h & 0xff00)
708         {
709             ret = g2d_blit_h(&blit_para);
710         }
711 
712         else {
713             struct mixer_para mixer_blit_para;
714             memset(&mixer_blit_para, 0, sizeof(struct mixer_para));
715             memcpy(&mixer_blit_para.dst_image_h,
716                    &blit_para.dst_image_h, sizeof(g2d_image_enh));
717             memcpy(&mixer_blit_para.src_image_h,
718                    &blit_para.src_image_h, sizeof(g2d_image_enh));
719             mixer_blit_para.flag_h = blit_para.flag_h;
720             mixer_blit_para.op_flag = OP_BITBLT;
721             ret = mixer_task_process(&para, &mixer_blit_para, 1);
722 
723         }
724 
725 
726         break;
727         }
728 
729     case G2D_CMD_LBC_ROT:
730         {
731             g2d_lbc_rot lbc_para;
732             memcpy(&lbc_para, (g2d_lbc_rot *)arg, sizeof(g2d_lbc_rot));
733             ret = g2d_lbc_rot_set_para(&lbc_para);
734             break;
735         }
736 
737     case G2D_CMD_BLD_H:{
738 
739             g2d_bld bld_para;
740             struct mixer_para mixer_bld_para;
741 
742 
743 
744             memcpy(&bld_para,  (g2d_bld *) arg, sizeof(g2d_bld));
745             memset(&mixer_bld_para, 0, sizeof(struct mixer_para));
746             memcpy(&mixer_bld_para.dst_image_h,
747                    &bld_para.dst_image, sizeof(g2d_image_enh));
748             memcpy(&mixer_bld_para.src_image_h,
749                    &bld_para.src_image[0], sizeof(g2d_image_enh));
750             /* ptn use as src  */
751             memcpy(&mixer_bld_para.ptn_image_h,
752                    &bld_para.src_image[1], sizeof(g2d_image_enh));
753             memcpy(&mixer_bld_para.ck_para, &bld_para.ck_para,
754                    sizeof(g2d_ck));
755             mixer_bld_para.bld_cmd = bld_para.bld_cmd;
756             mixer_bld_para.op_flag = OP_BLEND;
757 
758             ret  = mixer_task_process(&para, &mixer_bld_para, 1);
759 
760             break;
761         }
762     case G2D_CMD_FILLRECT_H:{
763 
764         g2d_fillrect_h fill_para;
765         struct mixer_para mixer_fill_para;
766 
767 
768         memcpy(&fill_para, (g2d_fillrect_h *) arg,  sizeof(g2d_fillrect_h));
769         memset(&mixer_fill_para, 0, sizeof(struct mixer_para));
770         memcpy(&mixer_fill_para.dst_image_h,
771                &fill_para.dst_image_h, sizeof(g2d_image_enh));
772         mixer_fill_para.op_flag = OP_FILLRECT;
773 
774         ret  = mixer_task_process(&para, &mixer_fill_para, 1);
775 
776         break;
777     }
778     case G2D_CMD_MASK_H:{
779 
780             g2d_maskblt mask_para;
781             struct mixer_para mixer_mask_para;
782 
783             memcpy(&mask_para, (g2d_maskblt *) arg, sizeof(g2d_maskblt));
784             memset(&mixer_mask_para, 0, sizeof(struct mixer_para));
785             memcpy(&mixer_mask_para.ptn_image_h,
786                    &mask_para.ptn_image_h, sizeof(g2d_image_enh));
787             memcpy(&mixer_mask_para.mask_image_h,
788                    &mask_para.mask_image_h, sizeof(g2d_image_enh));
789             memcpy(&mixer_mask_para.dst_image_h,
790                    &mask_para.dst_image_h, sizeof(g2d_image_enh));
791             memcpy(&mixer_mask_para.src_image_h,
792                    &mask_para.src_image_h, sizeof(g2d_image_enh));
793             mixer_mask_para.back_flag = mask_para.back_flag;
794             mixer_mask_para.fore_flag = mask_para.fore_flag;
795             mixer_mask_para.op_flag = OP_MASK;
796 
797             ret  = mixer_task_process(&para, &mixer_mask_para, 1);
798 
799             break;
800         }
801     case G2D_CMD_INVERTED_ORDER:
802         {
803             if ((enum g2d_scan_order)arg > G2D_SM_DTRL)
804             {
805                 G2D_ERR_MSG("scan mode is err.\n");
806                 ret = -EINVAL;
807                 goto err_noput;
808             }
809 
810             g2d_mutex_lock(global_lock);
811             scan_order = (enum g2d_scan_order)arg;
812             g2d_mutex_unlock(global_lock);
813             ret = 0;
814             break;
815         }
816 
817     default:
818         goto err_noput;
819         break;
820     }
821 
822 err_noput:
823     g2d_ioctl_mutex_unlock();
824 
825     return ret;
826 }
827 
828