vpu: modify for the iommu interface
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / vcodec_service.c
1 \r
2 /* arch/arm/mach-rk29/vpu.c\r
3  *\r
4  * Copyright (C) 2010 ROCKCHIP, Inc.\r
5  * author: chenhengming chm@rock-chips.com\r
6  *\r
7  * This software is licensed under the terms of the GNU General Public\r
8  * License version 2, as published by the Free Software Foundation, and\r
9  * may be copied, distributed, and modified under those terms.\r
10  *\r
11  * This program is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  */\r
17 \r
18 #include <linux/clk.h>\r
19 #include <linux/delay.h>\r
20 #include <linux/init.h>\r
21 #include <linux/interrupt.h>\r
22 #include <linux/io.h>\r
23 #include <linux/kernel.h>\r
24 #include <linux/module.h>\r
25 #include <linux/fs.h>\r
26 #include <linux/ioport.h>\r
27 #include <linux/miscdevice.h>\r
28 #include <linux/mm.h>\r
29 #include <linux/poll.h>\r
30 #include <linux/platform_device.h>\r
31 #include <linux/sched.h>\r
32 #include <linux/slab.h>\r
33 #include <linux/wakelock.h>\r
34 #include <linux/cdev.h>\r
35 #include <linux/of.h>\r
36 #include <linux/of_platform.h>\r
37 #include <linux/rockchip/cpu.h>\r
38 #include <linux/rockchip/cru.h>\r
39 \r
40 #include <asm/cacheflush.h>\r
41 #include <linux/uaccess.h>\r
42 #include <linux/rockchip/grf.h>\r
43 \r
44 #if defined(CONFIG_ION_ROCKCHIP)\r
45 #include <linux/rockchip_ion.h>\r
46 #endif\r
47 \r
48 #if defined(CONFIG_ROCKCHIP_IOMMU) & defined(CONFIG_ION_ROCKCHIP)\r
49 #define CONFIG_VCODEC_MMU\r
50 #endif\r
51 \r
52 #ifdef CONFIG_VCODEC_MMU\r
53 #include <linux/rockchip-iovmm.h>\r
54 #include <linux/dma-buf.h>\r
55 #endif\r
56 \r
57 #ifdef CONFIG_DEBUG_FS\r
58 #include <linux/debugfs.h>\r
59 #endif\r
60 \r
61 #if defined(CONFIG_ARCH_RK319X)\r
62 #include <mach/grf.h>\r
63 #endif\r
64 \r
65 #include "vcodec_service.h"\r
66 \r
67 #define HEVC_TEST_ENABLE        0\r
68 #define HEVC_SIM_ENABLE         0\r
69 #define VCODEC_CLOCK_ENABLE     1\r
70 \r
71 typedef enum {\r
72         VPU_DEC_ID_9190         = 0x6731,\r
73         VPU_ID_8270             = 0x8270,\r
74         VPU_ID_4831             = 0x4831,\r
75         HEVC_ID                 = 0x6867,\r
76 } VPU_HW_ID;\r
77 \r
78 typedef enum {\r
79         VPU_DEC_TYPE_9190       = 0,\r
80         VPU_ENC_TYPE_8270       = 0x100,\r
81         VPU_ENC_TYPE_4831       ,\r
82 } VPU_HW_TYPE_E;\r
83 \r
84 typedef enum VPU_FREQ {\r
85         VPU_FREQ_200M,\r
86         VPU_FREQ_266M,\r
87         VPU_FREQ_300M,\r
88         VPU_FREQ_400M,\r
89         VPU_FREQ_500M,\r
90         VPU_FREQ_600M,\r
91         VPU_FREQ_DEFAULT,\r
92         VPU_FREQ_BUT,\r
93 } VPU_FREQ;\r
94 \r
95 typedef struct {\r
96         VPU_HW_ID               hw_id;\r
97         unsigned long           hw_addr;\r
98         unsigned long           enc_offset;\r
99         unsigned long           enc_reg_num;\r
100         unsigned long           enc_io_size;\r
101         unsigned long           dec_offset;\r
102         unsigned long           dec_reg_num;\r
103         unsigned long           dec_io_size;\r
104 } VPU_HW_INFO_E;\r
105 \r
106 struct extra_info_elem {\r
107         u32 index;\r
108         u32 offset;\r
109 };\r
110 \r
111 #define EXTRA_INFO_MAGIC        0x4C4A46\r
112 \r
113 struct extra_info_for_iommu {\r
114         u32 magic;\r
115         u32 cnt;\r
116         struct extra_info_elem elem[20];\r
117 };\r
118 \r
119 #define VPU_SERVICE_SHOW_TIME                   0\r
120 \r
121 #if VPU_SERVICE_SHOW_TIME\r
122 static struct timeval enc_start, enc_end;\r
123 static struct timeval dec_start, dec_end;\r
124 static struct timeval pp_start,  pp_end;\r
125 #endif\r
126 \r
127 #define MHZ                                     (1000*1000)\r
128 \r
129 #define REG_NUM_9190_DEC                        (60)\r
130 #define REG_NUM_9190_PP                         (41)\r
131 #define REG_NUM_9190_DEC_PP                     (REG_NUM_9190_DEC+REG_NUM_9190_PP)\r
132 \r
133 #define REG_NUM_DEC_PP                          (REG_NUM_9190_DEC+REG_NUM_9190_PP)\r
134 \r
135 #define REG_NUM_ENC_8270                        (96)\r
136 #define REG_SIZE_ENC_8270                       (0x200)\r
137 #define REG_NUM_ENC_4831                        (164)\r
138 #define REG_SIZE_ENC_4831                       (0x400)\r
139 \r
140 #define REG_NUM_HEVC_DEC                        (68)\r
141 \r
142 #define SIZE_REG(reg)                           ((reg)*4)\r
143 \r
144 static VPU_HW_INFO_E vpu_hw_set[] = {\r
145         [0] = {\r
146                 .hw_id          = VPU_ID_8270,\r
147                 .hw_addr        = 0,\r
148                 .enc_offset     = 0x0,\r
149                 .enc_reg_num    = REG_NUM_ENC_8270,\r
150                 .enc_io_size    = REG_NUM_ENC_8270 * 4,\r
151                 .dec_offset     = REG_SIZE_ENC_8270,\r
152                 .dec_reg_num    = REG_NUM_9190_DEC_PP,\r
153                 .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
154         },\r
155         [1] = {\r
156                 .hw_id          = VPU_ID_4831,\r
157                 .hw_addr        = 0,\r
158                 .enc_offset     = 0x0,\r
159                 .enc_reg_num    = REG_NUM_ENC_4831,\r
160                 .enc_io_size    = REG_NUM_ENC_4831 * 4,\r
161                 .dec_offset     = REG_SIZE_ENC_4831,\r
162                 .dec_reg_num    = REG_NUM_9190_DEC_PP,\r
163                 .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
164         },\r
165         [2] = {\r
166                 .hw_id          = HEVC_ID,\r
167                 .hw_addr        = 0,\r
168                 .dec_offset     = 0x0,\r
169                 .dec_reg_num    = REG_NUM_HEVC_DEC,\r
170                 .dec_io_size    = REG_NUM_HEVC_DEC * 4,\r
171         },\r
172         [3] = {\r
173                 .hw_id          = VPU_DEC_ID_9190,\r
174                 .hw_addr        = 0,\r
175                 .enc_offset     = 0x0,\r
176                 .enc_reg_num    = 0,\r
177                 .enc_io_size    = 0,\r
178                 .dec_offset     = REG_SIZE_ENC_4831,\r
179                 .dec_reg_num    = REG_NUM_9190_DEC_PP,\r
180                 .dec_io_size    = REG_NUM_9190_DEC_PP * 4,\r
181         },\r
182 \r
183 };\r
184 \r
185 \r
186 #define DEC_INTERRUPT_REGISTER                  1\r
187 #define PP_INTERRUPT_REGISTER                   60\r
188 #define ENC_INTERRUPT_REGISTER                  1\r
189 \r
190 #define DEC_INTERRUPT_BIT                       0x100\r
191 #define DEC_BUFFER_EMPTY_BIT                    0x4000\r
192 #define PP_INTERRUPT_BIT                        0x100\r
193 #define ENC_INTERRUPT_BIT                       0x1\r
194 \r
195 #define HEVC_DEC_INT_RAW_BIT                    0x200\r
196 #define HEVC_DEC_STR_ERROR_BIT                  0x4000\r
197 #define HEVC_DEC_BUS_ERROR_BIT                  0x2000\r
198 #define HEVC_DEC_BUFFER_EMPTY_BIT               0x10000\r
199 \r
200 #define VPU_REG_EN_ENC                          14\r
201 #define VPU_REG_ENC_GATE                        2\r
202 #define VPU_REG_ENC_GATE_BIT                    (1<<4)\r
203 \r
204 #define VPU_REG_EN_DEC                          1\r
205 #define VPU_REG_DEC_GATE                        2\r
206 #define VPU_REG_DEC_GATE_BIT                    (1<<10)\r
207 #define VPU_REG_EN_PP                           0\r
208 #define VPU_REG_PP_GATE                         1\r
209 #define VPU_REG_PP_GATE_BIT                     (1<<8)\r
210 #define VPU_REG_EN_DEC_PP                       1\r
211 #define VPU_REG_DEC_PP_GATE                     61\r
212 #define VPU_REG_DEC_PP_GATE_BIT                 (1<<8)\r
213 \r
214 #if defined(CONFIG_VCODEC_MMU)\r
215 static u8 addr_tbl_vpu_h264dec[] = {\r
216         12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\r
217         25, 26, 27, 28, 29, 40, 41\r
218 };\r
219 \r
220 static u8 addr_tbl_vpu_vp8dec[] = {\r
221         10,12,13, 14, 18, 19, 27, 40\r
222 };\r
223 \r
224 static u8 addr_tbl_vpu_vp6dec[] = {\r
225         12, 13, 14, 18, 27, 40\r
226 };\r
227 \r
228 static u8 addr_tbl_vpu_vc1dec[] = {\r
229         12, 13, 14, 15, 16, 17, 27, 41\r
230 };\r
231 \r
232 static u8 addr_tbl_vpu_jpegdec[] = {\r
233         12, 40, 66, 67\r
234 };\r
235 \r
236 static u8 addr_tbl_vpu_defaultdec[] = {\r
237         12, 13, 14, 15, 16, 17, 40, 41\r
238 };\r
239 \r
240 static u8 addr_tbl_vpu_enc[] = {\r
241         5, 6, 7, 8, 9, 10, 11, 12, 13, 51\r
242 };\r
243 \r
244 static u8 addr_tbl_hevc_dec[] = {\r
245         4, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,\r
246         21, 22, 23, 24, 42, 43\r
247 };\r
248 #endif\r
249 \r
250 enum VPU_DEC_FMT {\r
251         VPU_DEC_FMT_H264,\r
252         VPU_DEC_FMT_MPEG4,\r
253         VPU_DEC_FMT_H263,\r
254         VPU_DEC_FMT_JPEG,\r
255         VPU_DEC_FMT_VC1,\r
256         VPU_DEC_FMT_MPEG2,\r
257         VPU_DEC_FMT_MPEG1,\r
258         VPU_DEC_FMT_VP6,\r
259         VPU_DEC_FMT_RV,\r
260         VPU_DEC_FMT_VP7,\r
261         VPU_DEC_FMT_VP8,\r
262         VPU_DEC_FMT_AVS,\r
263         VPU_DEC_FMT_SVC,\r
264         VPU_DEC_FMT_VC2,\r
265         VPU_DEC_FMT_MVC,\r
266         VPU_DEC_FMT_THEORA,\r
267         VPU_DEC_FMT_RES\r
268 };\r
269 \r
270 /**\r
271  * struct for process session which connect to vpu\r
272  *\r
273  * @author ChenHengming (2011-5-3)\r
274  */\r
275 typedef struct vpu_session {\r
276         VPU_CLIENT_TYPE         type;\r
277         /* a linked list of data so we can access them for debugging */\r
278         struct list_head        list_session;\r
279         /* a linked list of register data waiting for process */\r
280         struct list_head        waiting;\r
281         /* a linked list of register data in processing */\r
282         struct list_head        running;\r
283         /* a linked list of register data processed */\r
284         struct list_head        done;\r
285         wait_queue_head_t       wait;\r
286         pid_t                   pid;\r
287         atomic_t                task_running;\r
288 } vpu_session;\r
289 \r
290 /**\r
291  * struct for process register set\r
292  *\r
293  * @author ChenHengming (2011-5-4)\r
294  */\r
295 typedef struct vpu_reg {\r
296         VPU_CLIENT_TYPE         type;\r
297         VPU_FREQ                freq;\r
298         vpu_session             *session;\r
299         struct list_head        session_link;           /* link to vpu service session */\r
300         struct list_head        status_link;            /* link to register set list */\r
301         unsigned long           size;\r
302 #if defined(CONFIG_VCODEC_MMU)\r
303         struct list_head        mem_region_list;\r
304 #endif\r
305         unsigned long           *reg;\r
306 } vpu_reg;\r
307 \r
308 typedef struct vpu_device {\r
309         atomic_t                irq_count_codec;\r
310         atomic_t                irq_count_pp;\r
311         unsigned long           iobaseaddr;\r
312         unsigned int            iosize;\r
313         volatile u32            *hwregs;\r
314 } vpu_device;\r
315 \r
316 enum vcodec_device_id {\r
317         VCODEC_DEVICE_ID_VPU,\r
318         VCODEC_DEVICE_ID_HEVC\r
319 };\r
320 \r
321 struct vcodec_mem_region {\r
322         struct list_head srv_lnk;\r
323         struct list_head reg_lnk;\r
324         struct list_head session_lnk;\r
325         unsigned long iova;     /* virtual address for iommu */\r
326         unsigned long len;\r
327         struct ion_handle *hdl;\r
328 };\r
329 \r
330 typedef struct vpu_service_info {\r
331         struct wake_lock        wake_lock;\r
332         struct delayed_work     power_off_work;\r
333         struct mutex            lock;\r
334         struct list_head        waiting;                /* link to link_reg in struct vpu_reg */\r
335         struct list_head        running;                /* link to link_reg in struct vpu_reg */\r
336         struct list_head        done;                   /* link to link_reg in struct vpu_reg */\r
337         struct list_head        session;                /* link to list_session in struct vpu_session */\r
338         atomic_t                total_running;\r
339         bool                    enabled;\r
340         vpu_reg                 *reg_codec;\r
341         vpu_reg                 *reg_pproc;\r
342         vpu_reg                 *reg_resev;\r
343         VPUHwDecConfig_t        dec_config;\r
344         VPUHwEncConfig_t        enc_config;\r
345         VPU_HW_INFO_E           *hw_info;\r
346         unsigned long           reg_size;\r
347         bool                    auto_freq;\r
348         bool                    bug_dec_addr;\r
349         atomic_t                freq_status;\r
350 \r
351         struct clk              *aclk_vcodec;\r
352         struct clk              *hclk_vcodec;\r
353         struct clk              *clk_core;\r
354         struct clk              *clk_cabac;\r
355         struct clk              *pd_video;\r
356 \r
357         int                     irq_dec;\r
358         int                     irq_enc;\r
359 \r
360         vpu_device              enc_dev;\r
361         vpu_device              dec_dev;\r
362 \r
363         struct device           *dev;\r
364 \r
365         struct cdev             cdev;\r
366         dev_t                   dev_t;\r
367         struct class            *cls;\r
368         struct device           *child_dev;\r
369 \r
370         struct dentry           *debugfs_dir;\r
371         struct dentry           *debugfs_file_regs;\r
372 \r
373         u32 irq_status;\r
374 #if defined(CONFIG_VCODEC_MMU)\r
375         struct ion_client       *ion_client;\r
376         struct list_head        mem_region_list;\r
377         struct device           *mmu_dev;\r
378 #endif\r
379 \r
380         enum vcodec_device_id   dev_id;\r
381 \r
382         u32                     reserved_mode;\r
383 \r
384         struct delayed_work     simulate_work;\r
385 } vpu_service_info;\r
386 \r
387 typedef struct vpu_request\r
388 {\r
389         unsigned long *req;\r
390         unsigned long size;\r
391 } vpu_request;\r
392 \r
393 /// global variable\r
394 //static struct clk *pd_video;\r
395 static struct dentry *parent; // debugfs root directory for all device (vpu, hevc).\r
396 /* mutex for selecting operation registers of vpu or hevc */\r
397 static struct mutex g_mode_mutex;\r
398 \r
399 #ifdef CONFIG_DEBUG_FS\r
400 static int vcodec_debugfs_init(void);\r
401 static void vcodec_debugfs_exit(void);\r
402 static struct dentry* vcodec_debugfs_create_device_dir(char *dirname, struct dentry *parent);\r
403 static int debug_vcodec_open(struct inode *inode, struct file *file);\r
404 \r
405 static const struct file_operations debug_vcodec_fops = {\r
406         .open = debug_vcodec_open,\r
407         .read = seq_read,\r
408         .llseek = seq_lseek,\r
409         .release = single_release,\r
410 };\r
411 #endif\r
412 \r
413 #define VPU_POWER_OFF_DELAY             4*HZ /* 4s */\r
414 #define VPU_TIMEOUT_DELAY               2*HZ /* 2s */\r
415 #define VPU_SIMULATE_DELAY              msecs_to_jiffies(15)\r
416 \r
417 #define BIT_VCODEC_SEL_RK3036           (1<<3)\r
418 #define BIT_VCODEC_SEL_RK312X           (1<<15)\r
419 static void vcodec_enter_mode_nolock(enum vcodec_device_id id, u32 *reserved_mode)\r
420 {\r
421         if (cpu_is_rk3036() || cpu_is_rk312x()) {\r
422                 int bits = cpu_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;\r
423                 void __iomem *addr = cpu_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);\r
424                 if (reserved_mode)\r
425                         *reserved_mode = readl_relaxed(addr);\r
426                 if (id == VCODEC_DEVICE_ID_HEVC)\r
427                         writel_relaxed(readl_relaxed(addr) | (bits) | (bits << 16), addr);\r
428                 else\r
429                         writel_relaxed((readl_relaxed(addr) & (~bits)) | (bits << 16), addr);\r
430         }\r
431 }\r
432 \r
433 static void vcodec_exit_mode_nolock(enum vcodec_device_id id, u32 reserved_mode)\r
434 {\r
435         if (cpu_is_rk3036() || cpu_is_rk312x()) {\r
436                 int bits = cpu_is_rk3036() ? BIT_VCODEC_SEL_RK3036 : BIT_VCODEC_SEL_RK312X;\r
437                 void __iomem *addr = cpu_is_rk3036() ? (RK_GRF_VIRT + RK3036_GRF_SOC_CON1) : (RK_GRF_VIRT + RK312X_GRF_SOC_CON1);\r
438                 writel_relaxed(reserved_mode | (bits << 16), addr);\r
439         }\r
440 }\r
441 \r
442 static void vcodec_enter_mode(enum vcodec_device_id id)\r
443 {\r
444         if (cpu_is_rk3036() || cpu_is_rk312x())\r
445                 mutex_lock(&g_mode_mutex);\r
446         vcodec_enter_mode_nolock(id, NULL);\r
447 }\r
448 \r
449 static void vcodec_exit_mode(void)\r
450 {\r
451         if (cpu_is_rk3036() || cpu_is_rk312x())\r
452                 mutex_unlock(&g_mode_mutex);\r
453 }\r
454 \r
455 static int vpu_get_clk(struct vpu_service_info *pservice)\r
456 {\r
457 #if VCODEC_CLOCK_ENABLE\r
458         do {\r
459                 pservice->aclk_vcodec   = devm_clk_get(pservice->dev, "aclk_vcodec");\r
460                 if (IS_ERR(pservice->aclk_vcodec)) {\r
461                         dev_err(pservice->dev, "failed on clk_get aclk_vcodec\n");\r
462                         break;\r
463                 }\r
464 \r
465                 pservice->hclk_vcodec   = devm_clk_get(pservice->dev, "hclk_vcodec");\r
466                 if (IS_ERR(pservice->hclk_vcodec)) {\r
467                         dev_err(pservice->dev, "failed on clk_get hclk_vcodec\n");\r
468                         break;\r
469                 }\r
470 \r
471                 if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
472                         pservice->clk_core = devm_clk_get(pservice->dev, "clk_core");\r
473                         if (IS_ERR(pservice->clk_core)) {\r
474                                 dev_err(pservice->dev, "failed on clk_get clk_core\n");\r
475                                 break;\r
476                         }\r
477 \r
478                         if (!cpu_is_rk3036() && !cpu_is_rk312x()) {\r
479                                 pservice->clk_cabac = devm_clk_get(pservice->dev, "clk_cabac");\r
480                                 if (IS_ERR(pservice->clk_cabac)) {\r
481                                         dev_err(pservice->dev, "failed on clk_get clk_cabac\n");\r
482                                         break;\r
483                                 }\r
484                         } else {\r
485                                 pservice->clk_cabac = NULL;\r
486                         }\r
487 \r
488                         if (!cpu_is_rk3036() && !cpu_is_rk312x()) {\r
489                                 pservice->pd_video = devm_clk_get(pservice->dev, "pd_hevc");\r
490                                 if (IS_ERR(pservice->pd_video)) {\r
491                                         dev_err(pservice->dev, "failed on clk_get pd_hevc\n");\r
492                                         break;\r
493                                 }\r
494                         } else {\r
495                                 pservice->pd_video = NULL;\r
496                         }\r
497                 } else {\r
498                         if (!cpu_is_rk3036() && !cpu_is_rk312x()) {\r
499                                 pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");\r
500                                 if (IS_ERR(pservice->pd_video)) {\r
501                                         dev_err(pservice->dev, "failed on clk_get pd_video\n");\r
502                                         break;\r
503                                 }\r
504                         } else {\r
505                                 pservice->pd_video = NULL;\r
506                         }\r
507                 }\r
508 \r
509                 if (cpu_is_rk312x()) {\r
510                         pservice->pd_video = devm_clk_get(pservice->dev, "pd_video");\r
511                         if (IS_ERR(pservice->pd_video)) {\r
512                                 dev_err(pservice->dev, "failed on clk_get pd_video\n");\r
513                                 break;\r
514                         }\r
515                 }\r
516 \r
517                 return 0;\r
518         } while (0);\r
519 \r
520         return -1;\r
521 #else\r
522         return 0;\r
523 #endif\r
524 }\r
525 \r
526 static void vpu_put_clk(struct vpu_service_info *pservice)\r
527 {\r
528 #if VCODEC_CLOCK_ENABLE\r
529         if (pservice->pd_video) {\r
530                 devm_clk_put(pservice->dev, pservice->pd_video);\r
531         }\r
532 \r
533         if (pservice->aclk_vcodec) {\r
534                 devm_clk_put(pservice->dev, pservice->aclk_vcodec);\r
535         }\r
536 \r
537         if (pservice->hclk_vcodec) {\r
538                 devm_clk_put(pservice->dev, pservice->hclk_vcodec);\r
539         }\r
540 \r
541         if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
542                 if (pservice->clk_core) {\r
543                         devm_clk_put(pservice->dev, pservice->clk_core);\r
544                 }\r
545 \r
546                 if (pservice->clk_cabac) {\r
547                         devm_clk_put(pservice->dev, pservice->clk_cabac);\r
548                 }\r
549         }\r
550 #endif\r
551 }\r
552 \r
553 static void vpu_reset(struct vpu_service_info *pservice)\r
554 {\r
555 #if defined(CONFIG_ARCH_RK29)\r
556         clk_disable(aclk_ddr_vepu);\r
557         cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, true);\r
558         cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, true);\r
559         cru_set_soft_reset(SOFT_RST_VCODEC_AHB_BUS, true);\r
560         cru_set_soft_reset(SOFT_RST_VCODEC_AXI_BUS, true);\r
561         mdelay(10);\r
562         cru_set_soft_reset(SOFT_RST_VCODEC_AXI_BUS, false);\r
563         cru_set_soft_reset(SOFT_RST_VCODEC_AHB_BUS, false);\r
564         cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, false);\r
565         cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, false);\r
566         clk_enable(aclk_ddr_vepu);\r
567 #elif defined(CONFIG_ARCH_RK30)\r
568         pmu_set_idle_request(IDLE_REQ_VIDEO, true);\r
569         cru_set_soft_reset(SOFT_RST_CPU_VCODEC, true);\r
570         cru_set_soft_reset(SOFT_RST_VCODEC_NIU_AXI, true);\r
571         cru_set_soft_reset(SOFT_RST_VCODEC_AHB, true);\r
572         cru_set_soft_reset(SOFT_RST_VCODEC_AXI, true);\r
573         mdelay(1);\r
574         cru_set_soft_reset(SOFT_RST_VCODEC_AXI, false);\r
575         cru_set_soft_reset(SOFT_RST_VCODEC_AHB, false);\r
576         cru_set_soft_reset(SOFT_RST_VCODEC_NIU_AXI, false);\r
577         cru_set_soft_reset(SOFT_RST_CPU_VCODEC, false);\r
578         pmu_set_idle_request(IDLE_REQ_VIDEO, false);\r
579 #endif\r
580         pservice->reg_codec = NULL;\r
581         pservice->reg_pproc = NULL;\r
582         pservice->reg_resev = NULL;\r
583 }\r
584 \r
585 static void reg_deinit(struct vpu_service_info *pservice, vpu_reg *reg);\r
586 static void vpu_service_session_clear(struct vpu_service_info *pservice, vpu_session *session)\r
587 {\r
588         vpu_reg *reg, *n;\r
589         list_for_each_entry_safe(reg, n, &session->waiting, session_link) {\r
590                 reg_deinit(pservice, reg);\r
591         }\r
592         list_for_each_entry_safe(reg, n, &session->running, session_link) {\r
593                 reg_deinit(pservice, reg);\r
594         }\r
595         list_for_each_entry_safe(reg, n, &session->done, session_link) {\r
596                 reg_deinit(pservice, reg);\r
597         }\r
598 }\r
599 \r
600 static void vpu_service_dump(struct vpu_service_info *pservice)\r
601 {\r
602         int running;\r
603         vpu_reg *reg, *reg_tmp;\r
604         vpu_session *session, *session_tmp;\r
605 \r
606         running = atomic_read(&pservice->total_running);\r
607         printk("total_running %d\n", running);\r
608 \r
609         printk("reg_codec 0x%.8x\n", (unsigned int)pservice->reg_codec);\r
610         printk("reg_pproc 0x%.8x\n", (unsigned int)pservice->reg_pproc);\r
611         printk("reg_resev 0x%.8x\n", (unsigned int)pservice->reg_resev);\r
612 \r
613         list_for_each_entry_safe(session, session_tmp, &pservice->session, list_session) {\r
614                 printk("session pid %d type %d:\n", session->pid, session->type);\r
615                 running = atomic_read(&session->task_running);\r
616                 printk("task_running %d\n", running);\r
617                 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {\r
618                         printk("waiting register set 0x%.8x\n", (unsigned int)reg);\r
619                 }\r
620                 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {\r
621                         printk("running register set 0x%.8x\n", (unsigned int)reg);\r
622                 }\r
623                 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {\r
624                         printk("done    register set 0x%.8x\n", (unsigned int)reg);\r
625                 }\r
626         }\r
627 }\r
628 \r
629 static void vpu_service_power_off(struct vpu_service_info *pservice)\r
630 {\r
631         int total_running;\r
632         if (!pservice->enabled)\r
633                 return;\r
634 \r
635         pservice->enabled = false;\r
636         total_running = atomic_read(&pservice->total_running);\r
637         if (total_running) {\r
638                 pr_alert("alert: power off when %d task running!!\n", total_running);\r
639                 mdelay(50);\r
640                 pr_alert("alert: delay 50 ms for running task\n");\r
641                 vpu_service_dump(pservice);\r
642         }\r
643 \r
644 #if defined(CONFIG_VCODEC_MMU)\r
645         if (pservice->mmu_dev)\r
646                 rockchip_iovmm_deactivate(pservice->dev);\r
647 #endif\r
648 \r
649         pr_info("%s: power off...", dev_name(pservice->dev));\r
650         udelay(10);\r
651 #if VCODEC_CLOCK_ENABLE\r
652         if (pservice->pd_video)\r
653                 clk_disable_unprepare(pservice->pd_video);\r
654         if (pservice->hclk_vcodec)\r
655                 clk_disable_unprepare(pservice->hclk_vcodec);\r
656         if (pservice->aclk_vcodec)\r
657                 clk_disable_unprepare(pservice->aclk_vcodec);\r
658         if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
659                 if (pservice->clk_core)\r
660                         clk_disable_unprepare(pservice->clk_core);\r
661                 if (pservice->clk_cabac)\r
662                         clk_disable_unprepare(pservice->clk_cabac);\r
663         }\r
664 #endif\r
665         wake_unlock(&pservice->wake_lock);\r
666         pr_info("done\n");\r
667 }\r
668 \r
669 static inline void vpu_queue_power_off_work(struct vpu_service_info *pservice)\r
670 {\r
671         queue_delayed_work(system_nrt_wq, &pservice->power_off_work, VPU_POWER_OFF_DELAY);\r
672 }\r
673 \r
674 static void vpu_power_off_work(struct work_struct *work_s)\r
675 {\r
676         struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
677         struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, power_off_work);\r
678 \r
679         if (mutex_trylock(&pservice->lock)) {\r
680                 vpu_service_power_off(pservice);\r
681                 mutex_unlock(&pservice->lock);\r
682         } else {\r
683                 /* Come back later if the device is busy... */\r
684                 vpu_queue_power_off_work(pservice);\r
685         }\r
686 }\r
687 \r
688 static void vpu_service_power_on(struct vpu_service_info *pservice)\r
689 {\r
690         static ktime_t last;\r
691         ktime_t now = ktime_get();\r
692         if (ktime_to_ns(ktime_sub(now, last)) > NSEC_PER_SEC) {\r
693                 cancel_delayed_work_sync(&pservice->power_off_work);\r
694                 vpu_queue_power_off_work(pservice);\r
695                 last = now;\r
696         }\r
697         if (pservice->enabled)\r
698                 return ;\r
699 \r
700         pservice->enabled = true;\r
701         printk("%s: power on\n", dev_name(pservice->dev));\r
702 \r
703 #if VCODEC_CLOCK_ENABLE\r
704         if (pservice->aclk_vcodec)\r
705                 clk_prepare_enable(pservice->aclk_vcodec);\r
706 \r
707         if (pservice->hclk_vcodec)\r
708                 clk_prepare_enable(pservice->hclk_vcodec);\r
709 \r
710         if (pservice->dev_id == VCODEC_DEVICE_ID_HEVC) {\r
711                 if (pservice->clk_core)\r
712                         clk_prepare_enable(pservice->clk_core);\r
713         if (pservice->clk_cabac)\r
714                 clk_prepare_enable(pservice->clk_cabac);\r
715         }\r
716 \r
717         if (pservice->pd_video)\r
718                 clk_prepare_enable(pservice->pd_video);\r
719 #endif\r
720 \r
721 #if defined(CONFIG_ARCH_RK319X)\r
722         /// select aclk_vepu as vcodec clock source. \r
723 #define BIT_VCODEC_SEL  (1<<7)\r
724         writel_relaxed(readl_relaxed(RK319X_GRF_BASE + GRF_SOC_CON1) |\r
725                 (BIT_VCODEC_SEL) | (BIT_VCODEC_SEL << 16),\r
726                 RK319X_GRF_BASE + GRF_SOC_CON1);\r
727 #endif\r
728 \r
729         udelay(10);\r
730         wake_lock(&pservice->wake_lock);\r
731 \r
732 #if defined(CONFIG_VCODEC_MMU)\r
733         if (pservice->mmu_dev)\r
734                 rockchip_iovmm_activate(pservice->dev);\r
735 #endif    \r
736 }\r
737 \r
738 static inline bool reg_check_rmvb_wmv(vpu_reg *reg)\r
739 {\r
740         unsigned long type = (reg->reg[3] & 0xF0000000) >> 28;\r
741         return ((type == 8) || (type == 4));\r
742 }\r
743 \r
744 static inline bool reg_check_interlace(vpu_reg *reg)\r
745 {\r
746         unsigned long type = (reg->reg[3] & (1 << 23));\r
747         return (type > 0);\r
748 }\r
749 \r
750 static inline enum VPU_DEC_FMT reg_check_fmt(vpu_reg *reg)\r
751 {\r
752         enum VPU_DEC_FMT type = (enum VPU_DEC_FMT)((reg->reg[3] & 0xF0000000) >> 28);\r
753         return type;\r
754 }\r
755 \r
756 static inline int reg_probe_width(vpu_reg *reg)\r
757 {\r
758         int width_in_mb = reg->reg[4] >> 23;\r
759         return width_in_mb * 16;\r
760 }\r
761 \r
762 #if defined(CONFIG_VCODEC_MMU)\r
763 static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl,\r
764                                 int size, vpu_reg *reg,\r
765                                 struct extra_info_for_iommu *ext_inf)\r
766 {\r
767         int i;\r
768         int usr_fd = 0;\r
769         int offset = 0;\r
770 \r
771         if (tbl == NULL || size <= 0) {\r
772                 dev_err(pservice->dev, "input arguments invalidate\n");\r
773                 return -1;\r
774         }\r
775 \r
776         vpu_service_power_on(pservice);\r
777 \r
778         for (i = 0; i < size; i++) {\r
779                 usr_fd = reg->reg[tbl[i]] & 0x3FF;\r
780 \r
781                 if (tbl[i] == 41 && pservice->hw_info->hw_id != HEVC_ID &&\r
782                     (reg->type == VPU_DEC || reg->type == VPU_DEC_PP))\r
783                         /* special for vpu dec num 41 regitster */\r
784                         offset = reg->reg[tbl[i]] >> 10 << 4;\r
785                 else\r
786                         offset = reg->reg[tbl[i]] >> 10;\r
787 \r
788                 if (usr_fd != 0) {\r
789                         struct ion_handle *hdl;\r
790                         int ret;\r
791                         struct vcodec_mem_region *mem_region;\r
792 \r
793                         hdl = ion_import_dma_buf(pservice->ion_client, usr_fd);\r
794                         if (IS_ERR(hdl)) {\r
795                                 dev_err(pservice->dev, "import dma-buf from fd %d failed, reg[%d]\n", usr_fd, tbl[i]);\r
796                                 return PTR_ERR(hdl);\r
797                         }\r
798 \r
799                         mem_region = kzalloc(sizeof(struct vcodec_mem_region), GFP_KERNEL);\r
800 \r
801                         if (mem_region == NULL) {\r
802                                 dev_err(pservice->dev, "allocate memory for iommu memory region failed\n");\r
803                                 ion_free(pservice->ion_client, hdl);\r
804                                 return -1;\r
805                         }\r
806 \r
807                         mem_region->hdl = hdl;\r
808 \r
809                         vcodec_enter_mode(pservice->dev_id);\r
810                         ret = ion_map_iommu(pservice->dev, pservice->ion_client, mem_region->hdl, &mem_region->iova, &mem_region->len);\r
811                         vcodec_exit_mode();\r
812                         if (ret < 0) {\r
813                                 dev_err(pservice->dev, "ion map iommu failed\n");\r
814                                 kfree(mem_region);\r
815                                 ion_free(pservice->ion_client, hdl);\r
816                                 return ret;\r
817                         }\r
818                         reg->reg[tbl[i]] = mem_region->iova + offset;\r
819                         INIT_LIST_HEAD(&mem_region->reg_lnk);\r
820                         list_add_tail(&mem_region->reg_lnk, &reg->mem_region_list);\r
821                 }\r
822         }\r
823 \r
824         if (ext_inf != NULL && ext_inf->magic == EXTRA_INFO_MAGIC) {\r
825                 for (i=0; i<ext_inf->cnt; i++) {\r
826                         pr_info("reg[%d] + offset %d\n", ext_inf->elem[i].index, ext_inf->elem[i].offset);\r
827                         reg->reg[ext_inf->elem[i].index] += ext_inf->elem[i].offset;\r
828                 }\r
829         }\r
830 \r
831         return 0;\r
832 }\r
833 \r
834 static int vcodec_reg_address_translate(struct vpu_service_info *pservice,\r
835                                         vpu_reg *reg,\r
836                                         struct extra_info_for_iommu *ext_inf)\r
837 {\r
838         VPU_HW_ID hw_id;\r
839         u8 *tbl;\r
840         int size = 0;\r
841 \r
842         hw_id = pservice->hw_info->hw_id;\r
843 \r
844         if (hw_id == HEVC_ID) {\r
845                 tbl = addr_tbl_hevc_dec;\r
846                 size = sizeof(addr_tbl_hevc_dec);\r
847         } else {\r
848                 if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {\r
849                         switch (reg_check_fmt(reg)) {\r
850                         case VPU_DEC_FMT_H264:\r
851                                 {\r
852                                         tbl = addr_tbl_vpu_h264dec;\r
853                                         size = sizeof(addr_tbl_vpu_h264dec);\r
854                                         break;\r
855                                 }\r
856                         case VPU_DEC_FMT_VP8:\r
857                         case VPU_DEC_FMT_VP7:\r
858                                 {\r
859                                         tbl = addr_tbl_vpu_vp8dec;\r
860                                         size = sizeof(addr_tbl_vpu_vp8dec);\r
861                                         break;\r
862                                 }\r
863 \r
864                         case VPU_DEC_FMT_VP6:\r
865                                 {\r
866                                         tbl = addr_tbl_vpu_vp6dec;\r
867                                         size = sizeof(addr_tbl_vpu_vp6dec);\r
868                                         break;\r
869                                 }\r
870                         case VPU_DEC_FMT_VC1:\r
871                                 {\r
872                                         tbl = addr_tbl_vpu_vc1dec;\r
873                                         size = sizeof(addr_tbl_vpu_vc1dec);\r
874                                         break;\r
875                                 }\r
876 \r
877                         case VPU_DEC_FMT_JPEG:\r
878                                 {\r
879                                         tbl = addr_tbl_vpu_jpegdec;\r
880                                         size = sizeof(addr_tbl_vpu_jpegdec);\r
881                                         break;\r
882                                 }\r
883                         default:\r
884                                 tbl = addr_tbl_vpu_defaultdec;\r
885                                 size = sizeof(addr_tbl_vpu_defaultdec);\r
886                                 break;\r
887                         }\r
888                 } else if (reg->type == VPU_ENC) {\r
889                         tbl = addr_tbl_vpu_enc;\r
890                         size = sizeof(addr_tbl_vpu_enc);\r
891                 }\r
892         }\r
893 \r
894         if (size != 0) {\r
895                 return vcodec_bufid_to_iova(pservice, tbl, size, reg, ext_inf);\r
896         } else {\r
897                 return -1;\r
898         }\r
899 }\r
900 #endif\r
901 \r
902 static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session, void __user *src, unsigned long size)\r
903 {\r
904         int extra_size = 0;\r
905         struct extra_info_for_iommu extra_info;\r
906         vpu_reg *reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
907         if (NULL == reg) {\r
908                 pr_err("error: kmalloc fail in reg_init\n");\r
909                 return NULL;\r
910         }\r
911 \r
912         if (size > pservice->reg_size) {\r
913                 /*printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
914                 size = pservice->reg_size;*/\r
915                 extra_size = size - pservice->reg_size;\r
916                 size = pservice->reg_size;\r
917         }\r
918         reg->session = session;\r
919         reg->type = session->type;\r
920         reg->size = size;\r
921         reg->freq = VPU_FREQ_DEFAULT;\r
922         reg->reg = (unsigned long *)&reg[1];\r
923         INIT_LIST_HEAD(&reg->session_link);\r
924         INIT_LIST_HEAD(&reg->status_link);\r
925 \r
926 #if defined(CONFIG_VCODEC_MMU)\r
927         if (pservice->mmu_dev)\r
928                 INIT_LIST_HEAD(&reg->mem_region_list);\r
929 #endif\r
930 \r
931         if (copy_from_user(&reg->reg[0], (void __user *)src, size)) {\r
932                 pr_err("error: copy_from_user failed in reg_init\n");\r
933                 kfree(reg);\r
934                 return NULL;\r
935         }\r
936 \r
937         if (copy_from_user(&extra_info, (u8 *)src + size, extra_size)) {\r
938                 pr_err("error: copy_from_user failed in reg_init\n");\r
939                 kfree(reg);\r
940                 return NULL;\r
941         }\r
942 \r
943 #if defined(CONFIG_VCODEC_MMU)\r
944         if (pservice->mmu_dev && 0 > vcodec_reg_address_translate(pservice, reg, &extra_info)) {\r
945                 pr_err("error: translate reg address failed\n");\r
946                 kfree(reg);\r
947                 return NULL;\r
948         }\r
949 #endif\r
950 \r
951         mutex_lock(&pservice->lock);\r
952         list_add_tail(&reg->status_link, &pservice->waiting);\r
953         list_add_tail(&reg->session_link, &session->waiting);\r
954         mutex_unlock(&pservice->lock);\r
955 \r
956         if (pservice->auto_freq) {\r
957                 if (!soc_is_rk2928g()) {\r
958                         if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {\r
959                                 if (reg_check_rmvb_wmv(reg)) {\r
960                                         reg->freq = VPU_FREQ_200M;\r
961                                 } else if (reg_check_fmt(reg) == VPU_DEC_FMT_H264) {\r
962                                         if (reg_probe_width(reg) > 3200) {\r
963                                                 // raise frequency for 4k avc.\r
964                                                 reg->freq = VPU_FREQ_500M;\r
965                                         }\r
966                                 } else {\r
967                                         if (reg_check_interlace(reg)) {\r
968                                                 reg->freq = VPU_FREQ_400M;\r
969                                         }\r
970                                 }\r
971                         }\r
972                         if (reg->type == VPU_PP) {\r
973                                 reg->freq = VPU_FREQ_400M;\r
974                         }\r
975                 }\r
976         }\r
977 \r
978         return reg;\r
979 }\r
980 \r
981 static void reg_deinit(struct vpu_service_info *pservice, vpu_reg *reg)\r
982 {\r
983 #if defined(CONFIG_VCODEC_MMU)\r
984         struct vcodec_mem_region *mem_region = NULL, *n;\r
985 #endif\r
986 \r
987         list_del_init(&reg->session_link);\r
988         list_del_init(&reg->status_link);\r
989         if (reg == pservice->reg_codec)\r
990                 pservice->reg_codec = NULL;\r
991         if (reg == pservice->reg_pproc)\r
992                 pservice->reg_pproc = NULL;\r
993 \r
994 #if defined(CONFIG_VCODEC_MMU)\r
995         // release memory region attach to this registers table.\r
996         if (pservice->mmu_dev) {\r
997                 list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {\r
998                         /* do not unmap iommu manually,\r
999                            unmap will proccess when memory release */\r
1000                         /*vcodec_enter_mode(pservice->dev_id);\r
1001                         ion_unmap_iommu(pservice->dev,\r
1002                                         pservice->ion_client,\r
1003                                         mem_region->hdl);\r
1004                         vcodec_exit_mode();*/\r
1005                         ion_free(pservice->ion_client, mem_region->hdl);\r
1006                         list_del_init(&mem_region->reg_lnk);\r
1007                         kfree(mem_region);\r
1008                 }\r
1009         }\r
1010 #endif\r
1011 \r
1012         kfree(reg);\r
1013 }\r
1014 \r
1015 static void reg_from_wait_to_run(struct vpu_service_info *pservice, vpu_reg *reg)\r
1016 {\r
1017         list_del_init(&reg->status_link);\r
1018         list_add_tail(&reg->status_link, &pservice->running);\r
1019 \r
1020         list_del_init(&reg->session_link);\r
1021         list_add_tail(&reg->session_link, &reg->session->running);\r
1022 }\r
1023 \r
1024 static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count)\r
1025 {\r
1026         int i;\r
1027         u32 *dst = (u32 *)&reg->reg[0];\r
1028 \r
1029         for (i = 0; i < count; i++)\r
1030                 *dst++ = *src++;\r
1031 }\r
1032 \r
1033 static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg)\r
1034 {\r
1035         int irq_reg = -1;\r
1036         list_del_init(&reg->status_link);\r
1037         list_add_tail(&reg->status_link, &pservice->done);\r
1038 \r
1039         list_del_init(&reg->session_link);\r
1040         list_add_tail(&reg->session_link, &reg->session->done);\r
1041 \r
1042         vcodec_enter_mode(pservice->dev_id);\r
1043         switch (reg->type) {\r
1044         case VPU_ENC : {\r
1045                 pservice->reg_codec = NULL;\r
1046                 reg_copy_from_hw(reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);\r
1047                 irq_reg = ENC_INTERRUPT_REGISTER;\r
1048                 break;\r
1049         }\r
1050         case VPU_DEC : {\r
1051                 int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;\r
1052                 pservice->reg_codec = NULL;\r
1053                 reg_copy_from_hw(reg, pservice->dec_dev.hwregs, reg_len);\r
1054                 irq_reg = DEC_INTERRUPT_REGISTER;\r
1055                 break;\r
1056         }\r
1057         case VPU_PP : {\r
1058                 pservice->reg_pproc = NULL;\r
1059                 reg_copy_from_hw(reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);\r
1060                 pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
1061                 break;\r
1062         }\r
1063         case VPU_DEC_PP : {\r
1064                 pservice->reg_codec = NULL;\r
1065                 pservice->reg_pproc = NULL;\r
1066                 reg_copy_from_hw(reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);\r
1067                 pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
1068                 break;\r
1069         }\r
1070         default : {\r
1071                 pr_err("error: copy reg from hw with unknown type %d\n", reg->type);\r
1072                 break;\r
1073         }\r
1074         }\r
1075         vcodec_exit_mode();\r
1076 \r
1077         if (irq_reg != -1) {\r
1078                 reg->reg[irq_reg] = pservice->irq_status;\r
1079         }\r
1080 \r
1081         atomic_sub(1, &reg->session->task_running);\r
1082         atomic_sub(1, &pservice->total_running);\r
1083         wake_up(&reg->session->wait);\r
1084 }\r
1085 \r
1086 static void vpu_service_set_freq(struct vpu_service_info *pservice, vpu_reg *reg)\r
1087 {\r
1088         VPU_FREQ curr = atomic_read(&pservice->freq_status);\r
1089         if (curr == reg->freq) {\r
1090                 return ;\r
1091         }\r
1092         atomic_set(&pservice->freq_status, reg->freq);\r
1093         switch (reg->freq) {\r
1094         case VPU_FREQ_200M : {\r
1095                 clk_set_rate(pservice->aclk_vcodec, 200*MHZ);\r
1096                 //printk("default: 200M\n");\r
1097         } break;\r
1098         case VPU_FREQ_266M : {\r
1099                 clk_set_rate(pservice->aclk_vcodec, 266*MHZ);\r
1100                 //printk("default: 266M\n");\r
1101         } break;\r
1102         case VPU_FREQ_300M : {\r
1103                 clk_set_rate(pservice->aclk_vcodec, 300*MHZ);\r
1104                 //printk("default: 300M\n");\r
1105         } break;\r
1106         case VPU_FREQ_400M : {\r
1107                 clk_set_rate(pservice->aclk_vcodec, 400*MHZ);\r
1108                 //printk("default: 400M\n");\r
1109         } break;\r
1110         case VPU_FREQ_500M : {\r
1111                 clk_set_rate(pservice->aclk_vcodec, 500*MHZ);\r
1112         } break;\r
1113         case VPU_FREQ_600M : {\r
1114                 clk_set_rate(pservice->aclk_vcodec, 600*MHZ);\r
1115         } break;\r
1116         default : {\r
1117                 if (soc_is_rk2928g()) {\r
1118                         clk_set_rate(pservice->aclk_vcodec, 400*MHZ);\r
1119                 } else {\r
1120                         clk_set_rate(pservice->aclk_vcodec, 300*MHZ);\r
1121                 }\r
1122                 //printk("default: 300M\n");\r
1123         } break;\r
1124         }\r
1125 }\r
1126 \r
1127 #if HEVC_SIM_ENABLE\r
1128 static void simulate_start(struct vpu_service_info *pservice);\r
1129 #endif\r
1130 static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)\r
1131 {\r
1132         int i;\r
1133         u32 *src = (u32 *)&reg->reg[0];\r
1134         atomic_add(1, &pservice->total_running);\r
1135         atomic_add(1, &reg->session->task_running);\r
1136         if (pservice->auto_freq) {\r
1137                 vpu_service_set_freq(pservice, reg);\r
1138         }\r
1139 \r
1140         vcodec_enter_mode(pservice->dev_id);\r
1141 \r
1142         switch (reg->type) {\r
1143         case VPU_ENC : {\r
1144                 int enc_count = pservice->hw_info->enc_reg_num;\r
1145                 u32 *dst = (u32 *)pservice->enc_dev.hwregs;\r
1146 \r
1147                 pservice->reg_codec = reg;\r
1148 \r
1149                 dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC] & 0x6;\r
1150 \r
1151                 for (i = 0; i < VPU_REG_EN_ENC; i++)\r
1152                         dst[i] = src[i];\r
1153 \r
1154                 for (i = VPU_REG_EN_ENC + 1; i < enc_count; i++)\r
1155                         dst[i] = src[i];\r
1156 \r
1157                 dsb();\r
1158 \r
1159                 dst[VPU_REG_ENC_GATE] = src[VPU_REG_ENC_GATE] | VPU_REG_ENC_GATE_BIT;\r
1160                 dst[VPU_REG_EN_ENC]   = src[VPU_REG_EN_ENC];\r
1161 \r
1162 #if VPU_SERVICE_SHOW_TIME\r
1163                 do_gettimeofday(&enc_start);\r
1164 #endif\r
1165 \r
1166         } break;\r
1167         case VPU_DEC : {\r
1168                 u32 *dst = (u32 *)pservice->dec_dev.hwregs;\r
1169 \r
1170                 pservice->reg_codec = reg;\r
1171 \r
1172                 if (pservice->hw_info->hw_id != HEVC_ID) {\r
1173                         for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)\r
1174                                 dst[i] = src[i];\r
1175                 } else {\r
1176                         for (i = REG_NUM_HEVC_DEC - 1; i > VPU_REG_EN_DEC; i--) {\r
1177                                 dst[i] = src[i];\r
1178                         }\r
1179                 }\r
1180 \r
1181                 dsb();\r
1182 \r
1183                 if (pservice->hw_info->hw_id != HEVC_ID) {\r
1184                         dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;\r
1185                         dst[VPU_REG_EN_DEC]   = src[VPU_REG_EN_DEC];\r
1186                 } else {\r
1187                         dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];\r
1188                 }\r
1189 \r
1190                 dsb();\r
1191                 dmb();\r
1192 \r
1193 #if VPU_SERVICE_SHOW_TIME\r
1194                 do_gettimeofday(&dec_start);\r
1195 #endif\r
1196 \r
1197         } break;\r
1198         case VPU_PP : {\r
1199                 u32 *dst = (u32 *)pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER;\r
1200                 pservice->reg_pproc = reg;\r
1201 \r
1202                 dst[VPU_REG_PP_GATE] = src[VPU_REG_PP_GATE] | VPU_REG_PP_GATE_BIT;\r
1203 \r
1204                 for (i = VPU_REG_PP_GATE + 1; i < REG_NUM_9190_PP; i++)\r
1205                         dst[i] = src[i];\r
1206 \r
1207                 dsb();\r
1208 \r
1209                 dst[VPU_REG_EN_PP] = src[VPU_REG_EN_PP];\r
1210 \r
1211 #if VPU_SERVICE_SHOW_TIME\r
1212                 do_gettimeofday(&pp_start);\r
1213 #endif\r
1214 \r
1215         } break;\r
1216         case VPU_DEC_PP : {\r
1217                 u32 *dst = (u32 *)pservice->dec_dev.hwregs;\r
1218                 pservice->reg_codec = reg;\r
1219                 pservice->reg_pproc = reg;\r
1220 \r
1221                 for (i = VPU_REG_EN_DEC_PP + 1; i < REG_NUM_9190_DEC_PP; i++)\r
1222                         dst[i] = src[i];\r
1223 \r
1224                 dst[VPU_REG_EN_DEC_PP]   = src[VPU_REG_EN_DEC_PP] | 0x2;\r
1225                 dsb();\r
1226 \r
1227                 dst[VPU_REG_DEC_PP_GATE] = src[VPU_REG_DEC_PP_GATE] | VPU_REG_PP_GATE_BIT;\r
1228                 dst[VPU_REG_DEC_GATE]    = src[VPU_REG_DEC_GATE]    | VPU_REG_DEC_GATE_BIT;\r
1229                 dst[VPU_REG_EN_DEC]      = src[VPU_REG_EN_DEC];\r
1230 \r
1231 #if VPU_SERVICE_SHOW_TIME\r
1232                 do_gettimeofday(&dec_start);\r
1233 #endif\r
1234 \r
1235         } break;\r
1236         default : {\r
1237                 pr_err("error: unsupport session type %d", reg->type);\r
1238                 atomic_sub(1, &pservice->total_running);\r
1239                 atomic_sub(1, &reg->session->task_running);\r
1240                 break;\r
1241         }\r
1242         }\r
1243 \r
1244         vcodec_exit_mode();\r
1245 \r
1246 #if HEVC_SIM_ENABLE\r
1247         if (pservice->hw_info->hw_id == HEVC_ID) {\r
1248                 simulate_start(pservice);\r
1249         }\r
1250 #endif\r
1251 }\r
1252 \r
1253 static void try_set_reg(struct vpu_service_info *pservice)\r
1254 {\r
1255         // first get reg from reg list\r
1256         if (!list_empty(&pservice->waiting)) {\r
1257                 int can_set = 0;\r
1258                 vpu_reg *reg = list_entry(pservice->waiting.next, vpu_reg, status_link);\r
1259 \r
1260                 vpu_service_power_on(pservice);\r
1261 \r
1262                 switch (reg->type) {\r
1263                 case VPU_ENC : {\r
1264                         if ((NULL == pservice->reg_codec) &&  (NULL == pservice->reg_pproc))\r
1265                                 can_set = 1;\r
1266                 } break;\r
1267                 case VPU_DEC : {\r
1268                         if (NULL == pservice->reg_codec)\r
1269                                 can_set = 1;\r
1270                         if (pservice->auto_freq && (NULL != pservice->reg_pproc)) {\r
1271                                 can_set = 0;\r
1272                         }\r
1273                 } break;\r
1274                 case VPU_PP : {\r
1275                         if (NULL == pservice->reg_codec) {\r
1276                                 if (NULL == pservice->reg_pproc)\r
1277                                         can_set = 1;\r
1278                         } else {\r
1279                                 if ((VPU_DEC == pservice->reg_codec->type) && (NULL == pservice->reg_pproc))\r
1280                                         can_set = 1;\r
1281                                 // can not charge frequency when vpu is working\r
1282                                 if (pservice->auto_freq) {\r
1283                                         can_set = 0;\r
1284                                 }\r
1285                         }\r
1286                 } break;\r
1287                 case VPU_DEC_PP : {\r
1288                         if ((NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc))\r
1289                                 can_set = 1;\r
1290                         } break;\r
1291                 default : {\r
1292                         printk("undefined reg type %d\n", reg->type);\r
1293                 } break;\r
1294                 }\r
1295                 if (can_set) {\r
1296                         reg_from_wait_to_run(pservice, reg);\r
1297                         reg_copy_to_hw(pservice, reg);\r
1298                 }\r
1299         }\r
1300 }\r
1301 \r
1302 static int return_reg(struct vpu_service_info *pservice, vpu_reg *reg, u32 __user *dst)\r
1303 {\r
1304         int ret = 0;\r
1305         switch (reg->type) {\r
1306         case VPU_ENC : {\r
1307                 if (copy_to_user(dst, &reg->reg[0], pservice->hw_info->enc_io_size))\r
1308                         ret = -EFAULT;\r
1309                 break;\r
1310         }\r
1311         case VPU_DEC : {\r
1312                 int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;\r
1313                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(reg_len)))\r
1314                         ret = -EFAULT;\r
1315                 break;\r
1316         }\r
1317         case VPU_PP : {\r
1318                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_PP)))\r
1319                         ret = -EFAULT;\r
1320                 break;\r
1321         }\r
1322         case VPU_DEC_PP : {\r
1323                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_DEC_PP)))\r
1324                         ret = -EFAULT;\r
1325                 break;\r
1326         }\r
1327         default : {\r
1328                 ret = -EFAULT;\r
1329                 pr_err("error: copy reg to user with unknown type %d\n", reg->type);\r
1330                 break;\r
1331         }\r
1332         }\r
1333         reg_deinit(pservice, reg);\r
1334         return ret;\r
1335 }\r
1336 \r
1337 static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)\r
1338 {\r
1339     struct vpu_service_info *pservice = container_of(filp->f_dentry->d_inode->i_cdev, struct vpu_service_info, cdev);\r
1340         vpu_session *session = (vpu_session *)filp->private_data;\r
1341         if (NULL == session) {\r
1342                 return -EINVAL;\r
1343         }\r
1344 \r
1345         switch (cmd) {\r
1346         case VPU_IOC_SET_CLIENT_TYPE : {\r
1347                 session->type = (VPU_CLIENT_TYPE)arg;\r
1348                 break;\r
1349         }\r
1350         case VPU_IOC_GET_HW_FUSE_STATUS : {\r
1351                 vpu_request req;\r
1352                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {\r
1353                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_from_user failed\n");\r
1354                         return -EFAULT;\r
1355                 } else {\r
1356                         if (VPU_ENC != session->type) {\r
1357                                 if (copy_to_user((void __user *)req.req, &pservice->dec_config, sizeof(VPUHwDecConfig_t))) {\r
1358                                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);\r
1359                                         return -EFAULT;\r
1360                                 }\r
1361                         } else {\r
1362                                 if (copy_to_user((void __user *)req.req, &pservice->enc_config, sizeof(VPUHwEncConfig_t))) {\r
1363                                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);\r
1364                                         return -EFAULT;\r
1365                                 }\r
1366                         }\r
1367                 }\r
1368 \r
1369                 break;\r
1370         }\r
1371         case VPU_IOC_SET_REG : {\r
1372                 vpu_request req;\r
1373                 vpu_reg *reg;\r
1374                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {\r
1375                         pr_err("error: VPU_IOC_SET_REG copy_from_user failed\n");\r
1376                         return -EFAULT;\r
1377                 }\r
1378                 reg = reg_init(pservice, session, (void __user *)req.req, req.size);\r
1379                 if (NULL == reg) {\r
1380                         return -EFAULT;\r
1381                 } else {\r
1382                         mutex_lock(&pservice->lock);\r
1383                         try_set_reg(pservice);\r
1384                         mutex_unlock(&pservice->lock);\r
1385                 }\r
1386 \r
1387                 break;\r
1388         }\r
1389         case VPU_IOC_GET_REG : {\r
1390                 vpu_request req;\r
1391                 vpu_reg *reg;\r
1392                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {\r
1393                         pr_err("error: VPU_IOC_GET_REG copy_from_user failed\n");\r
1394                         return -EFAULT;\r
1395                 } else {\r
1396                         int ret = wait_event_timeout(session->wait, !list_empty(&session->done), VPU_TIMEOUT_DELAY);\r
1397                         if (!list_empty(&session->done)) {\r
1398                                 if (ret < 0) {\r
1399                                         pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session->pid, ret);\r
1400                                 }\r
1401                                 ret = 0;\r
1402                         } else {\r
1403                                 if (unlikely(ret < 0)) {\r
1404                                         pr_err("error: pid %d wait task ret %d\n", session->pid, ret);\r
1405                                 } else if (0 == ret) {\r
1406                                         pr_err("error: pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));\r
1407                                         ret = -ETIMEDOUT;\r
1408                                 }\r
1409                         }\r
1410                         if (ret < 0) {\r
1411                                 int task_running = atomic_read(&session->task_running);\r
1412                                 mutex_lock(&pservice->lock);\r
1413                                 vpu_service_dump(pservice);\r
1414                                 if (task_running) {\r
1415                                         atomic_set(&session->task_running, 0);\r
1416                                         atomic_sub(task_running, &pservice->total_running);\r
1417                                         printk("%d task is running but not return, reset hardware...", task_running);\r
1418                                         vpu_reset(pservice);\r
1419                                         printk("done\n");\r
1420                                 }\r
1421                                 vpu_service_session_clear(pservice, session);\r
1422                                 mutex_unlock(&pservice->lock);\r
1423                                 return ret;\r
1424                         }\r
1425                 }\r
1426                 mutex_lock(&pservice->lock);\r
1427                 reg = list_entry(session->done.next, vpu_reg, session_link);\r
1428                 return_reg(pservice, reg, (u32 __user *)req.req);\r
1429                 mutex_unlock(&pservice->lock);\r
1430                 break;\r
1431         }\r
1432         case VPU_IOC_PROBE_IOMMU_STATUS: {\r
1433                 int iommu_enable = 0;\r
1434 \r
1435 #if defined(CONFIG_VCODEC_MMU)\r
1436                 iommu_enable = pservice->mmu_dev ? 1 : 0;\r
1437 #endif\r
1438 \r
1439                 if (copy_to_user((void __user *)arg, &iommu_enable, sizeof(int))) {\r
1440                         pr_err("error: VPU_IOC_PROBE_IOMMU_STATUS copy_to_user failed\n");\r
1441                         return -EFAULT;\r
1442                 }\r
1443                 break;\r
1444         }\r
1445         default : {\r
1446                 pr_err("error: unknow vpu service ioctl cmd %x\n", cmd);\r
1447                 break;\r
1448         }\r
1449         }\r
1450 \r
1451         return 0;\r
1452 }\r
1453 \r
1454 static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)\r
1455 {\r
1456         int ret = -EINVAL, i = 0;\r
1457         volatile u32 *tmp = (volatile u32 *)ioremap_nocache(hw_addr, 0x4);\r
1458         u32 enc_id = *tmp;\r
1459 \r
1460 #if HEVC_SIM_ENABLE\r
1461         /// temporary, hevc driver test.\r
1462         if (strncmp(dev_name(p->dev), "hevc_service", strlen("hevc_service")) == 0) {\r
1463                 p->hw_info = &vpu_hw_set[2];\r
1464                 return 0;\r
1465         }\r
1466 #endif\r
1467         enc_id = (enc_id >> 16) & 0xFFFF;\r
1468         pr_info("checking hw id %x\n", enc_id);\r
1469         p->hw_info = NULL;\r
1470         for (i = 0; i < ARRAY_SIZE(vpu_hw_set); i++) {\r
1471                 if (enc_id == vpu_hw_set[i].hw_id) {\r
1472                         p->hw_info = &vpu_hw_set[i];\r
1473                         ret = 0;\r
1474                         break;\r
1475                 }\r
1476         }\r
1477         iounmap((void *)tmp);\r
1478         return ret;\r
1479 }\r
1480 \r
1481 static int vpu_service_open(struct inode *inode, struct file *filp)\r
1482 {\r
1483         struct vpu_service_info *pservice = container_of(inode->i_cdev, struct vpu_service_info, cdev);\r
1484         vpu_session *session = (vpu_session *)kmalloc(sizeof(vpu_session), GFP_KERNEL);\r
1485         if (NULL == session) {\r
1486                 pr_err("error: unable to allocate memory for vpu_session.");\r
1487                 return -ENOMEM;\r
1488         }\r
1489 \r
1490         session->type   = VPU_TYPE_BUTT;\r
1491         session->pid    = current->pid;\r
1492         INIT_LIST_HEAD(&session->waiting);\r
1493         INIT_LIST_HEAD(&session->running);\r
1494         INIT_LIST_HEAD(&session->done);\r
1495         INIT_LIST_HEAD(&session->list_session);\r
1496         init_waitqueue_head(&session->wait);\r
1497         atomic_set(&session->task_running, 0);\r
1498         mutex_lock(&pservice->lock);\r
1499         list_add_tail(&session->list_session, &pservice->session);\r
1500         filp->private_data = (void *)session;\r
1501         mutex_unlock(&pservice->lock);\r
1502 \r
1503         pr_debug("dev opened\n");\r
1504         return nonseekable_open(inode, filp);\r
1505 }\r
1506 \r
1507 static int vpu_service_release(struct inode *inode, struct file *filp)\r
1508 {\r
1509         struct vpu_service_info *pservice = container_of(inode->i_cdev, struct vpu_service_info, cdev);\r
1510         int task_running;\r
1511         vpu_session *session = (vpu_session *)filp->private_data;\r
1512         if (NULL == session)\r
1513                 return -EINVAL;\r
1514 \r
1515         task_running = atomic_read(&session->task_running);\r
1516         if (task_running) {\r
1517                 pr_err("error: vpu_service session %d still has %d task running when closing\n", session->pid, task_running);\r
1518                 msleep(50);\r
1519         }\r
1520         wake_up(&session->wait);\r
1521 \r
1522         mutex_lock(&pservice->lock);\r
1523         /* remove this filp from the asynchronusly notified filp's */\r
1524         list_del_init(&session->list_session);\r
1525         vpu_service_session_clear(pservice, session);\r
1526         kfree(session);\r
1527         filp->private_data = NULL;\r
1528         mutex_unlock(&pservice->lock);\r
1529 \r
1530         pr_debug("dev closed\n");\r
1531         return 0;\r
1532 }\r
1533 \r
1534 static const struct file_operations vpu_service_fops = {\r
1535         .unlocked_ioctl = vpu_service_ioctl,\r
1536         .open           = vpu_service_open,\r
1537         .release        = vpu_service_release,\r
1538         //.fasync       = vpu_service_fasync,\r
1539 };\r
1540 \r
1541 static irqreturn_t vdpu_irq(int irq, void *dev_id);\r
1542 static irqreturn_t vdpu_isr(int irq, void *dev_id);\r
1543 static irqreturn_t vepu_irq(int irq, void *dev_id);\r
1544 static irqreturn_t vepu_isr(int irq, void *dev_id);\r
1545 static void get_hw_info(struct vpu_service_info *pservice);\r
1546 \r
1547 #if HEVC_SIM_ENABLE\r
1548 static void simulate_work(struct work_struct *work_s)\r
1549 {\r
1550         struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
1551         struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, simulate_work);\r
1552         vpu_device *dev = &pservice->dec_dev;\r
1553 \r
1554         if (!list_empty(&pservice->running)) {\r
1555                 atomic_add(1, &dev->irq_count_codec);\r
1556                 vdpu_isr(0, (void*)pservice);\r
1557         } else {\r
1558                 //simulate_start(pservice);\r
1559                 pr_err("empty running queue\n");\r
1560         }\r
1561 }\r
1562 \r
1563 static void simulate_init(struct vpu_service_info *pservice)\r
1564 {\r
1565         INIT_DELAYED_WORK(&pservice->simulate_work, simulate_work);\r
1566 }\r
1567 \r
1568 static void simulate_start(struct vpu_service_info *pservice)\r
1569 {\r
1570         cancel_delayed_work_sync(&pservice->power_off_work);\r
1571         queue_delayed_work(system_nrt_wq, &pservice->simulate_work, VPU_SIMULATE_DELAY);\r
1572 }\r
1573 #endif\r
1574 \r
1575 #ifdef CONFIG_VCODEC_MMU\r
1576 static struct device *rockchip_get_sysmmu_device_by_compatible(const char *compt)\r
1577 {\r
1578         struct device_node *dn = NULL;\r
1579         struct platform_device *pd = NULL;\r
1580         struct device *ret = NULL ;\r
1581 \r
1582         dn = of_find_compatible_node(NULL,NULL,compt);\r
1583         if(!dn) {\r
1584                 printk("can't find device node %s \r\n",compt);\r
1585                 return NULL;\r
1586         }\r
1587         \r
1588         pd = of_find_device_by_node(dn);\r
1589         if(!pd) {       \r
1590                 printk("can't find platform device in device node %s \r\n",compt);\r
1591                 return  NULL;\r
1592         }\r
1593         ret = &pd->dev;\r
1594         \r
1595         return ret;\r
1596 \r
1597 }\r
1598 #ifdef CONFIG_IOMMU_API\r
1599 static inline void platform_set_sysmmu(struct device *iommu, struct device *dev)\r
1600 {\r
1601         dev->archdata.iommu = iommu;\r
1602 }\r
1603 #else\r
1604 static inline void platform_set_sysmmu(struct device *iommu, struct device *dev)\r
1605 {\r
1606 }\r
1607 #endif\r
1608 #endif\r
1609 \r
1610 #if HEVC_TEST_ENABLE\r
1611 static int hevc_test_case0(vpu_service_info *pservice);\r
1612 #endif\r
1613 #if defined(CONFIG_ION_ROCKCHIP)\r
1614 extern struct ion_client *rockchip_ion_client_create(const char * name);\r
1615 #endif\r
1616 static int vcodec_probe(struct platform_device *pdev)\r
1617 {\r
1618         int ret = 0;\r
1619         struct resource *res = NULL;\r
1620         struct device *dev = &pdev->dev;\r
1621         void __iomem *regs = NULL;\r
1622         struct device_node *np = pdev->dev.of_node;\r
1623         struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);\r
1624         char *prop = (char*)dev_name(dev);\r
1625 #if defined(CONFIG_VCODEC_MMU)\r
1626         u32 iommu_en = 0;\r
1627         char mmu_dev_dts_name[40];\r
1628         of_property_read_u32(np, "iommu_enabled", &iommu_en);\r
1629 #endif\r
1630 \r
1631         pr_info("probe device %s\n", dev_name(dev));\r
1632 \r
1633         of_property_read_string(np, "name", (const char**)&prop);\r
1634         dev_set_name(dev, prop);\r
1635 \r
1636         if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
1637                 pservice->dev_id = VCODEC_DEVICE_ID_HEVC;\r
1638         } else if (strcmp(dev_name(dev), "vpu_service") == 0) {\r
1639                 pservice->dev_id = VCODEC_DEVICE_ID_VPU;\r
1640         } else {\r
1641                 dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));\r
1642                 return -1;\r
1643         }\r
1644 \r
1645         mutex_init(&g_mode_mutex);\r
1646         vcodec_enter_mode(pservice->dev_id);\r
1647 \r
1648         wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");\r
1649         INIT_LIST_HEAD(&pservice->waiting);\r
1650         INIT_LIST_HEAD(&pservice->running);\r
1651         INIT_LIST_HEAD(&pservice->done);\r
1652         INIT_LIST_HEAD(&pservice->session);\r
1653         mutex_init(&pservice->lock);\r
1654         pservice->reg_codec     = NULL;\r
1655         pservice->reg_pproc     = NULL;\r
1656         atomic_set(&pservice->total_running, 0);\r
1657         pservice->enabled = false;\r
1658 #if defined(CONFIG_VCODEC_MMU)\r
1659         pservice->mmu_dev = NULL;\r
1660 #endif\r
1661         pservice->dev = dev;\r
1662 \r
1663         if (0 > vpu_get_clk(pservice))\r
1664                 goto err;\r
1665 \r
1666         INIT_DELAYED_WORK(&pservice->power_off_work, vpu_power_off_work);\r
1667 \r
1668         vpu_service_power_on(pservice);\r
1669 \r
1670         mdelay(1);\r
1671 \r
1672         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1673 \r
1674         res->flags &= ~IORESOURCE_CACHEABLE;\r
1675 \r
1676         regs = devm_ioremap_resource(pservice->dev, res);\r
1677         if (IS_ERR(regs)) {\r
1678                 ret = PTR_ERR(regs);\r
1679                 goto err;\r
1680         }\r
1681 \r
1682         {\r
1683                 u32 offset = res->start;\r
1684                 if (cpu_is_rk3036()) {\r
1685                         if (pservice->dev_id == VCODEC_DEVICE_ID_VPU)\r
1686                                 offset += 0x400;\r
1687                 }\r
1688                 ret = vpu_service_check_hw(pservice, offset);\r
1689                 if (ret < 0) {\r
1690                         pr_err("error: hw info check faild\n");\r
1691                         goto err;\r
1692                 }\r
1693         }\r
1694 \r
1695         /// define regs address.\r
1696         pservice->dec_dev.iobaseaddr = res->start + pservice->hw_info->dec_offset;\r
1697         pservice->dec_dev.iosize     = pservice->hw_info->dec_io_size;\r
1698 \r
1699         pservice->dec_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->dec_offset);\r
1700 \r
1701         pservice->reg_size   = pservice->dec_dev.iosize;\r
1702 \r
1703         if (pservice->hw_info->hw_id != HEVC_ID && !cpu_is_rk3036()) {\r
1704                 pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;\r
1705                 pservice->enc_dev.iosize     = pservice->hw_info->enc_io_size;\r
1706 \r
1707                 pservice->reg_size = pservice->reg_size > pservice->enc_dev.iosize ? pservice->reg_size : pservice->enc_dev.iosize;\r
1708 \r
1709                 pservice->enc_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->enc_offset);\r
1710 \r
1711                 pservice->irq_enc = platform_get_irq_byname(pdev, "irq_enc");\r
1712                 if (pservice->irq_enc < 0) {\r
1713                         dev_err(pservice->dev, "cannot find IRQ encoder\n");\r
1714                         ret = -ENXIO;\r
1715                         goto err;\r
1716                 }\r
1717 \r
1718                 ret = devm_request_threaded_irq(pservice->dev, pservice->irq_enc, vepu_irq, vepu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
1719                 if (ret) {\r
1720                         dev_err(pservice->dev, "error: can't request vepu irq %d\n", pservice->irq_enc);\r
1721                         goto err;\r
1722                 }\r
1723         }\r
1724 \r
1725         pservice->irq_dec = platform_get_irq_byname(pdev, "irq_dec");\r
1726         if (pservice->irq_dec < 0) {\r
1727                 dev_err(pservice->dev, "cannot find IRQ decoder\n");\r
1728                 ret = -ENXIO;\r
1729                 goto err;\r
1730         }\r
1731 \r
1732         /* get the IRQ line */\r
1733         ret = devm_request_threaded_irq(pservice->dev, pservice->irq_dec, vdpu_irq, vdpu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
1734         if (ret) {\r
1735                 dev_err(pservice->dev, "error: can't request vdpu irq %d\n", pservice->irq_dec);\r
1736                 goto err;\r
1737         }\r
1738 \r
1739         atomic_set(&pservice->dec_dev.irq_count_codec, 0);\r
1740         atomic_set(&pservice->dec_dev.irq_count_pp, 0);\r
1741         atomic_set(&pservice->enc_dev.irq_count_codec, 0);\r
1742         atomic_set(&pservice->enc_dev.irq_count_pp, 0);\r
1743 \r
1744         /// create device\r
1745         ret = alloc_chrdev_region(&pservice->dev_t, 0, 1, dev_name(dev));\r
1746         if (ret) {\r
1747                 dev_err(dev, "alloc dev_t failed\n");\r
1748                 goto err;\r
1749         }\r
1750 \r
1751         cdev_init(&pservice->cdev, &vpu_service_fops);\r
1752 \r
1753         pservice->cdev.owner = THIS_MODULE;\r
1754         pservice->cdev.ops = &vpu_service_fops;\r
1755 \r
1756         ret = cdev_add(&pservice->cdev, pservice->dev_t, 1);\r
1757 \r
1758         if (ret) {\r
1759                 dev_err(dev, "add dev_t failed\n");\r
1760                 goto err;\r
1761         }\r
1762 \r
1763         pservice->cls = class_create(THIS_MODULE, dev_name(dev));\r
1764 \r
1765         if (IS_ERR(pservice->cls)) {\r
1766                 ret = PTR_ERR(pservice->cls);\r
1767                 dev_err(dev, "class_create err:%d\n", ret);\r
1768                 goto err;\r
1769         }\r
1770 \r
1771         pservice->child_dev = device_create(pservice->cls, dev, pservice->dev_t, NULL, dev_name(dev));\r
1772 \r
1773         platform_set_drvdata(pdev, pservice);\r
1774 \r
1775         get_hw_info(pservice);\r
1776 \r
1777 \r
1778 #ifdef CONFIG_DEBUG_FS\r
1779         pservice->debugfs_dir = vcodec_debugfs_create_device_dir((char*)dev_name(dev), parent);\r
1780         if (pservice->debugfs_dir == NULL)\r
1781                 pr_err("create debugfs dir %s failed\n", dev_name(dev));\r
1782 \r
1783         pservice->debugfs_file_regs =\r
1784                 debugfs_create_file("regs", 0664,\r
1785                                     pservice->debugfs_dir, pservice,\r
1786                                     &debug_vcodec_fops);\r
1787 #endif\r
1788 \r
1789 #if defined(CONFIG_VCODEC_MMU)\r
1790         if (iommu_en) {\r
1791                 pservice->ion_client = rockchip_ion_client_create("vpu");\r
1792                 if (IS_ERR(pservice->ion_client)) {\r
1793                         dev_err(&pdev->dev, "failed to create ion client for vcodec");\r
1794                         return PTR_ERR(pservice->ion_client);\r
1795                 } else {\r
1796                         dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
1797                 }\r
1798 \r
1799                 if (pservice->hw_info->hw_id == HEVC_ID)\r
1800                         sprintf(mmu_dev_dts_name, HEVC_IOMMU_COMPATIBLE_NAME);\r
1801                 else\r
1802                         sprintf(mmu_dev_dts_name, VPU_IOMMU_COMPATIBLE_NAME);\r
1803 \r
1804                 pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);\r
1805 \r
1806                 if (pservice->mmu_dev) {\r
1807                         platform_set_sysmmu(pservice->mmu_dev, pservice->dev);\r
1808                         rockchip_iovmm_activate(pservice->dev);\r
1809                 }\r
1810         }\r
1811 #endif\r
1812 \r
1813         vpu_service_power_off(pservice);\r
1814         vcodec_exit_mode();\r
1815 \r
1816         pr_info("init success\n");\r
1817 \r
1818 #if HEVC_SIM_ENABLE\r
1819         if (pservice->hw_info->hw_id == HEVC_ID)\r
1820                 simulate_init(pservice);\r
1821 #endif\r
1822 \r
1823 #if HEVC_TEST_ENABLE\r
1824         hevc_test_case0(pservice);\r
1825 #endif\r
1826 \r
1827         return 0;\r
1828 \r
1829 err:\r
1830         pr_info("init failed\n");\r
1831         vpu_service_power_off(pservice);\r
1832         vpu_put_clk(pservice);\r
1833         wake_lock_destroy(&pservice->wake_lock);\r
1834 \r
1835         if (res)\r
1836                 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
1837         if (pservice->irq_enc > 0)\r
1838                 free_irq(pservice->irq_enc, (void *)pservice);\r
1839         if (pservice->irq_dec > 0)\r
1840                 free_irq(pservice->irq_dec, (void *)pservice);\r
1841 \r
1842         if (pservice->child_dev) {\r
1843                 device_destroy(pservice->cls, pservice->dev_t);\r
1844                 cdev_del(&pservice->cdev);\r
1845                 unregister_chrdev_region(pservice->dev_t, 1);\r
1846         }\r
1847 \r
1848         if (pservice->cls)\r
1849                 class_destroy(pservice->cls);\r
1850 \r
1851         return ret;\r
1852 }\r
1853 \r
1854 static int vcodec_remove(struct platform_device *pdev)\r
1855 {\r
1856         struct vpu_service_info *pservice = platform_get_drvdata(pdev);\r
1857         struct resource *res;\r
1858 \r
1859         device_destroy(pservice->cls, pservice->dev_t);\r
1860         class_destroy(pservice->cls);\r
1861         cdev_del(&pservice->cdev);\r
1862         unregister_chrdev_region(pservice->dev_t, 1);\r
1863 \r
1864         free_irq(pservice->irq_enc, (void *)&pservice->enc_dev);\r
1865         free_irq(pservice->irq_dec, (void *)&pservice->dec_dev);\r
1866         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1867         devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
1868         vpu_put_clk(pservice);\r
1869         wake_lock_destroy(&pservice->wake_lock);\r
1870 \r
1871 #ifdef CONFIG_DEBUG_FS\r
1872         debugfs_remove(pservice->debugfs_file_regs);\r
1873         debugfs_remove(pservice->debugfs_dir);\r
1874 #endif\r
1875 \r
1876         return 0;\r
1877 }\r
1878 \r
1879 #if defined(CONFIG_OF)\r
1880 static const struct of_device_id vcodec_service_dt_ids[] = {\r
1881         {.compatible = "vpu_service",},\r
1882         {.compatible = "rockchip,hevc_service",},\r
1883         {},\r
1884 };\r
1885 #endif\r
1886 \r
1887 static struct platform_driver vcodec_driver = {\r
1888         .probe = vcodec_probe,\r
1889         .remove = vcodec_remove,\r
1890         .driver = {\r
1891                 .name = "vcodec",\r
1892                 .owner = THIS_MODULE,\r
1893 #if defined(CONFIG_OF)\r
1894                 .of_match_table = of_match_ptr(vcodec_service_dt_ids),\r
1895 #endif\r
1896         },\r
1897 };\r
1898 \r
1899 static void get_hw_info(struct vpu_service_info *pservice)\r
1900 {\r
1901         VPUHwDecConfig_t *dec = &pservice->dec_config;\r
1902         VPUHwEncConfig_t *enc = &pservice->enc_config;\r
1903 \r
1904         if (pservice->dev_id == VCODEC_DEVICE_ID_VPU) {\r
1905                 u32 configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG0];\r
1906                 u32 asicID      = pservice->dec_dev.hwregs[0];\r
1907 \r
1908                 dec->h264Support    = (configReg >> DWL_H264_E) & 0x3U;\r
1909                 dec->jpegSupport    = (configReg >> DWL_JPEG_E) & 0x01U;\r
1910                 if (dec->jpegSupport && ((configReg >> DWL_PJPEG_E) & 0x01U))\r
1911                         dec->jpegSupport = JPEG_PROGRESSIVE;\r
1912                 dec->mpeg4Support   = (configReg >> DWL_MPEG4_E) & 0x3U;\r
1913                 dec->vc1Support     = (configReg >> DWL_VC1_E) & 0x3U;\r
1914                 dec->mpeg2Support   = (configReg >> DWL_MPEG2_E) & 0x01U;\r
1915                 dec->sorensonSparkSupport = (configReg >> DWL_SORENSONSPARK_E) & 0x01U;\r
1916                 dec->refBufSupport  = (configReg >> DWL_REF_BUFF_E) & 0x01U;\r
1917                 dec->vp6Support     = (configReg >> DWL_VP6_E) & 0x01U;\r
1918 \r
1919                 if (soc_is_rk3190() || soc_is_rk3288())\r
1920                         dec->maxDecPicWidth = 4096;\r
1921                 else if (cpu_is_rk3036() || cpu_is_rk312x())\r
1922                         dec->maxDecPicWidth = 1920;\r
1923                 else\r
1924                         dec->maxDecPicWidth = configReg & 0x07FFU;\r
1925 \r
1926                 /* 2nd Config register */\r
1927                 configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG1];\r
1928                 if (dec->refBufSupport) {\r
1929                         if ((configReg >> DWL_REF_BUFF_ILACE_E) & 0x01U)\r
1930                                 dec->refBufSupport |= 2;\r
1931                         if ((configReg >> DWL_REF_BUFF_DOUBLE_E) & 0x01U)\r
1932                                 dec->refBufSupport |= 4;\r
1933                 }\r
1934                 dec->customMpeg4Support = (configReg >> DWL_MPEG4_CUSTOM_E) & 0x01U;\r
1935                 dec->vp7Support     = (configReg >> DWL_VP7_E) & 0x01U;\r
1936                 dec->vp8Support     = (configReg >> DWL_VP8_E) & 0x01U;\r
1937                 dec->avsSupport     = (configReg >> DWL_AVS_E) & 0x01U;\r
1938 \r
1939                 /* JPEG xtensions */\r
1940                 if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U))\r
1941                         dec->jpegESupport = (configReg >> DWL_JPEG_EXT_E) & 0x01U;\r
1942                 else\r
1943                         dec->jpegESupport = JPEG_EXT_NOT_SUPPORTED;\r
1944 \r
1945                 if (((asicID >> 16) >= 0x9170U) || ((asicID >> 16) == 0x6731U) )\r
1946                         dec->rvSupport = (configReg >> DWL_RV_E) & 0x03U;\r
1947                 else\r
1948                         dec->rvSupport = RV_NOT_SUPPORTED;\r
1949                 dec->mvcSupport = (configReg >> DWL_MVC_E) & 0x03U;\r
1950 \r
1951                 if (dec->refBufSupport && (asicID >> 16) == 0x6731U )\r
1952                         dec->refBufSupport |= 8; /* enable HW support for offset */\r
1953 \r
1954                 /// invalidate fuse register value in rk319x vpu and following.\r
1955                 if (!soc_is_rk3190() && !soc_is_rk3288() && !cpu_is_rk3036() && !cpu_is_rk312x()) {\r
1956                         VPUHwFuseStatus_t hwFuseSts;\r
1957                         /* Decoder fuse configuration */\r
1958                         u32 fuseReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
1959 \r
1960                         hwFuseSts.h264SupportFuse = (fuseReg >> DWL_H264_FUSE_E) & 0x01U;\r
1961                         hwFuseSts.mpeg4SupportFuse = (fuseReg >> DWL_MPEG4_FUSE_E) & 0x01U;\r
1962                         hwFuseSts.mpeg2SupportFuse = (fuseReg >> DWL_MPEG2_FUSE_E) & 0x01U;\r
1963                         hwFuseSts.sorensonSparkSupportFuse = (fuseReg >> DWL_SORENSONSPARK_FUSE_E) & 0x01U;\r
1964                         hwFuseSts.jpegSupportFuse = (fuseReg >> DWL_JPEG_FUSE_E) & 0x01U;\r
1965                         hwFuseSts.vp6SupportFuse = (fuseReg >> DWL_VP6_FUSE_E) & 0x01U;\r
1966                         hwFuseSts.vc1SupportFuse = (fuseReg >> DWL_VC1_FUSE_E) & 0x01U;\r
1967                         hwFuseSts.jpegProgSupportFuse = (fuseReg >> DWL_PJPEG_FUSE_E) & 0x01U;\r
1968                         hwFuseSts.rvSupportFuse = (fuseReg >> DWL_RV_FUSE_E) & 0x01U;\r
1969                         hwFuseSts.avsSupportFuse = (fuseReg >> DWL_AVS_FUSE_E) & 0x01U;\r
1970                         hwFuseSts.vp7SupportFuse = (fuseReg >> DWL_VP7_FUSE_E) & 0x01U;\r
1971                         hwFuseSts.vp8SupportFuse = (fuseReg >> DWL_VP8_FUSE_E) & 0x01U;\r
1972                         hwFuseSts.customMpeg4SupportFuse = (fuseReg >> DWL_CUSTOM_MPEG4_FUSE_E) & 0x01U;\r
1973                         hwFuseSts.mvcSupportFuse = (fuseReg >> DWL_MVC_FUSE_E) & 0x01U;\r
1974 \r
1975                         /* check max. decoder output width */\r
1976 \r
1977                         if (fuseReg & 0x8000U)\r
1978                                 hwFuseSts.maxDecPicWidthFuse = 1920;\r
1979                         else if (fuseReg & 0x4000U)\r
1980                                 hwFuseSts.maxDecPicWidthFuse = 1280;\r
1981                         else if (fuseReg & 0x2000U)\r
1982                                 hwFuseSts.maxDecPicWidthFuse = 720;\r
1983                         else if (fuseReg & 0x1000U)\r
1984                                 hwFuseSts.maxDecPicWidthFuse = 352;\r
1985                         else    /* remove warning */\r
1986                                 hwFuseSts.maxDecPicWidthFuse = 352;\r
1987 \r
1988                         hwFuseSts.refBufSupportFuse = (fuseReg >> DWL_REF_BUFF_FUSE_E) & 0x01U;\r
1989 \r
1990                         /* Pp configuration */\r
1991                         configReg = pservice->dec_dev.hwregs[VPU_PP_HW_SYNTH_CFG];\r
1992 \r
1993                         if ((configReg >> DWL_PP_E) & 0x01U) {\r
1994                                 dec->ppSupport = 1;\r
1995                                 dec->maxPpOutPicWidth = configReg & 0x07FFU;\r
1996                                 /*pHwCfg->ppConfig = (configReg >> DWL_CFG_E) & 0x0FU; */\r
1997                                 dec->ppConfig = configReg;\r
1998                         } else {\r
1999                                 dec->ppSupport = 0;\r
2000                                 dec->maxPpOutPicWidth = 0;\r
2001                                 dec->ppConfig = 0;\r
2002                         }\r
2003 \r
2004                         /* check the HW versio */\r
2005                         if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {\r
2006                                 /* Pp configuration */\r
2007                                 configReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
2008                                 if ((configReg >> DWL_PP_E) & 0x01U) {\r
2009                                         /* Pp fuse configuration */\r
2010                                         u32 fuseRegPp = pservice->dec_dev.hwregs[VPU_PP_HW_FUSE_CFG];\r
2011 \r
2012                                         if ((fuseRegPp >> DWL_PP_FUSE_E) & 0x01U) {\r
2013                                                 hwFuseSts.ppSupportFuse = 1;\r
2014                                                 /* check max. pp output width */\r
2015                                                 if (fuseRegPp & 0x8000U)\r
2016                                                         hwFuseSts.maxPpOutPicWidthFuse = 1920;\r
2017                                                 else if (fuseRegPp & 0x4000U)\r
2018                                                         hwFuseSts.maxPpOutPicWidthFuse = 1280;\r
2019                                                 else if (fuseRegPp & 0x2000U)\r
2020                                                         hwFuseSts.maxPpOutPicWidthFuse = 720;\r
2021                                                 else if (fuseRegPp & 0x1000U)\r
2022                                                         hwFuseSts.maxPpOutPicWidthFuse = 352;\r
2023                                                 else\r
2024                                                         hwFuseSts.maxPpOutPicWidthFuse = 352;\r
2025                                                 hwFuseSts.ppConfigFuse = fuseRegPp;\r
2026                                         } else {\r
2027                                                 hwFuseSts.ppSupportFuse = 0;\r
2028                                                 hwFuseSts.maxPpOutPicWidthFuse = 0;\r
2029                                                 hwFuseSts.ppConfigFuse = 0;\r
2030                                         }\r
2031                                 } else {\r
2032                                         hwFuseSts.ppSupportFuse = 0;\r
2033                                         hwFuseSts.maxPpOutPicWidthFuse = 0;\r
2034                                         hwFuseSts.ppConfigFuse = 0;\r
2035                                 }\r
2036 \r
2037                                 if (dec->maxDecPicWidth > hwFuseSts.maxDecPicWidthFuse)\r
2038                                         dec->maxDecPicWidth = hwFuseSts.maxDecPicWidthFuse;\r
2039                                 if (dec->maxPpOutPicWidth > hwFuseSts.maxPpOutPicWidthFuse)\r
2040                                         dec->maxPpOutPicWidth = hwFuseSts.maxPpOutPicWidthFuse;\r
2041                                 if (!hwFuseSts.h264SupportFuse) dec->h264Support = H264_NOT_SUPPORTED;\r
2042                                 if (!hwFuseSts.mpeg4SupportFuse) dec->mpeg4Support = MPEG4_NOT_SUPPORTED;\r
2043                                 if (!hwFuseSts.customMpeg4SupportFuse) dec->customMpeg4Support = MPEG4_CUSTOM_NOT_SUPPORTED;\r
2044                                 if (!hwFuseSts.jpegSupportFuse) dec->jpegSupport = JPEG_NOT_SUPPORTED;\r
2045                                 if ((dec->jpegSupport == JPEG_PROGRESSIVE) && !hwFuseSts.jpegProgSupportFuse)\r
2046                                         dec->jpegSupport = JPEG_BASELINE;\r
2047                                 if (!hwFuseSts.mpeg2SupportFuse) dec->mpeg2Support = MPEG2_NOT_SUPPORTED;\r
2048                                 if (!hwFuseSts.vc1SupportFuse) dec->vc1Support = VC1_NOT_SUPPORTED;\r
2049                                 if (!hwFuseSts.vp6SupportFuse) dec->vp6Support = VP6_NOT_SUPPORTED;\r
2050                                 if (!hwFuseSts.vp7SupportFuse) dec->vp7Support = VP7_NOT_SUPPORTED;\r
2051                                 if (!hwFuseSts.vp8SupportFuse) dec->vp8Support = VP8_NOT_SUPPORTED;\r
2052                                 if (!hwFuseSts.ppSupportFuse) dec->ppSupport = PP_NOT_SUPPORTED;\r
2053 \r
2054                                 /* check the pp config vs fuse status */\r
2055                                 if ((dec->ppConfig & 0xFC000000) && ((hwFuseSts.ppConfigFuse & 0xF0000000) >> 5)) {\r
2056                                         u32 deInterlace = ((dec->ppConfig & PP_DEINTERLACING) >> 25);\r
2057                                         u32 alphaBlend  = ((dec->ppConfig & PP_ALPHA_BLENDING) >> 24);\r
2058                                         u32 deInterlaceFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_DEINTERLACING) >> 25);\r
2059                                         u32 alphaBlendFuse  = (((hwFuseSts.ppConfigFuse >> 5) & PP_ALPHA_BLENDING) >> 24);\r
2060 \r
2061                                         if (deInterlace && !deInterlaceFuse) dec->ppConfig &= 0xFD000000;\r
2062                                         if (alphaBlend && !alphaBlendFuse) dec->ppConfig &= 0xFE000000;\r
2063                                 }\r
2064                                 if (!hwFuseSts.sorensonSparkSupportFuse) dec->sorensonSparkSupport = SORENSON_SPARK_NOT_SUPPORTED;\r
2065                                 if (!hwFuseSts.refBufSupportFuse)   dec->refBufSupport = REF_BUF_NOT_SUPPORTED;\r
2066                                 if (!hwFuseSts.rvSupportFuse)       dec->rvSupport = RV_NOT_SUPPORTED;\r
2067                                 if (!hwFuseSts.avsSupportFuse)      dec->avsSupport = AVS_NOT_SUPPORTED;\r
2068                                 if (!hwFuseSts.mvcSupportFuse)      dec->mvcSupport = MVC_NOT_SUPPORTED;\r
2069                         }\r
2070                 }\r
2071 \r
2072                 if (!cpu_is_rk3036()) {\r
2073                         configReg = pservice->enc_dev.hwregs[63];\r
2074                         enc->maxEncodedWidth = configReg & ((1 << 11) - 1);\r
2075                         enc->h264Enabled = (configReg >> 27) & 1;\r
2076                         enc->mpeg4Enabled = (configReg >> 26) & 1;\r
2077                         enc->jpegEnabled = (configReg >> 25) & 1;\r
2078                         enc->vsEnabled = (configReg >> 24) & 1;\r
2079                         enc->rgbEnabled = (configReg >> 28) & 1;\r
2080                         /*enc->busType = (configReg >> 20) & 15;\r
2081                         enc->synthesisLanguage = (configReg >> 16) & 15;\r
2082                         enc->busWidth = (configReg >> 12) & 15;*/\r
2083                         enc->reg_size = pservice->reg_size;\r
2084                         enc->reserv[0] = enc->reserv[1] = 0;\r
2085                 }\r
2086 \r
2087                 pservice->auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926() || soc_is_rk3288();\r
2088                 if (pservice->auto_freq) {\r
2089                         pr_info("vpu_service set to auto frequency mode\n");\r
2090                         atomic_set(&pservice->freq_status, VPU_FREQ_BUT);\r
2091                 }\r
2092 \r
2093                 pservice->bug_dec_addr = cpu_is_rk30xx();\r
2094         } else {\r
2095                 if (cpu_is_rk3036()  || cpu_is_rk312x())\r
2096                         dec->maxDecPicWidth = 1920;\r
2097                 else\r
2098                         dec->maxDecPicWidth = 4096;\r
2099                 /* disable frequency switch in hevc.*/\r
2100                 pservice->auto_freq = false;\r
2101         }\r
2102 }\r
2103 \r
2104 static irqreturn_t vdpu_irq(int irq, void *dev_id)\r
2105 {\r
2106         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2107         vpu_device *dev = &pservice->dec_dev;\r
2108         u32 raw_status;\r
2109         u32 irq_status;\r
2110 \r
2111         vcodec_enter_mode_nolock(pservice->dev_id, &pservice->reserved_mode);\r
2112 \r
2113         irq_status = raw_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2114 \r
2115         pr_debug("dec_irq\n");\r
2116 \r
2117         if (irq_status & DEC_INTERRUPT_BIT) {\r
2118                 pr_debug("dec_isr dec %x\n", irq_status);\r
2119                 if ((irq_status & 0x40001) == 0x40001)\r
2120                 {\r
2121                         do {\r
2122                                 irq_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2123                         } while ((irq_status & 0x40001) == 0x40001);\r
2124                 }\r
2125 \r
2126                 /* clear dec IRQ */\r
2127                 if (pservice->hw_info->hw_id != HEVC_ID)\r
2128                         writel(irq_status & (~DEC_INTERRUPT_BIT|DEC_BUFFER_EMPTY_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2129                 else\r
2130                         writel(0, dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2131                 atomic_add(1, &dev->irq_count_codec);\r
2132         }\r
2133 \r
2134         if (pservice->hw_info->hw_id != HEVC_ID) {\r
2135                 irq_status = readl(dev->hwregs + PP_INTERRUPT_REGISTER);\r
2136                 if (irq_status & PP_INTERRUPT_BIT) {\r
2137                         pr_debug("vdpu_isr pp  %x\n", irq_status);\r
2138                         /* clear pp IRQ */\r
2139                         writel(irq_status & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER);\r
2140                         atomic_add(1, &dev->irq_count_pp);\r
2141                 }\r
2142         }\r
2143 \r
2144         pservice->irq_status = raw_status;\r
2145 \r
2146         vcodec_exit_mode_nolock(pservice->dev_id, pservice->reserved_mode);\r
2147 \r
2148         return IRQ_WAKE_THREAD;\r
2149 }\r
2150 \r
2151 static irqreturn_t vdpu_isr(int irq, void *dev_id)\r
2152 {\r
2153         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2154         vpu_device *dev = &pservice->dec_dev;\r
2155 \r
2156         mutex_lock(&pservice->lock);\r
2157         if (atomic_read(&dev->irq_count_codec)) {\r
2158 #if VPU_SERVICE_SHOW_TIME\r
2159                 do_gettimeofday(&dec_end);\r
2160                 pr_info("dec task: %ld ms\n",\r
2161                         (dec_end.tv_sec  - dec_start.tv_sec)  * 1000 +\r
2162                         (dec_end.tv_usec - dec_start.tv_usec) / 1000);\r
2163 #endif\r
2164                 atomic_sub(1, &dev->irq_count_codec);\r
2165                 if (NULL == pservice->reg_codec) {\r
2166                         pr_err("error: dec isr with no task waiting\n");\r
2167                 } else {\r
2168                         reg_from_run_to_done(pservice, pservice->reg_codec);\r
2169                 }\r
2170         }\r
2171 \r
2172         if (atomic_read(&dev->irq_count_pp)) {\r
2173 \r
2174 #if VPU_SERVICE_SHOW_TIME\r
2175                 do_gettimeofday(&pp_end);\r
2176                 printk("pp  task: %ld ms\n",\r
2177                         (pp_end.tv_sec  - pp_start.tv_sec)  * 1000 +\r
2178                         (pp_end.tv_usec - pp_start.tv_usec) / 1000);\r
2179 #endif\r
2180 \r
2181                 atomic_sub(1, &dev->irq_count_pp);\r
2182                 if (NULL == pservice->reg_pproc) {\r
2183                         pr_err("error: pp isr with no task waiting\n");\r
2184                 } else {\r
2185                         reg_from_run_to_done(pservice, pservice->reg_pproc);\r
2186                 }\r
2187         }\r
2188         try_set_reg(pservice);\r
2189         mutex_unlock(&pservice->lock);\r
2190         return IRQ_HANDLED;\r
2191 }\r
2192 \r
2193 static irqreturn_t vepu_irq(int irq, void *dev_id)\r
2194 {\r
2195         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2196         vpu_device *dev = &pservice->enc_dev;\r
2197         u32 irq_status;\r
2198 \r
2199         vcodec_enter_mode_nolock(pservice->dev_id,  &pservice->reserved_mode);\r
2200         irq_status= readl(dev->hwregs + ENC_INTERRUPT_REGISTER);\r
2201 \r
2202         pr_debug("vepu_irq irq status %x\n", irq_status);\r
2203 \r
2204 #if VPU_SERVICE_SHOW_TIME\r
2205         do_gettimeofday(&enc_end);\r
2206         pr_info("enc task: %ld ms\n",\r
2207                 (enc_end.tv_sec  - enc_start.tv_sec)  * 1000 +\r
2208                 (enc_end.tv_usec - enc_start.tv_usec) / 1000);\r
2209 #endif\r
2210         if (likely(irq_status & ENC_INTERRUPT_BIT)) {\r
2211                 /* clear enc IRQ */\r
2212                 writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER);\r
2213                 atomic_add(1, &dev->irq_count_codec);\r
2214         }\r
2215 \r
2216         pservice->irq_status = irq_status;\r
2217 \r
2218         vcodec_exit_mode_nolock(pservice->dev_id, pservice->reserved_mode);\r
2219 \r
2220         return IRQ_WAKE_THREAD;\r
2221 }\r
2222 \r
2223 static irqreturn_t vepu_isr(int irq, void *dev_id)\r
2224 {\r
2225         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2226         vpu_device *dev = &pservice->enc_dev;\r
2227 \r
2228         mutex_lock(&pservice->lock);\r
2229         if (atomic_read(&dev->irq_count_codec)) {\r
2230                 atomic_sub(1, &dev->irq_count_codec);\r
2231                 if (NULL == pservice->reg_codec) {\r
2232                         pr_err("error: enc isr with no task waiting\n");\r
2233                 } else {\r
2234                         reg_from_run_to_done(pservice, pservice->reg_codec);\r
2235                 }\r
2236         }\r
2237         try_set_reg(pservice);\r
2238         mutex_unlock(&pservice->lock);\r
2239         return IRQ_HANDLED;\r
2240 }\r
2241 \r
2242 static int __init vcodec_service_init(void)\r
2243 {\r
2244         int ret;\r
2245 \r
2246         if ((ret = platform_driver_register(&vcodec_driver)) != 0) {\r
2247                 pr_err("Platform device register failed (%d).\n", ret);\r
2248                 return ret;\r
2249         }\r
2250 \r
2251 #ifdef CONFIG_DEBUG_FS\r
2252         vcodec_debugfs_init();\r
2253 #endif\r
2254 \r
2255         return ret;\r
2256 }\r
2257 \r
2258 static void __exit vcodec_service_exit(void)\r
2259 {\r
2260 #ifdef CONFIG_DEBUG_FS\r
2261         vcodec_debugfs_exit();\r
2262 #endif\r
2263 \r
2264         platform_driver_unregister(&vcodec_driver);\r
2265 }\r
2266 \r
2267 module_init(vcodec_service_init);\r
2268 module_exit(vcodec_service_exit);\r
2269 \r
2270 #ifdef CONFIG_DEBUG_FS\r
2271 #include <linux/seq_file.h>\r
2272 \r
2273 static int vcodec_debugfs_init()\r
2274 {\r
2275         parent = debugfs_create_dir("vcodec", NULL);\r
2276         if (!parent)\r
2277                 return -1;\r
2278 \r
2279         return 0;\r
2280 }\r
2281 \r
2282 static void vcodec_debugfs_exit()\r
2283 {\r
2284         debugfs_remove(parent);\r
2285 }\r
2286 \r
2287 static struct dentry* vcodec_debugfs_create_device_dir(char *dirname, struct dentry *parent)\r
2288 {\r
2289         return debugfs_create_dir(dirname, parent);\r
2290 }\r
2291 \r
2292 static int debug_vcodec_show(struct seq_file *s, void *unused)\r
2293 {\r
2294         struct vpu_service_info *pservice = s->private;\r
2295         unsigned int i, n;\r
2296         vpu_reg *reg, *reg_tmp;\r
2297         vpu_session *session, *session_tmp;\r
2298 \r
2299         mutex_lock(&pservice->lock);\r
2300         vpu_service_power_on(pservice);\r
2301         if (pservice->hw_info->hw_id != HEVC_ID) {\r
2302                 seq_printf(s, "\nENC Registers:\n");\r
2303                 n = pservice->enc_dev.iosize >> 2;\r
2304                 for (i = 0; i < n; i++) {\r
2305                         seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->enc_dev.hwregs + i));\r
2306                 }\r
2307         }\r
2308         seq_printf(s, "\nDEC Registers:\n");\r
2309         n = pservice->dec_dev.iosize >> 2;\r
2310         for (i = 0; i < n; i++)\r
2311                 seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
2312 \r
2313         seq_printf(s, "\nvpu service status:\n");\r
2314         list_for_each_entry_safe(session, session_tmp, &pservice->session, list_session) {\r
2315                 seq_printf(s, "session pid %d type %d:\n", session->pid, session->type);\r
2316                 /*seq_printf(s, "waiting reg set %d\n");*/\r
2317                 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {\r
2318                         seq_printf(s, "waiting register set\n");\r
2319                 }\r
2320                 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {\r
2321                         seq_printf(s, "running register set\n");\r
2322                 }\r
2323                 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {\r
2324                         seq_printf(s, "done    register set\n");\r
2325                 }\r
2326         }\r
2327         mutex_unlock(&pservice->lock);\r
2328 \r
2329         return 0;\r
2330 }\r
2331 \r
2332 static int debug_vcodec_open(struct inode *inode, struct file *file)\r
2333 {\r
2334         return single_open(file, debug_vcodec_show, inode->i_private);\r
2335 }\r
2336 \r
2337 #endif\r
2338 \r
2339 #if HEVC_TEST_ENABLE & defined(CONFIG_ION_ROCKCHIP)\r
2340 #include "hevc_test_inc/pps_00.h"\r
2341 #include "hevc_test_inc/register_00.h"\r
2342 #include "hevc_test_inc/rps_00.h"\r
2343 #include "hevc_test_inc/scaling_list_00.h"\r
2344 #include "hevc_test_inc/stream_00.h"\r
2345 \r
2346 #include "hevc_test_inc/pps_01.h"\r
2347 #include "hevc_test_inc/register_01.h"\r
2348 #include "hevc_test_inc/rps_01.h"\r
2349 #include "hevc_test_inc/scaling_list_01.h"\r
2350 #include "hevc_test_inc/stream_01.h"\r
2351 \r
2352 #include "hevc_test_inc/cabac.h"\r
2353 \r
2354 extern struct ion_client *rockchip_ion_client_create(const char * name);\r
2355 \r
2356 static struct ion_client *ion_client = NULL;\r
2357 u8* get_align_ptr(u8* tbl, int len, u32 *phy)\r
2358 {\r
2359         int size = (len+15) & (~15);\r
2360         struct ion_handle *handle;\r
2361         u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
2362 \r
2363         if (ion_client == NULL)\r
2364                 ion_client = rockchip_ion_client_create("vcodec");\r
2365 \r
2366         handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
2367 \r
2368         ptr = ion_map_kernel(ion_client, handle);\r
2369 \r
2370         ion_phys(ion_client, handle, phy, &size);\r
2371 \r
2372         memcpy(ptr, tbl, len);\r
2373 \r
2374         return ptr;\r
2375 }\r
2376 \r
2377 u8* get_align_ptr_no_copy(int len, u32 *phy)\r
2378 {\r
2379         int size = (len+15) & (~15);\r
2380         struct ion_handle *handle;\r
2381         u8 *ptr;\r
2382 \r
2383         if (ion_client == NULL)\r
2384                 ion_client = rockchip_ion_client_create("vcodec");\r
2385 \r
2386         handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
2387 \r
2388         ptr = ion_map_kernel(ion_client, handle);\r
2389 \r
2390         ion_phys(ion_client, handle, phy, &size);\r
2391 \r
2392         return ptr;\r
2393 }\r
2394 \r
2395 #define TEST_CNT    2\r
2396 static int hevc_test_case0(vpu_service_info *pservice)\r
2397 {\r
2398         vpu_session session;\r
2399         vpu_reg *reg;\r
2400         unsigned long size = 272;//sizeof(register_00); // registers array length\r
2401         int testidx = 0;\r
2402         int ret = 0;\r
2403 \r
2404         u8 *pps_tbl[TEST_CNT];\r
2405         u8 *register_tbl[TEST_CNT];\r
2406         u8 *rps_tbl[TEST_CNT];\r
2407         u8 *scaling_list_tbl[TEST_CNT];\r
2408         u8 *stream_tbl[TEST_CNT];\r
2409 \r
2410         int stream_size[2];\r
2411         int pps_size[2];\r
2412         int rps_size[2];\r
2413         int scl_size[2];\r
2414         int cabac_size[2];\r
2415 \r
2416         u32 phy_pps;\r
2417         u32 phy_rps;\r
2418         u32 phy_scl;\r
2419         u32 phy_str;\r
2420         u32 phy_yuv;\r
2421         u32 phy_ref;\r
2422         u32 phy_cabac;\r
2423 \r
2424         volatile u8 *stream_buf;\r
2425         volatile u8 *pps_buf;\r
2426         volatile u8 *rps_buf;\r
2427         volatile u8 *scl_buf;\r
2428         volatile u8 *yuv_buf;\r
2429         volatile u8 *cabac_buf;\r
2430         volatile u8 *ref_buf;\r
2431 \r
2432         u8 *pps;\r
2433         u8 *yuv[2];\r
2434         int i;\r
2435 \r
2436         pps_tbl[0] = pps_00;\r
2437         pps_tbl[1] = pps_01;\r
2438 \r
2439         register_tbl[0] = register_00;\r
2440         register_tbl[1] = register_01;\r
2441 \r
2442         rps_tbl[0] = rps_00;\r
2443         rps_tbl[1] = rps_01;\r
2444 \r
2445         scaling_list_tbl[0] = scaling_list_00;\r
2446         scaling_list_tbl[1] = scaling_list_01;\r
2447 \r
2448         stream_tbl[0] = stream_00;\r
2449         stream_tbl[1] = stream_01;\r
2450 \r
2451         stream_size[0] = sizeof(stream_00);\r
2452         stream_size[1] = sizeof(stream_01);\r
2453 \r
2454         pps_size[0] = sizeof(pps_00);\r
2455         pps_size[1] = sizeof(pps_01);\r
2456 \r
2457         rps_size[0] = sizeof(rps_00);\r
2458         rps_size[1] = sizeof(rps_01);\r
2459 \r
2460         scl_size[0] = sizeof(scaling_list_00);\r
2461         scl_size[1] = sizeof(scaling_list_01);\r
2462 \r
2463         cabac_size[0] = sizeof(Cabac_table);\r
2464         cabac_size[1] = sizeof(Cabac_table);\r
2465 \r
2466         /* create session */\r
2467         session.pid = current->pid;\r
2468         session.type = VPU_DEC;\r
2469         INIT_LIST_HEAD(&session.waiting);\r
2470         INIT_LIST_HEAD(&session.running);\r
2471         INIT_LIST_HEAD(&session.done);\r
2472         INIT_LIST_HEAD(&session.list_session);\r
2473         init_waitqueue_head(&session.wait);\r
2474         atomic_set(&session.task_running, 0);\r
2475         list_add_tail(&session.list_session, &pservice->session);\r
2476 \r
2477         yuv[0] = get_align_ptr_no_copy(256*256*2, &phy_yuv);\r
2478         yuv[1] = get_align_ptr_no_copy(256*256*2, &phy_ref);\r
2479 \r
2480         while (testidx < TEST_CNT) {\r
2481                 /* create registers */\r
2482                 reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
2483                 if (NULL == reg) {\r
2484                         pr_err("error: kmalloc fail in reg_init\n");\r
2485                         return -1;\r
2486                 }\r
2487 \r
2488                 if (size > pservice->reg_size) {\r
2489                         printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
2490                         size = pservice->reg_size;\r
2491                 }\r
2492                 reg->session = &session;\r
2493                 reg->type = session.type;\r
2494                 reg->size = size;\r
2495                 reg->freq = VPU_FREQ_DEFAULT;\r
2496                 reg->reg = (unsigned long *)&reg[1];\r
2497                 INIT_LIST_HEAD(&reg->session_link);\r
2498                 INIT_LIST_HEAD(&reg->status_link);\r
2499 \r
2500                 /* TODO: stuff registers */\r
2501                 memcpy(&reg->reg[0], register_tbl[testidx], /*sizeof(register_00)*/ 176);\r
2502 \r
2503                 stream_buf = get_align_ptr(stream_tbl[testidx], stream_size[testidx], &phy_str);\r
2504                 pps_buf = get_align_ptr(pps_tbl[0], pps_size[0], &phy_pps);\r
2505                 rps_buf = get_align_ptr(rps_tbl[testidx], rps_size[testidx], &phy_rps);\r
2506                 scl_buf = get_align_ptr(scaling_list_tbl[testidx], scl_size[testidx], &phy_scl);\r
2507                 cabac_buf = get_align_ptr(Cabac_table, cabac_size[testidx], &phy_cabac);\r
2508 \r
2509                 pps = pps_buf;\r
2510 \r
2511                 /* TODO: replace reigster address */\r
2512                 for (i=0; i<64; i++) {\r
2513                         u32 scaling_offset;\r
2514                         u32 tmp;\r
2515 \r
2516                         scaling_offset = (u32)pps[i*80+74];\r
2517                         scaling_offset += (u32)pps[i*80+75] << 8;\r
2518                         scaling_offset += (u32)pps[i*80+76] << 16;\r
2519                         scaling_offset += (u32)pps[i*80+77] << 24;\r
2520 \r
2521                         tmp = phy_scl + scaling_offset;\r
2522 \r
2523                         pps[i*80+74] = tmp & 0xff;\r
2524                         pps[i*80+75] = (tmp >> 8) & 0xff;\r
2525                         pps[i*80+76] = (tmp >> 16) & 0xff;\r
2526                         pps[i*80+77] = (tmp >> 24) & 0xff;\r
2527                 }\r
2528 \r
2529                 printk("%s %d, phy stream %08x, phy pps %08x, phy rps %08x\n",\r
2530                         __func__, __LINE__, phy_str, phy_pps, phy_rps);\r
2531 \r
2532                 reg->reg[1] = 0x21;\r
2533                 reg->reg[4] = phy_str;\r
2534                 reg->reg[5] = ((stream_size[testidx]+15)&(~15))+64;\r
2535                 reg->reg[6] = phy_cabac;\r
2536                 reg->reg[7] = testidx?phy_ref:phy_yuv;\r
2537                 reg->reg[42] = phy_pps;\r
2538                 reg->reg[43] = phy_rps;\r
2539                 for (i = 10; i <= 24; i++)\r
2540                         reg->reg[i] = phy_yuv;\r
2541 \r
2542                 mutex_lock(&pservice->lock);\r
2543                 list_add_tail(&reg->status_link, &pservice->waiting);\r
2544                 list_add_tail(&reg->session_link, &session.waiting);\r
2545                 mutex_unlock(&pservice->lock);\r
2546 \r
2547                 printk("%s %d %p\n", __func__, __LINE__, pservice);\r
2548 \r
2549                 /* stuff hardware */\r
2550                 try_set_reg(pservice);\r
2551 \r
2552                 /* wait for result */\r
2553                 ret = wait_event_timeout(session.wait, !list_empty(&session.done), VPU_TIMEOUT_DELAY);\r
2554                 if (!list_empty(&session.done)) {\r
2555                         if (ret < 0)\r
2556                                 pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session.pid, ret);\r
2557                         ret = 0;\r
2558                 } else {\r
2559                         if (unlikely(ret < 0)) {\r
2560                                 pr_err("error: pid %d wait task ret %d\n", session.pid, ret);\r
2561                         } else if (0 == ret) {\r
2562                                 pr_err("error: pid %d wait %d task done timeout\n", session.pid, atomic_read(&session.task_running));\r
2563                                 ret = -ETIMEDOUT;\r
2564                         }\r
2565                 }\r
2566                 if (ret < 0) {\r
2567                         int task_running = atomic_read(&session.task_running);\r
2568                         int n;\r
2569                         mutex_lock(&pservice->lock);\r
2570                         vpu_service_dump(pservice);\r
2571                         if (task_running) {\r
2572                                 atomic_set(&session.task_running, 0);\r
2573                                 atomic_sub(task_running, &pservice->total_running);\r
2574                                 printk("%d task is running but not return, reset hardware...", task_running);\r
2575                                 vpu_reset(pservice);\r
2576                                 printk("done\n");\r
2577                         }\r
2578                         vpu_service_session_clear(pservice, &session);\r
2579                         mutex_unlock(&pservice->lock);\r
2580 \r
2581                         printk("\nDEC Registers:\n");\r
2582                         n = pservice->dec_dev.iosize >> 2;\r
2583                         for (i=0; i<n; i++)\r
2584                                 printk("\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
2585 \r
2586                         pr_err("test index %d failed\n", testidx);\r
2587                         break;\r
2588                 } else {\r
2589                         pr_info("test index %d success\n", testidx);\r
2590 \r
2591                         vpu_reg *reg = list_entry(session.done.next, vpu_reg, session_link);\r
2592 \r
2593                         for (i=0; i<68; i++) {\r
2594                                 if (i % 4 == 0)\r
2595                                         printk("%02d: ", i);\r
2596                                 printk("%08x ", reg->reg[i]);\r
2597                                 if ((i+1) % 4 == 0)\r
2598                                         printk("\n");\r
2599                         }\r
2600 \r
2601                         testidx++;\r
2602                 }\r
2603 \r
2604                 reg_deinit(pservice, reg);\r
2605         }\r
2606 \r
2607         return 0;\r
2608 }\r
2609 \r
2610 #endif\r
2611 \r